A simple introduction

OAuth(Open Authorization) is the most popular Authorization mechanism used to authorize third-party applications and obtain user data. Previously, users had to register to log in to any website, and tedious information filling made them feel helpless. Now, users can authorize to log in to third-party applications through OAuth protocol, which eliminates the registration process and improves user retention rate to a certain extent.

OAuth authorization process analysis

There are four steps in the authorization code mode:

  1. A third-party application attempts to obtain user authorization by accessing the authorization server. The user decides whether to authorize the application
  2. After obtaining user authorization, the authorization server returns the authorization code to the application server
  3. The application server carries the authorization code and requests a token from the authorization server. The authorization server issues the token after successfully authenticating the authorization code and client key
  4. The application server carries the token and requests the user information from the authorization server. The authorization server authenticates the token and returns the required information

Here is a simple sequence diagram I drew:

Why does the authorization server return code instead of access_token directly? Is this a redundant step? First of all, it is not a redundant operation, and that has to do with the way it is requested, for security purposes, as you will see later in the actual practice.

  • The link that leads the user to the link, that’s a hyperlink, that’s agetThe request, after the authorization server gets the user’s authorization, is made through the hyperlinkredirect_uriYou can see it in the browser address bar if you just return itaccess_tokenIt’s not safe.
  • soOAuthIntroducing the authorization code, authorization code is doesn’t matter, because when I went to request token will check again (at a higher level of checking, request not only to the authorization code to the application itself some identity information), but the authorization server response didn’t go through the browser, directly to the backend, so much a request but guarantee the safety of the token.

OAuth authorized actual combat

I connected with QQ, GitHub and Weibo. The process was basically the same, but there were differences in some API parameters, so I had to check the documents by myself, such as OpenID for QQ to request user information, UID for Weibo and so on. GitHub is the simplest, can be localhost local test, like Weibo, QQ need IP and domain name, wechat seems not to support personal development.

Here is GitHub as an example:

  1. Go to theGitHubTo register application information and obtainclient idandclient secret

    How to create
  2. Place links and direct users to click

    Detailed documentation(This document has parameters and request methods in the entire authorization process)
    <a id="github" class="github" href="Https://github.com/login/oauth/authorize?client_id=xx&redirect_uri=http://127.0.0.1:8085/githubcallback&scope=user&stat e=1">
        <i class="fa fa-github"></i>
    </a>
    Copy the code
  3. The background receives the authorization codecodeAnd carrycodeTo apply for the token
    // Encapsulate the parameters of the request token
    @Data
    public class GitHubAccessTokenDTO {
        // The client ID received during registration
        private String client_id;
        // The customer password received during registration
        private String client_secret;
        / / authorization code
        private String code;
        // Where to redirect the user after redirecting URI authorization
        private String redirect_uri;
        // Self-provided random strings prevent cross-site attacks
        private String state;
    }
    
    // Send a Post request to request a token (using okhttp3)
    public String getAccessToken(GitHubAccessTokenDTO accessTokenDTO) {
        MediaType mediaType = MediaType.get("application/json; charset=utf-8");
        OkHttpClient client = new OkHttpClient();
    
        RequestBody body = RequestBody.create(mediaType, JSON.toJSONString(accessTokenDTO));
        Request request = new Request.Builder()
                .url("https://github.com/login/oauth/access_token")
                .post(body)
                .build();
        try (Response response = client.newCall(request).execute()) {
            String str = response.body().string();
            // Intercept useful parts
            String token = str.split("&") [0].split("=") [1];
            return token;
        } catch (IOException e) {
            log.error("get GitHub access_token error, {}", e);
        }
        return null;
    }
    
    // Controller receives code,state, request token
    @GetMapping("/githubcallback")
    public String github_callback(@RequestParam(name = "code") String code,
                                  @RequestParam(name = "state") String state) {
        GitHubAccessTokenDTO accessTokenDTO = new GitHubAccessTokenDTO();
        accessTokenDTO.setClient_id(github_clientId);
        accessTokenDTO.setClient_secret(github_secret);
        accessTokenDTO.setState(state);
        accessTokenDTO.setCode(code);
        accessTokenDTO.setRedirect_uri(github_redirectUri);
        String accessToken = gitHubProvider.getAccessToken(accessTokenDTO);     
    }
    Copy the code
  4. According to the tokenaccess_tokenRequesting user information
    public GitHubUser getUser(String accessToken) {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url("https://api.github.com/user")
                .header("Authorization"."token " + accessToken)
                .build();
    
        try {
            Response response = client.newCall(request).execute();
            String str = response.body().string();// Json format, need to convert (using FastJSON)
            GitHubUser gitHubUser = JSON.parseObject(str, GitHubUser.class);
            return gitHubUser;
        } catch (IOException e) {
            log.error("get GitHub User error, {}", e);
        }
        return null;
    }
    
    // Continue the request at github_callback()
    GitHubUser gitHubUser = gitHubProvider.getUser(accessToken);
    Copy the code
  5. Get user information, you can drop persistent
    // handled in github_callback()
    if(gitHubUser ! =null) {// Login succeeded
        // Database user to get the desired information (can also login persistent, add cookies, etc.)
        // userService.insert(user); .
        
        // Login successful, return to home page
        return "redirect:/";
    }
    Copy the code

conclusion

In the process of connecting to other authorized services, it is necessary to refer to relevant documents. Some documents are not clear, and manual debugging is needed to test them. It is still a good exercise for one’s ability. That above is my a few individual opinion, if be wrong, still ask everybody to correct!!!