Authentication and Authorization

Authentication

Authentication is how to prove that you are yourself, and generally the way to prove that you are yourself is through id cards; Authentication on the Internet usually uses a username and password to prove that you are yourself. Common identity authentication methods are as follows:

  1. Login with username and password
  2. Email sends login link
  3. Mobile phone number Receiving verification code

Authorization

For example, when you install a mobile application, the application will apply for permission. If you agree to this permission application process, it is called authorization. Similarly, in OAuth, the licensee gains certain permissions. Oauth is commonly used by:

  1. qq
  2. WeChat
  3. weibo
  4. facebook
  5. twitter

The relationship between authorization and authentication

Authorization does not necessarily require authentication. For example: When you have a key, you can open the door, you are not necessarily the owner of the house. Oauth authorization on the Internet is usually granted by token.

OAuth

The concept of the request

OAuth is a standard authorization method in the Internet industry. Each company implements its own OAuth authentication and authorization process according to this set of standards, and third parties need to use OAuth to access this process. OAuth is currently available in two versions:

  1. 1. X (deprecated)
  2. 2. X (popular)

Role understanding

There are several roles in the OAuth third-party authentication and authorization process:

  1. Client: browser
  2. Server side: Develop the corresponding server side of this website
  3. Authorized server: provider of OAuth third-party access services, such as QQ and wechat.

Another way of saying this is that the client and the server can be combined as the authorized party. If you do a pure client-side OAuth access, then you can also do without the server, but this access method is not very secure.

Authorization way

At present, there are many ways of OAuth authorization in the industry, among which the most important ones are the following:

  1. Authorization Code (most commonly used)
  2. Refresh Token: Applies for a new authorization Token from the OAuth access party if the authorization Token has not expired
  3. Device Code: Applies to third-party access of smart TVS.
  4. Password: use the API exposed by OAuth to log in with the user name and Password of this website. (Not recommended, trust and security, generally used for internal login)
  5. Implicit: Obsolete
  6. Client Credentials

Authorization Code

The process for accessing OAuth through authentication and authorization codes is as follows:

  1. The client initiates a requestredirectGo to OAuth access party and attachclient_id
  2. The user inredirectEnter your username and password on the next web site
  3. After a successful login, the OAuth access party returns one to the servercode.
  4. Server side getcodeAfter that, take itclient_secretandcodeApply to OAuth access party for accessToken
  5. After obtaining the Token, the server enters the authorization window
  6. If the authorization succeeds, go to the client website.

Github OAuth Third-party access

Registered making request

url:https://github.com/settings/apps

  1. Log in making
  2. Click your picture, Setting
  3. Click on the developer setting
  4. New request App

Note: The URL of a HomePage should be filled with the root path of the local project before the project is launched and the domain name after the project is launched. Similarly Authorization callback URL before online fill out http://localhost:3000/auth, the online after fill in the domain name + / auth. After successful registration, a client_id and client_secret values appear, which are very important. It needs to be saved in a project file

OAuth field description

Jump field

Url: https://github.com/login/oauth/authorize param:

  1. Client_id: client_id is the client_id at registration time
  2. Scope: indicates the desired permission scope
  3. Redirect_uri: specifies the address to be redirected to the project after authorization. It must be the same as the address used when registering Github OAuth Appredirect uriThe same
  4. Login: the specific account used to login and authorize applications. If you have logged in to github from that site and authorized it, you will not need to login to OAuth for this request.
  5. State: random string that cannot be guessed. It is used to prevent cross-site request forgery attacks.
  6. Allow_signup: Whether to provide the option to register GitHub to unauthenticated users in the OAuth process. The default value is true. False Used when the policy forbids registration.

The request token

Url: https://github.com/login/oauth/access_token param:

  1. Client_id: Required, specifying the token user
  2. Client_secret: Required, which indicates the token user
  3. Code: required, indicating that the user is authorized
  4. Redirect_uri: same as above
  5. State: same as above

Requesting user information

Url: https://api.github.com/user the header:

  1. Authorization: Specifies the access_token returned during access_token requesttoken +access_token

Github OAuth Authorization how to ensure security

strategy

  1. One-time code: The code returned after the authorization is successful is one-time. After the access_token request is made, the last code is invalid.
  2. Id + secret authentication: When requesting access_token, not only code is required, but also client_ID and client_secret are required. Even if the code has been leaked, as long as the other party does not have these two fields, it cannot obtain our access_token.
  3. Redirect_uri: This field is the URI returned when the request is made, if the field matches github’sAuthorization callback URLIf not, an error will be reported.

Use cookies and sessions to store tokens

After the user completes the OAuth process, the token is saved in the cookie and session, so that the user does not need to perform OAuth authentication and authorization every time he switches pages.

