node. JS application: KOA2 using JWT for authentication

Source: Internet
Author: User
Tags auth error handling
Objective

In the development of back-end separation, when data interaction is done through Restful APIs, it is easy for others to get and invoke these APIs if the API is not protected. So how to authenticate the server side?

The JSON Web Token is abbreviated as JWT, which defines a concise, self-contained method for communicating information securely between both parties in a JSON object. JWT can be signed using the HMAC algorithm or the public key pair of RSA.

It seems to be the same as the real one, so how do you go about certification?

First user login, enter the user name and password after the request server login interface, the server to verify the user name password is correct, generate token and return to the front end, the front-end storage token, and in the subsequent request to the token in the request header to the server, the server verify token valid, return the correct data.

Since the server side uses the KOA2 framework for development, in addition to the use of the Jsonwebtoken library, but also to use a KOA-JWT middleware, the middleware for KOA on the Jsonwebtoken is encapsulated, more convenient to use. Let's see how it's used.

Generate tokens

A route is registered here to /login obtain tokens when the user logs in.

  const Router = require (' Koa-router ') (), const JWT = require (' Jsonwebtoken '); Const Usermodel = Require ('..    /models/usermodel.js '); Router.post ('/login ', async (CTX) = {Const DATA = Ctx.request.body;            if (!data.name | |!data.password) {return ctx.body = {code: ' 000002 ', Data:null, msg: ' argument not valid '}} const result = await Usermodel.findone ({name:data.name, PASSWORD:DATA.PASSW         ORD}) if (result!== null) {Const TOKEN = jwt.sign ({name:result.name, _id:result._id        }, ' My_token ', {expiresin: ' 2h '}); return ctx.body = {code: ' 000001 ', Data:token, msg: ' Login successful '}}else{re Turn ctx.body = {code: ' 000002 ', Data:null, msg: ' Username or password error '}}}); Module.expo RTS = router;  

After verifying that the user name password is correct, call Jsonwebtoken's sign () method to generate tokens, receive three parameters, the first is the load, used to encode the data stored in the token, but also to verify the token can be obtained after the data; the second one is the key, its own definition, The same key is required to decode the authentication, and the third is the options to set the token expiration time.

Get token

The next step is to get token from the front end, where the request is made using Axios in Vue.js and the token is saved to localstorage after the request succeeds. After the successful login, but also to save the current time, in addition to determine whether the token exists, you can also easily determine whether the current token is expired, if expired, skip the login page

submit(){    axios.post('/login', {        name: this.username,        password: this.password    }).then(res => {        if(res.code === '000001'){            localStorage.setItem('token', res.data);            localStorage.setItem('token_exp', new Date().getTime());            this.$router.push('/');        }else{            alert(res.msg);        }    })}

Then, when requesting the server-side API, pass the token in the request header to the server for verification. Each request to obtain token in the localstorage, this is cumbersome, the use of the Axios request interceptor, each request has been taken token put into headers operation.

axios.interceptors.request.use(config => {    const token = localStorage.getItem('token');    config.headers.common['Authorization'] = 'Bearer ' + token;    return config;})
Verify token

KOA-JWT Middleware for validation and easy to use

const koa = require('koa');const koajwt = require('koa-jwt');const app = new koa();// 错误处理app.use((ctx, next) => {    return next().catch((err) => {        if(err.status === 401){            ctx.status = 401;            ctx.body = 'Protected resource, use Authorization header to get access\n';        }else{            throw err;        }    })})app.use(koajwt({    secret: 'my_token'}).unless({    path: [/\/user\/login/]}));

Using App.use to invoke the middleware and pass in the key {secret: 'my_token'} , unless can specify which URLs do not need token validation. Token validation fails with a 401 error, so error handling needs to be added, and it will not be executed until App.use (KOAJWT ()) is placed.

If no token or token expires at the time of the request, 401 is returned.

Parsing KOA-JWT

We used the Jsonwebtoken sign () method to generate tokens, so what KOA-JWT did to help us verify tokens.

Resolvers/auth-header.js
module.exports = function resolveAuthorizationHeader(ctx, opts) {    if (!ctx.header || !ctx.header.authorization) {        return;    }    const parts = ctx.header.authorization.split(' ');    if (parts.length === 2) {        const scheme = parts[0];        const credentials = parts[1];        if (/^Bearer$/i.test(scheme)) {            return credentials;        }    }    if (!opts.passthrough) {        ctx.throw(401, 'Bad Authorization header format. Format is "Authorization: Bearer <token>"');    }};

In Auth-header.js, determine if there is a authorization in the request header, and if so, separate the token from the authorization. If there is no authorization, it means that the client does not pass tokens to the server, which throws a 401 error state.

Verify.js
const jwt = require('jsonwebtoken');module.exports = (...args) => {    return new Promise((resolve, reject) => {        jwt.verify(...args, (error, decoded) => {            error ? reject(error) : resolve(decoded);        });    });};

In Verify.js, the return result is validated using the Verify () method provided by Jsonwebtoken. Jsonwebtoken's sign () method generates tokens, while the Verify () method is used to authenticate and parse tokens. If token is not valid, it will be validated in this method.

Index.js
const decodedToken = await verify(token, secret, opts);if (isRevoked) {    const tokenRevoked = await isRevoked(ctx, decodedToken, token);    if (tokenRevoked) {        throw new Error('Token revoked');    }}ctx.state[key] = decodedToken;  // 这里的key = 'user'if (tokenKey) {    ctx.state[tokenKey] = token;}

In Index.js, call the method of Verify.js to verify and parse token, get the data of sign () above, {name: result.name, _id: result._id} and assign value to ctx.state.user , in the controller can directly through to ctx.state.user get name and _id .

Security
    • If the JWT's encryption key is compromised, it is possible to generate tokens from the key and arbitrarily request the API. Therefore, the key must never exist in the front-end code, or it can easily be found.
    • In HTTP requests, tokens are placed in the header, and it is easy for the intermediary to grab the data in the header by grabbing the package tool. And HTTPS even can be caught, but it is encrypted transmission, so also can not get token, it will be relatively safe.
Summarize

This is the basic process of JWT, which may not be the perfect one, but it's enough for most logins.
The above code may not be specific enough, here is an example using Koa + Mongoose + vue.js implementation: Jwt-demo, can be used as a reference.

More articles: Lin-xin/blog

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.