OAuth2 Authentication with Spring Security and Github

In this article I will show how to authenticate using the OAuth2 system with Spring Security and Github. For that, I will need to create a Github login application and connect it to my Spring Boot application with Spring Security to allow it to perform the necessary requests.

Content:

  • Github Apps
  • OAuth2 Authentication types
  • Spring Security configuration
  • OAuth2 workflow
  • @AuthenticationPrincipal and OAuth2User object

Check this video for more details.

All the code of the article is available in the following repository.

Github Apps

The OAuth2 system is an authentication system based on an authorization server, in my case I will use Github. Let’s first see how to create and configure a Github application to use it as an authorization server.

Github Developer settings
Github Developer settings

In the developer section, I can create an OAuth application.

Github OAuth registration application
Github OAuth registration application

Multiple OAuth2 clients have this callback URL already defined by convention, as Spring Boot does:

  • login is the action
  • oauth2 is the protocol
  • code is the type of the OAuth2
  • and github is the server

OAuth2 Authorization types

There are multiple OAuth2 authorizations types. The main components of the OAuth2 authorization system are:

  • the client, which use to be the backend server;
  • the user agent, usually the browser;
  • the authorization server, Github or Google or Facebook;
  • and the resource owner, the database the user wants to read, which is the Github account in our case.

I want to read the Github account for two reasons: if I don’t have the profile in my database application, I will fill it with the Github account information; and if I already have the profile in my database application, I use the Github account to look for the business information linked to this user.

Ok, but which are the different authorization types? And what are they used for? The authorization code grant is the one by default. The backend server will redirect the browser to an authentication page hosted in the authorization server. When done, the browser will obtain a code. This code must be sent to the backend. And the backend must now validate the code with the authorization server. This last step will allow the browser to read the necessary information from the target database.

There are other OAuth2 systems, but I won’t handle them in this article:

  • there is the implicit grant, which is mostly used for mobile or javascript applications;
  • the resource owner password credentials grant, which requires that the backend and the database have a trusted relationship;
  • and the client credentials grant, which is mainly used for API authentication.

Spring Security configuration

Okay, my Github application is ready. Let’s create the credentials to allow my backend to authenticate to the Github authorization server.

Github OAuth application information
Github OAuth application information

And now, let’s move to my Spring Boot application. I only need one Maven dependency.

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-oauth2-client</artifactId>
        </dependency>

And configure this dependency to talk with the Github server in the application.yml.

spring:
  security:
    oauth2:
      client:
        registration:
          github:
            clientId: **********************
            clientSecret: **********************

OAuth2 workflow

This is the default URL used by the OAuth2 clients, http://localhost:8080/oauth2/authorization/github. It will start the authentication workflow.

  1. The workflow starts with the backend server. This one will generate a link for the browser to see the login form in the authorization server. The login form of Github.
  2. The link to the login form will contain the information of my backend server, which type of authorization I am asking for, the id of the application I’ve created on Github, the redirect URL which must be the same as the one configured, the scope which is the action I want to perform upon the Github account (i want to read the account information), and the state which is a unique ID of the request. This way, the link can’t be used twice.
  3. Then, the authorization server will answer the browser with that code and the same state ID.
  4. The browser must send this code to the backend.
  5. And the backend will request an access token with this code. The resulting access token will then be used against the Github API to read the user’s account.

Too many steps, right? Hopefully, the previous library does all of them for me.

> curl http://localhost:8080/oauth2/authorization/github -v
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET /oauth2/authorization/github HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 302
< Set-Cookie: JSESSIONID=78D09F3F3C7548C826738DC755F23357; Path=/; HttpOnly
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Location: <strong>https://github.com/login/oauth/authorize?response_type=code&client_id=f18640a7e427a2594735&scope=read:user&state=27_wXJS6iyf-tVVes9yD-1cGXItpEo9EsEygsoeBwnA%3D&redirect_uri=http://localhost:8080/login/oauth2/code/github</strong>
< Content-Length: 0
< Date: Tue, 02 Nov 2021 21:57:12 GMT
<
* Connection #0 to host localhost left intact
* Closing connection 0

Here is the authorization type, code, my client ID, f18640a7e427a2594735, the scope, read:user, my unique ID, 7_wXJS6iyf-tVVes9yD-1cGXItpEo9EsEygsoeBwnA=, and the redirect URL, http://localhost:8080/login/oauth2/code/github. Let’s open it in a browser.

@AuthenticationPrincipal and OAuth2User object

Inspecting the network when opening the URL in the browser, I can see the request to the github authorization server. And also the callback to my application with the code and the state information. The Spring Boot OAuth2 library will create a cookie with the session ID and with the user information in the session. And to read the user information, I just need to add the @AuthenticationPrincipal OAuth2User to read the information in the controllers.

    @GetMapping("/messages")
    public ResponseEntity<List<MessageDto>> getCommunityMessages(
            @AuthenticationPrincipal OAuth2User principal,
            @RequestParam(value = "page", defaultValue = "0") int page) {

        UserDto user = authenticationService.findOrCreateByLogin(principal);
        return ResponseEntity.ok(communityService.getCommunityMessages(user, page));
    }

The OAuth2User object contains the information which came from the Github account, from the Github API.

There isn’t a lot of code, but a lot of information. Hopefully the Spring Boot OAuth2 dependency does it all for me.

References

Repository

My New ebook, How to Master Git With 20 Commands, is available now.

One response to “OAuth2 Authentication with Spring Security and Github”

  1. […] monolith application, I can use the OAuth2 client dependency with little configuration, check here how to do […]

    Like

Leave a comment

A WordPress.com Website.