DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Authentication With Remote LDAP Server in Spring Web MVC
  • Spring OAuth Server: Token Claim Customization
  • Authentication With Remote LDAP Server in Spring WebFlux
  • How to Implement Two-Factor Authentication in A Spring Boot OAuth Server? Part 2: Under the Hood

Trending

  • DevOps Is Dead, Long Live Platform Engineering
  • How to Prevent Data Loss in C#
  • Architecting Sub-Microsecond HFT Systems With C++ and Zero-Copy IPC
  • Smart Deployment Strategies for Modern Applications
  1. DZone
  2. Software Design and Architecture
  3. Security
  4. Authorization Code Grant Flow With Spring Security OAuth 2.0

Authorization Code Grant Flow With Spring Security OAuth 2.0

In this tutorial, learn how to implement a Spring authorization server using Spring Security OAuth2.

By 
Amit Mishra user avatar
Amit Mishra
·
Rob Gravelle user avatar
Rob Gravelle
·
Updated Jan. 26, 24 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
39.7K Views

Join the DZone community and get the full member experience.

Join For Free

What Is an Authorization Code Grant?

According to the OAuth 2.0 specification, an authorization code grant flow is a two-step process mainly used by confidential clients (a web server or secured application that can promise the security of credentials).

OAuth 2.0 is an open standard authorization protocol that enables secure and delegated access to resources on the web. It allows users to grant limited access to their resources (such as profiles or data) to third-party applications without sharing their credentials. OAuth 2.0 is widely used for authentication and authorization in modern web and mobile applications.

Spring Authorization Server is an OAuth 2.0 and OpenID Connect (OIDC) compliant authorization server built on the Spring framework designed to simplify the implementation of secure and standardized authorization protocols. Introduced as part of the Spring Security ecosystem, the Spring Authorization Server facilitates the centralized management of authorization policies and access control for distributed applications. It supports various grant types, enabling different authentication flows such as authorization codes, client credentials, and refresh token grants. The server's modular architecture and integration with Spring Boot make it easy to configure and customize, providing developers with a flexible and scalable solution for managing authentication and authorization in their Spring-based applications.

DZone’s previously covered OAuth 2.0 specifications and how we can implement OAuth 2.0 client credentials grant flow working with Spring's authorization server. In this article, we're going to see how we can implement an authorization code grant flow and get it working with Spring Security. In the first step, we'll request the authorization endpoint to get an authorization code from the authorization server and then use it to get an access token from the authorization server at the token endpoint.

Getting Started

Please make sure that you have all these dependencies in your pom.xml.

XML
 




x


 
1
<dependencies>
2
        <dependency>
3
            <groupId>org.springframework.security</groupId>
4
            <artifactId>spring-security-jwt</artifactId>
5
            <version>1.1.1.RELEASE</version>
6
        </dependency>
7
        <dependency>
8
            <groupId>org.springframework.security.oauth</groupId>
9
            <artifactId>spring-security-oauth2</artifactId>
10
            <version>2.5.0.RELEASE</version>
11
        </dependency>
12
        <dependency>
13
            <groupId>org.springframework.security.oauth.boot</groupId>
14
            <artifactId>spring-security-oauth2-autoconfigure</artifactId>
15
            <version>2.4.0</version>
16
        </dependency>
17
</dependencies>



spring-security-oauth2 has all core dependencies required for OAuth, and spring-security-jwt is for jwt support in oauth2. The auto-configure dependency is required for auto-configuration, and if you don't want to include this one, you will have to add some jaxb dependencies to get it working.

Enabling Authorization Server Support

To enable the support for the authorization server, you would need to add an annotation on top of @SpringBootApplication: @EnableAuthorizationServe.

Java
 




xxxxxxxxxx
1


 
1
@EnableAuthorizationServer
2
@SpringBootApplication
3
public class SpringAuthorizationServerApplication {
4

          
5
    public static void main(String[] args) {
6
        SpringApplication.run(SpringAuthorizationServerApplication.class, args);
7
    }
8

          
9
}



Overriding Authorization Server's Default Configuration

To override the default configuration of Spring's Authorization Server, we will need to extend our configuration class with AuthorizationServerConfigurerAdapter. To reduce the code and effort for demonstration purposes, we will be using in-memory client configuration. The configuration should look similar to what I have here.

Java
 




xxxxxxxxxx
1
25


 
1
@SuppressWarnings("deprecation")
2
@Configuration
3
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {
4
    
5
     @Bean("passwordEncoder")
6
     BCryptPasswordEncoder passwordEncoder() {
7
         return new BCryptPasswordEncoder();
8
     }
9
  
10
    @Override
11
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
12
         clients
13
            .inMemory()
14
                .withClient("clientId")
15
                    .secret(passwordEncoder().encode("client-secret"))
16
                    .scopes("read", "write")
17
                    .authorizedGrantTypes("authorization_code", "refresh_token")
18
                    .redirectUris("http://localhost:8081/oauth/login/client-app")
19
                    .autoApprove(true);
20
     }
21
    
22
    @Bean
23
    JwtTokenStore getAccessTokenConverter() {
24
        return new JwtTokenStore(JwtTokenEnhancer.getInstance());
25
    }
