Serengeti logo BLACK white bg w slogan

Simplifying OAuth 2.0 and OpenID Connect Implementation with Spring Authorization Server

Majid Hajrić, Software Developer
25.04.2024.

In the world of modern web development, security is paramount. With the rise of distributed systems and microservices architecture, securing applications and APIs has become increasingly complex. OAuth 2.0 and OpenID Connect (OIDC) have emerged as industry standards for authorization and authentication, respectively. Implementing these protocols has traditionally required considerable effort and expertise. However, with the advent of frameworks like Spring Authorization Server, the process has been streamlined, making building secure, identity-aware applications easier than ever.

In this post, we will focus on the minimum required configuration for the application, and rely on the Spring Boot auto-configuration for defaults.

Understanding OAuth 2.0 and OpenID Connect

OAuth 2.0 is an authorization framework that enables secure access to resources without sharing credentials. You are not sharing credentials with the application, but rather authorizing the application to access your resources on your behalf. It allows users to grant another application limited access to their resources (such as photos or documents) without exposing their credentials. This is achieved through the exchange of tokens, such as access tokens and refresh tokens.

OpenID Connect, on the other hand, is an authentication layer built on top of OAuth 2.0. It provides identity verification, allowing users to log in to applications using their preferred identity provider (IdP), such as Google or Facebook. OpenID Connect adds an ID Token to the OAuth 2.0 protocol, which contains information about the authenticated user.

Introducing Spring Authorization Server

Spring Authorization Server is a new module introduced in the Spring Security ecosystem, specifically designed to simplify OAuth 2.0 and OpenID Connect implementation. It provides a set of building blocks and abstractions that greatly reduce the complexity of setting up authorization and authentication mechanisms in Spring-based applications.

Prerequisites

Before we begin, make sure you have the following prerequisites installed:

  • Java Development Kit (JDK) 17
  • Maven
  • Insomnia Rest or Postman

Step 1: Setting Up the Project

Create a new Spring Boot project using Spring Initializer.

Add spring-boot-starter-oauth2-authorization-server to your project configuration.

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-oauth2-authorization-server</artifactId>
        </dependency>
    </dependencies>

    Configure your project to use OAuth2 and OpenID by defining the necessary properties in your application.properties or application.yml. Also add a default client, although we could define @Bean RegisteredClientRepository, we will keep it here for simplicity. Customize the configurations according to your application requirements such as defining client IDs, client secrets, scopes, etc.

    server:
      port: 9000

    spring:
      application:
        name: authorization-server

      security:
         oauth2:
            authorizationserver:
               client:
                  oidc-client:
                     registration:
                        client-id: "oidc-client"
                        client-secret: "{noop}secret"
                        client-authentication-methods:
                           - "client_secret_basic"
                        authorization-grant-types:
                           - "authorization_code"
                           - "refresh_token"
                        redirect-uris:
                           - "http://127.0.0.1:8080/login/oauth2/code/oidc-client"
                        post-logout-redirect-uris:
                           - "http://127.0.0.1:8080/"
                        scopes:
                           - "openid"
                           - "profile"

                     require-authorization-consent: true

    Step 2: Implementing OAuth2 and OpenID Server

    Create configuration classes to define your OAuth2 and OpenID server settings.

    @Configuration
    public class AuthorizationServerConfig {

        @Bean
        @Order(Ordered.HIGHEST_PRECEDENCE)
        public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
            OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
            http
                    .getConfigurer(OAuth2AuthorizationServerConfigurer.class)
                    .oidc(withDefaults()); // Enable OpenID Connect 1.0
            http
                    .exceptionHandling((exceptions) -> exceptions
                            .defaultAuthenticationEntryPointFor(
                                    new LoginUrlAuthenticationEntryPoint("/login"),
                                    new MediaTypeRequestMatcher(MediaType.TEXT_HTML)
                            )
                    )
                    .oauth2ResourceServer((resourceServer) -> resourceServer.jwt(withDefaults()));
            return http.build();
        }

        // other beans omitted
    }

    Create a configuration class to define Security settings that will protect our endpoints from unauthorized access:

    @Configuration
    @EnableWebSecurity
    public class WebSecurityConfig {

       @Bean
       public SecurityFilterChain defaultFilterChain(HttpSecurity http) throws Exception {
          http.
                  authorizeHttpRequests(authorize ->
                          authorize
                                  .anyRequest().authenticated());
          http
                  .formLogin(Customizer.withDefaults());
                return http.build();
       }

        // other beans omitted
    }


    Step 3: Testing Your OAuth2 and OpenID Server

    Start your Spring Boot application.

    Access the authorization endpoint to initiate the OAuth2 flow.

    image 5

    Authenticate by form login and authorize on the consent screen for the client application.

    image 6

    Obtain the access token and utilize it to access protected resources.

    image 7

    See the userinfo endpoint to view the user profile.

    image 8

    Conclusion

    Implementing OAuth2 and OpenID servers with the Spring Boot Authorization Server extension provides a robust and secure solution for managing authentication and authorization in your applications. By following the steps outlined in this guide, you can ensure seamless integration of OAuth2 and OpenID protocols, enhancing the security and reliability of your systems.

    Full source code can be found here.

    Next Steps

    We have covered the basic setup and configuration of OAuth2 and OpenID servers using Spring Authorization Server. However, there are many advanced features and customizations that can be implemented to enhance the security and user experience of your applications. Some of the features you might consider adding include:

    • Implement custom “/login” page
    • User registration
    • Social Login - Google, GitHub, etc
    • Password reset
    • Username verification (email and phone)
    • MFA
    • Password-less Login
    • JPA implementation (possible MongoDB)
    • Admin interface as SPA utilizing spring-resource-server
    • User Account Page - self-service profile management
    • Multi-tenancy

    References

    Let's do business

    The project was co-financed by the European Union from the European Regional Development Fund. The content of the site is the sole responsibility of Serengeti ltd.
    cross