github Authorized Logon Tutorial and How to Design User Table for Third Party Authorized Logon

Keywords: Javascript github Database JSON Session

Requirement: If you want to comment on an article on the website, and the comment is for users to register and log in, how can you avoid this troublesome step? The answer is to login through third-party authorization. This article describes the github Authorized Login tutorial.

Effect Experience Address: http://biaochenxuying.cn

1. github third-party authorized login tutorial

Let's first look at the complete flow chart of github authorization 1:

Or look at the complete flow chart of github authorization 2:

1.1 Application for an OAuth App

First we have to log on to github and apply for an OAuth App. The steps are as follows:

  1. Log on to github
  2. Click Settings - > Developer Settings on the right side of New OAuth App under the Avatar
  3. Fill in the relevant configuration of app application, there are two key configuration items
  4. Homepage URL This is the subsequent authorized URL, which you can understand as the root directory address of your project.
  5. Authorization callback URL after the successful authorization callback address, this is very important, which is given to you when you get the authorization code callback address.

The concrete practice is as follows:

    1. First log in to your GitHub account, then click on Settings.

    1. Click OAuth Apps, Register a new application or New OAuth App.

    1. Enter information.

    1. Application Information Description.

The process can also see the official documentation of GitHub settings.- Registering OAuth Apps.

1.2 Authorized Logon

github document: building-oauth-apps/authorizing-oauth-apps

The main three steps of authorizing login are as follows:

In this practice, the project uses front-end and back-end separation, so the first step is implemented in the front-end, while the second and third steps are implemented in the back-end, because the parameter Client_secret is needed in the second interface, and the user information obtained in the third step is saved in the back-end to the database.

1.3. Code implementation

1.3.1 front-end

The author's project technology is react.

// config.js

// Please fill in the true content of your application for OAuth App at ***
 const config = {
  'oauth_uri': 'https://github.com/login/oauth/authorize',
  'redirect_uri': 'http://biaochenxuying.cn/',
  'client_id': '*****',
  'client_secret': '*******',
};

// Local Development Environment
if (process.env.NODE_ENV === 'development') {
  config.redirect_uri = "http://localhost:3001/"
  config.client_id = "******"
  config.client_secret = "*****"
}
export default config; 

Code reference config.js

The redirect_uri callback address is in a separate environment, so I've built two new OAuth App s, one for online production and one for local development.

Generally speaking, the login page should be independent, corresponding to the corresponding routing / login, but the login component of this project is a sub-component of nav component, nav is a global component, so the callback address is written. http://biaochenxuying.cn/.

  • So click jump is written in login.js.
  • After authorization, the code is written in nav.js
  • After nav.js gets the code value, it requests the back-end interface, which returns user information.
  • When the back end gets the code, it also goes to github to get access_token, and then according to access_token to get github to get the user's information.
// login.js

// html
<Button
    style={{ width: '100%' }}
    onClick={this.handleOAuth} >
      github Authorized login
</Button>

// js
handleOAuth(){
    // Save page links before authorization
    window.localStorage.preventHref = window.location.href
    // window.location.href = 'https://github.com/login/oauth/authorize?client_id=***&redirect_uri=http://biaochenxuying.cn/'
    window.location.href = `${config.oauth_uri}?client_id=${config.client_id}&redirect_uri=${config.redirect_uri}`
}

Code reference login.js

// nav.js

componentDidMount() {
    // console.log('code :', getQueryStringByName('code'));
    const code = getQueryStringByName('code')
    if (code) {
      this.setState(
        {
          code
        },
        () => {
          if (!this.state.code) {
            return;
          }
          this.getUser(this.state.code);
        },
      );
    }
  }

componentWillReceiveProps(nextProps) {
    const code = getQueryStringByName('code')
    if (code) {
      this.setState(
        {
          code
        },
        () => {
          if (!this.state.code) {
            return;
          }
          this.getUser(this.state.code);
        },
      );
    }
  }
  getUser(code) {
    https
      .post(
        urls.getUser,
        {
          code,
        },
        { withCredentials: true },
      )
      .then(res => {
        // console.log('res :', res.data);
        if (res.status === 200 && res.data.code === 0) {
          this.props.loginSuccess(res.data);
          let userInfo = {
            _id: res.data.data._id,
            name: res.data.data.name,
          };
          window.sessionStorage.userInfo = JSON.stringify(userInfo);
          message.success(res.data.message, 1);
          this.handleLoginCancel();
          // Jump to the page before authorization
          const href = window.localStorage.preventHref
          if(href){
            window.location.href = href 
          }
        } else {
          this.props.loginFailure(res.data.message);
          message.error(res.data.message, 1);
        }
      })
      .catch(err => {
        console.log(err);
      });
  }

Reference nav.js

1.3.2 backend

The technologies used in the back end of my project are node.js and express.

  • After the back end gets the code from the front end, it also goes to github to get access_token, and then according to access_token to get github to get the user's information.
  • Then the user information to be used is saved to the database through registration, and then returned to the front end.
// app.config.js

exports.GITHUB = {
    oauth_uri: 'https://github.com/login/oauth/authorize',
    access_token_url: 'https://github.com/login/oauth/access_token',
    // Get GitHub user information url//eg: https://api.github.com/user?Access_token=****&scope=&token_type=bearer
    user_url: 'https://api.github.com/user',

    // production environment
    redirect_uri: 'http://biaochenxuying.cn/',
    client_id: '*****',
    client_secret: '*****',

    // // Development environment
    // redirect_uri: "http://localhost:3001/",
    // client_id: "*****",
    // client_secret: "*****",
};

Code reference app.config.js

// Routing file user.js

const fetch = require('node-fetch');
const CONFIG = require('../app.config.js');
const User = require('../models/user');

// User information authorized by third party login
exports.getUser = (req, res) => {
  let { code } = req.body;
  if (!code) {
    responseClient(res, 400, 2, 'code Defect');
    return;
  }
  let path = CONFIG.GITHUB.access_token_url;
  const params = {
    client_id: CONFIG.GITHUB.client_id,
    client_secret: CONFIG.GITHUB.client_secret,
    code: code,
  };
  // console.log(code);
  fetch(path, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json', 
    },
    body: JSON.stringify(params),
  })
    .then(res1 => {
      return res1.text();
    })
    .then(body => {
      const args = body.split('&');
      let arg = args[0].split('=');
      const access_token = arg[1];
      // console.log("body:",body);
      console.log('access_token:', access_token);
      return access_token;
    })
    .then(async token => {
      const url = CONFIG.GITHUB.user_url + '?access_token=' + token;
      console.log('url:', url);
      await fetch(url)
        .then(res2 => {
          console.log('res2 :', res2);
          return res2.json();
        })
        .then(response => {
          console.log('response ', response);
          if (response.id) {
            //Verify that the user is already in the database
            User.findOne({ github_id: response.id })
              .then(userInfo => {
                // console.log('userInfo :', userInfo);
                if (userInfo) {
                  //Set session after successful login
                  req.session.userInfo = userInfo;
                  responseClient(res, 200, 0, 'Authorized Logon Successful', userInfo);
                } else {
                  let obj = {
                    github_id: response.id,
                    email: response.email,
                    password: response.login,
                    type: 2,
                    avatar: response.avatar_url,
                    name: response.login,
                    location: response.location,
                  };
                  //Register to the database
                  let user = new User(obj);
                  user.save().then(data => {
                    // console.log('data :', data);
                    req.session.userInfo = data;
                    responseClient(res, 200, 0, 'Authorized Logon Successful', data);
                  });
                }
              })
              .catch(err => {
                responseClient(res);
                return;
              });
          } else {
            responseClient(res, 400, 1, 'Authorization login failed', response);
          }
        });
    })
    .catch(e => {
      console.log('e:', e);
    });
};

Code reference user.js

As for whether to register to the user table or save to another oauth mapping table after getting github's user information, it depends on your project.

The user information from github is as follows:

Ultimately:

Participating articles:

  1. https://www.jianshu.com/p/a9c...
  2. https://blog.csdn.net/zhuming...

2. How to Design User List for Third Party Authorized Login

When the third party authorizes login, is the third party's user information stored in the original user table or a new table?

Answer: It depends on the specific project. There are many ways to do it. See below.

After the third party authorized login, the third party user information will generally return the user's unique logo, openid or unionid or id, depending on the third party, such as github's ID.

  • 1. Save directly to the database by registration

The first kind: if the website does not have the registration function, it can login directly through the third party authorization. After the authorization is successful, the third user information can be registered and saved directly in the user table of its own database. A typical example is the authorized login of Wechat Public Number.

The second kind: If the website has the registration function, it can also login through the third party authorization. After the authorization is successful, the third party user information can also be registered and stored directly in the user table of its own database (but the password is automatically generated by the back end, the user does not know, and can only login with the third party authorization). This way, the third party user and the original registered user can login with the third party authorization. The information is in the same table, depending on the specific situation of the project. The author's blog website has adopted this method for the time being.

  • 2. Adding Mapping Table

In reality, many websites have a variety of account login modes, such as login with the registration id of the website, login with mobile phone number, login with QQ, and so on. There are mapping relationships in the database, QQ, mobile phone number and so on are mapped on the registration id of the website. Make sure that no matter how you log in, as long as you look up the mapping relationship and find out which id is mapped on the registered website, you can let which id log in successfully.

  • 3. Create an oauth table, an id column, and record the id of the corresponding user registry.

Create an oauth table, an id column, record the id of the corresponding user registry, and then how many columns do you have the third party login function, you set up how many columns to record the openid returned by the third party login interface; when the third party logins, you get the id information through the open id of the record of the table, and if there exists, you read the registry through id and then record the relevant information with session. . There is no openid binding or new registration account information binding for users to enter their registered accounts into the login/registration interface.

Refer to the article for specific code practices:

1. Design of user information table for third party login

2. Talking about the structure design of database user table and third party login

4. last

The author's github blog address: https://github.com/biaochenxuying/blog

If you think this article is good or helpful to you, please give me a compliment or a star, your compliment is the greatest motivation for me to continue to create.

Wechat Public Number: Biao Chen Xu Ying
Share the front-end, back-end development and other related technical articles, hot resources, casual, the whole stack programmer's growth path.
Pay attention to the public number and reply to the welfare, then give you free video resources, absolutely dry goods.
For details of benefits, please click on ___________ Free access to resources -- Python, Java, Linux, Go, node, vue, react, javaScript

Posted by figuringout on Fri, 10 May 2019 03:46:38 -0700