Store the cookies

How the KOA framework stores cookies:

server.use(async (ctx, next) => {
  ctx.cookies.set('id', id, {
    httpOnly: true
  });
  await next()
})
Copy the code

Store the session

const session = require('koa-session');
// Encrypt the cookie. The encrypted ciphertext is JWT
server.keys = ['ainuo develop github apps'];
const SESSION_CONFIG = {
  // key is the name of the stored field
  key: 'jid'.// When no store is configured, sessions are stored in cookies as JWT
   // store:
};
// Use session middleware
server.use(session(SESSION_CONFIG, server));
// Generally we expose a separate interface for setting up sessions.
router.get('/set/user'.async ctx => {
    / / set the session
  ctx.session.user = {
    name: 'ainuo'.age: 18
  };
  ctx.body = 'set session success'
});
Copy the code

Store the token in Redis

Creating a Store object

This object was created to integrate Redis into KOS-session and to simplify redis operations

function getRedisSessionId(sessionId) {
  return `ssid:${sessionId}`
}

module.exports = class RedisSessionStore {
  constructor(client) {
    this.client = client
  }

  // Get session data stored in Redis according to sessionId
  async get(sessionId) {
    console.log('get session', sessionId);
    const id = getRedisSessionId(sessionId);
    const data = await this.client.get(id);
    if(! data) {return null
    }
    try {
      return JSON.parse(data);
    } catch (e) {
      console.log(e)
    }
  }

  // Store session data to Redis
  async set(sessionId, sessionValue, lifetime) {
    console.log('set session', sessionId);
    const id = getRedisSessionId(sessionId);
    if (typeof lifetime === "number") {
      lifetime = Math.ceil(lifetime / 1000);
    }
    try {
      const sessionStr = JSON.stringify(sessionValue);
      if (lifetime) {
        await this.client.setex(id, lifetime, sessionStr)
      } else {
        await this.client.set(id, sessionStr)
      }
    } catch (e) {
      console.log(e)
    }
  }

  // Delete a session from Redis
  async destroy(sessionId) {
    console.log('destroy session', sessionId);
    const id = getRedisSessionId(sessionId);
    await this.client.del(id)
  }
}
Copy the code

Koa-session connects to the Redis database

const Redis = require('ioredis');
// Some configuration can be passed in
const client = new Redis({});
server.keys = ['ainuo develop github apps'];
const SESSION_CONFIG = {
  key: 'jid'.// When no store is configured, sessions are stored in cookies as JWT
   store: new RedisSessionStore(client),
   // maxAge: 10 * 1000,
};
// Encrypt the session on the server
server.use(session(SESSION_CONFIG, server));
// Delete ssiD: XXX from redis database when deleting session
router.get('/del/user'.async ctx => {
    / / set the session
    ctx.session = null;
    ctx.body = 'del session success'
});
// Add session to redis database when setting session
router.get('/set/user'.async ctx => {
  / / set the session
  ctx.session.user = {
    name: 'ainuo'.age: 18
  };
  ctx.body = 'set session success'
});
Copy the code

Koa connects to Github OAuth

//config,js
module.exports = {
  github: {
    client_id: 'xxxx'.client_secret: 'xxxx'.request_token_url: 'https://github.com/login/oauth/access_token'.auth_url: 'https://github.com/login/oauth/authorize'.scope: 'user'.user_info_url: 'https://api.github.com/user'}};// auth.js
const axios = require('axios');
const {github} = require('.. /config');
const {client_id, client_secret, request_token_url} = github;
module.exports = function (server) {
  server.use(async (ctx, next) => {
    if (ctx.path === '/auth') {
      const code = ctx.query.code;
      if (code) {
        // Initiate a request to access_token
        const res = await axios({
          method: 'POST'.url: request_token_url,
          data: {
            client_id,
            client_secret,
            code
          },
          headers: {
            Accept: 'application/json',}});if (res.status === 200 && !(res.data && res.data.error)) {
          ctx.session.githubAuth = res.data;
          const {access_token, token_type} = res.data;
          // Request user information
          const userInfoRes = await axios({
            method: 'GET'.url: github.user_info_url,
            headers: {
              Authorization: `token ${access_token}`}});// Store user information to session and redis
          ctx.session.userInfo = userInfoRes.data;
          // Redirect to the home page after the authorization process is complete
          ctx.redirect('/');
        } else {
          const errorMsg = res.data && res.data.error;
          ctx.body = `request token failed ${errorMsg}`}}else {
        ctx.body = 'code not exist'; }}else {
      await next()
    }
  })
};

// server.js
// Encrypt the session on the server
server.use(session(SESSION_CONFIG, server));
Github oauth login
auth(server);
Copy the code

The project address