OAuth

There are a lot of basic content about Oauth 2.0 protocol on the Internet, SO I won’t repeat the blog. If you don’t understand the basic concept, you can Google it first. But I found that there were very few actual demos, so I wrote this blog.

  • This article uses GitHub login as an example to demonstrate.

  • Although the online environment must have a cloud server, debugging can be simulated directly locally

  • Demonstrate a complete login process without writing a line of code!! Please be sure to manual practical operation!!

In fact, OAuth certification to say:

  • There are three characters:

    GitHub, user, third side

  • Need is the accomplishment of one thing:

    Let third-Side secure a token from GitHub with the user’s consent

  • Third-side gets this token and can use it

    • Identifies a user and reads basic information about the user
    • Perform actions on GitHub on behalf of the user, such as writing an issue

The basic flow

  1. Register an application with GitHub

    One application corresponds to one project, and we need to get a Client ID and secret for subsequent login authentication

  2. Construct relevant login links that direct the user to click login. This step requires the client ID above

  3. Once the user agrees to log in, third-side gets a code(more on that later) from which it can get the user’s token from GitHub

The first step is to register the App

Since we will use GitHub as the third party to log in, we must register an application on the official website first.

  • Web site:Github.com/settings/de…

Just click the green button, and the page 👇 will appear after clicking:

It’s a lot, but only two fields are critical

  • Application Name: This is what GitHub uses to identify our APP

  • Authorization Callback URL: the one I’ve highlighted in red above is critical

  • This url is for display purposes and will not be used in the following login

The Authorization Callback URL is the url that GitHub uses to inform our server when a user confirms login. Therefore, the actual URL should be listened for by a special server program. But you can follow me to fill in this step and talk about it later.

After registration, we have this data:

There are two key numbers

  • Cliendt_id is what GitHub uses to identify our APP

    Next we need to build our login URL from this field

  • Client Secret is very important, we will use it to authenticate later, so keep it well. This is just a demo tutorial. It was destroyed when it was finished, so it was made public.

To construct the URL

And then what do we do? Very simple

<body>
  <a href="https://github.com/login/oauth/authorize\
?client_id=47878c9a96cfc358eb6e">
    login with github</a>
</body>
Copy the code

All we have to do is add code to our login page that directs the user to click our login button.

Notice the flow above? We’re actually halfway through the login authentication process, so let’s analyze it.

First of all, think about this: How many important HTTP packets have been delivered since the user clicked Login with Github?

Unimportant refers to the requests for CSS AND JS resources attached to the middle pages, which do not count.

How many HTTP requests are there related to login authentication?

Three!! Make that clear, and you’ll basically understand.

First we construct an HTML page like this

<body>
  <a href="https://github.com/login/oauth/authorize\
?client_id=47878c9a96cfc358eb6e">
    login with github</a>
</body>
Copy the code

The point is we constructed a URL

  • https://github.com/login/oauth/authorize:

    This part is fixed, as long as you log in from GitHub. You can see this link from the official documentation.

    If it is wechat login, Twitter login, is also similar, the specific URL can be found on the relevant official website.

    GitHub listens for this route to perform login processing

  • It is then followed by a query string client_id= 47878c9a96CFc358eb6e.

    Its value is the client ID we applied for before. This is a mandatory field that GitHub uses to determine which site a user wants to log in to after clicking on it.

GitHub then returns a page to confirm that the user really wants to log in, which is the first HTTP request and response

And then what happens when the user clicks OK?

  • When users click Confirm, GitHub sends a message to confirm that they have logged in to a website

  • GitHub receives an acknowledgement message from the user and returns a status code 302 message

This is the second HTTP request and response. Because the browser receives the 302 redirect and goes directly to the new url, you might miss it if you don’t look carefully.

The status code of 302 message, its Location fields or so long: https://github.com/fish56/OAuth?code=a1aee8cacf7560825665 >

  • https://github.com/fish56/OAuth

    This field is the callback URL we filled in before, normally this should be the URL of our cloud server. But for the sake of demonstration, I just filled in my Github address, it doesn’t matter

  • code=a1aee8cacf7560825665:

    (Because the author debugging, so now write token and GIF inside the different ha)

    This is our OAuth login a core information. As I said before, the core purpose of our OAuth login is to enable third-party websites to get users’ tokens safely. When the user’s browser receives the previous HTTP response of 302, it sends a request to our server, and the server gets the code at the same time. The server can then get the user’s token from Github using this code.

This is the third HTTP request.

Why return a code instead of a token?

A: For security, if the token passes through the user’s hand once, it may be stolen by other malicious people.

Under OAuth, GitHub will return a code to the user, and then the user’s browser will carry the code to our server through redirection, so that the server gets the code.

After the server gets this code, it applies to GitHub for token by combining the previous client Secret, which will be safer.

We’ve only done half of this before, so let’s use Postman to demonstrate how to get the token through code.

The login

We need to apply to GitHub for the token of the user

  • code

    This is only available to the server if the user agrees to log in.

  • client secret + client id

  • To https://github.com/login/oauth/access_token launched a POST request, and carry on three fields above

    This URL is specified by GitHub and can be found in its official documentation

We then construct the request in Postman like this:

Alas, you can see that we did get the user’s token:

Access_token = 9094 eb58a23093fd593d43eb28c1f06ce7904ed5 & scope = & token_type = bearer.

But the actual situation above the operation is completed by the online server, I operate is convenient for everyone to understand.

The code field

As we can see from the above example, we don’t need a server if it’s just a demonstration. Let’s go ahead and demonstrate this directly in local code.

  • The demo code was written using Node + Express + Request
  • However, the code is very simple and can be read without understanding the technology stack above
  • The flow is exactly the same as the previous demonstration, just done in code
  • See the source code here GitHub

Since we need to start the local server to listen for responses, we first need to modify our callback URL.

Please amend the the callback URL to to http://localhost:8099/github/login.

This is the directory structure of our program

And here’s our Node code:

const querystring = require('querystring');
const express = require('express');
const request = require('request');

const githubConfig = require('./oauth.conf')

let app = express();

// Create a routing function that listens for /github/login get requests
app.get('/github/login'.async function(req,res){
    
  //read code from url
  let code = req.query.code

  // After receiving the code, request GitHub for the user's token
  request.post(githubConfig.access_token_url, {
      form: {client_id: githubConfig.client_ID,
        client_secret: githubConfig.client_Secret,
        code: code
      }
    },function(error, response, body) {
     // Normally, the return value should be of the form access_token=9094eb58a23093fd59
     // 3d43eb28c1f06ce7904ed5&scope=&token_type=bearer
     // can be parsed using the following function
      let result = querystring.parse(body)
      
      // Get the token and return the result, indicating that we are successful
      let access_token = result["access_token"]
      if(access_token == undefined){
        res.send(result.error_description)
      }
      res.send(`You are login! you token is ${access_token}`)})})// Listen to 8999 and start the program. Note that the port number must be the same as the one we filled in before
app.listen(8099.function(){
    console.log('listening localhost:8099')})Copy the code

This is a request. Conf. Js. Be sure to replace the relevant fields with your own configuration.

module.exports = {
  client_ID: '47878c9a96cfc358eb6e'.client_Secret: '4813689c043c60dbf3d3a0d8e0a984afc0bf810a'.access_token_url: 'https://github.com/login/oauth/access_token'
}
Copy the code

This is the actual effect

What does our code do? It just automates what we were doing manually with Postman

  • Listening to thehttp://localhost:8099/github/login
  • After receiving the code from the user’s browser, our server applied to GitHub for the user token
  • If the token is returned to the user, the login is successful

But actually I left out a lot of things. Under normal circumstances, after the server receives the user’s token, it should:

  • Save the token to the database
  • Get data like a user’s name from Github via token
  • Tokens should not be returned to the user
  • A cookie is returned to the user to keep the user logged in, and this cookie is matched to the user’s token in the database

conclusion

Okay, so that’s basically a login process.

  • Construct a login link that directs the user to log in
  • After a user logs in, GitHub redirects the user to our pre-set URL, along with a code
  • The server gets the code and applies to GitHub for a token
  • After receiving the token, the server can confirm that the user logged in successfully and then return a successful login page