26
}



Please make sure that you've marked your class @Configuration so that it can be picked by Spring Security OAuth2. 

As discussed, authorization code grant flow is for confidential clients; one can guarantee the security of credentials. So here, we have used the BCryptPassword encoder to encode our credentials. That's the reason I've defined a bean of BCrypt. 

To configure client details, we will need to override a configure method that contains ClientDetailsServiceConfigurer, and using in-memory configuration, we can add the required details.

The token store bean that you see I used to customize the jwt token. All you have to do is extend your token converter class from JwtAccessTokenConverter and define a bean in the Authorization Server config to tell the Auth Server to use your configuration for jwt. 

Configuring Spring Security

Till now, all we did was for the Authorization Server. Let's add some Spring Security configurations to add users that we will be authenticating. Extend your class from the WebSecurityConfigurer adapter like so:

Java
 




x


 
1
@EnableWebSecurity
2
@Configuration
3
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
4
    
5
    @Autowired
6
    @Qualifier("passwordEncoder")
7
    BCryptPasswordEncoder passwordEncoder;
8

          
9
    @Override
10
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
11
        auth.inMemoryAuthentication()
12
            .withUser("username")
13
            .password(passwordEncoder.encode("password"))
14
            .roles("USER");
15
    }
16

          
17
    @Override
18
    protected void configure(HttpSecurity http) throws Exception {
19
        
20
        http.authorizeRequests()
21
            .anyRequest()
22
            .authenticated().and()
23
            .formLogin().permitAll()
24
            .and()
25
            .logout().permitAll();
26
        
27
        http.csrf().disable();
28
    }
29
}



It's a normal Spring Security configuration for form login, and we've used in-memory user storage. With that being finished, we're good to start testing the application.

Getting Authorization Code

To get the authorization code, we need to request the server and redirect you to the auth server's login page if you're not authenticated. To get the code, we hit /oauth/authorize with a few required params.

  • response_type : Must set to code (required)
  • client_id : clientId that we set up in the auth server (required)
  • state: Some random value to maintain state between server and client (optional)
  • redirect_uri: Optional 
  • localhost:8080/oauth/authorize?response_type=code&client_id=clientId&state=8781487s1: The link will redirect you to a login page and after successful login, it will redirect you to the redirect link that we had set up in the auth server with some params  (http://localhost:8081/oauth/login/client-app?code=EXUdZm&state=8781487s1).

The core value that we see in the response parameter is the authorization code that we will use later to access the access token and refresh token from the auth server. Learn more tips for OAuth2 token validation.

Access Token Exchange Authorization Code Example

To get an access token and refresh token, we will need to make a post request with clientId and client-secret in basic auth header with a few params.

Here are some code samples of a token request and response:

HTTP
 




x


 
1
POST /oauth/token?grant_type=authorization_code& code=X2KnGB& client_Id=clientId& state=8781487s1 HTTP/1.1
2
Host: localhost:8080
3
Authorization: Basic Y2xpZW50SWQ6Y2xpZW50LXNlY3JldA==
4
cache-control: no-cache



Once, you make this post request you will get a response similar to this:

JSON
 




xxxxxxxxxx
1


 
1
{
2
    "access_token": "U9c7fB35jHh6vW-WsBd-VdfLcOs",
3
    "token_type": "bearer",
4
    "refresh_token": "hGMk8bgNwO7YHrKaCZkc380BB68",
5
    "expires_in": 43199,
6
    "scope": "read write"
7
}



That's all! You can use this token to access protected resources. Since I've signed this token using RSA private and public keys, that's the reason it's different from a normal jwt token. Further review how to secure Spring Boot microservices with JSON web tokens.

I would like you to see how I implemented an access token converter.

Java
 




x


 
1
public class JwtTokenEnhancer extends JwtAccessTokenConverter {
2
    
3
    private static final String PRIVATE_KEY = "Your private rsa key";
4
    private static final String PUBLIC_KEY = "Your public rsa key";
5
    
6
    public JwtTokenEnhancer(String publicKey, String privateKey) {
7
        super.setSigningKey(privateKey);
8
        super.setVerifierKey(publicKey);
9
    }
10
    
11
    public static JwtAccessTokenConverter getInstance() {
12
        return new JwtTokenEnhancer(JwtTokenEnhancer.PUBLIC_KEY, JwtTokenEnhancer.PRIVATE_KEY);
13
    }
14
    
15
    
16
}
17

          



Remember, it's wrapped into a token store bean that we've defined in auth server configurations. With that being said, thank you so much for taking the time to read this post, and I will be coming up with some Spring Security 5 OAuth2.0 articles. This project is available on GitHub.

Spring Security authentication Spring Framework JWT (JSON Web Token)

Opinions expressed by DZone contributors are their own.

Related

  • Authentication With Remote LDAP Server in Spring Web MVC
  • Spring OAuth Server: Token Claim Customization
  • Authentication With Remote LDAP Server in Spring WebFlux
  • How to Implement Two-Factor Authentication in A Spring Boot OAuth Server? Part 2: Under the Hood

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook