1. Overview

Here is an explanation of spring security Oauth 2.0 authentication server implementation example using spring boot. To implements OAuth 2.0 first of all need to understand two terminologies.

  1. Authentication Server
  2. Resource Server (here is an example of OAuth2 Resouce server)

Authentication server is responsible for giving grant to access resources.

Resource server which contains actual resources like RestAPI, Images or any other resources.

 2. Example

Technology Stack

We have used following frameworks used to build spring security auth  2.0 authentication server example using spring boot

  • Spring boot
  • Spring security
  • Spring auth2.0
  • Maven
  • Tomcat 8.5

 

spring security auth 2.0 authentication server

spring security auth 2.0 authentication server

2.1 pom.xml

To implements, authentication server spring-security-oauth2 must be available in CLASSPATH.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>spring-boot-example</groupId>
    <artifactId>spring-security-auth-2.0-authentication-server-example</artifactId>
    <version>1.0-SNAPSHOT</version>
    <description>spring security auth 2.0 authentication server example using spring boot</description>
    <!-- Inherit defaults from Spring Boot -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.4.RELEASE</version>
    </parent>
    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>  <!--starter require for spring boot spring security-->
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.security.oauth</groupId>
            <artifactId>spring-security-oauth2</artifactId>
        </dependency>
    </dependencies>

    <!-- Package as an executable jar -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

2.2 SecurityAuth2Configuration

  • @EnableAuthorizationServer indicate that this service considers as the authentication server.
  • AuthorizationServerConfigurerAdapter class is used to configure spring boot auth 2.0 authentication server. withClient and secret method requires client and secret which will be used to authentication server. Right now we have used client and secret in memory. Generally for each resource server client and secret will be different.
  • accessTokenValiditySeconds indicate the life of access token, after that access token will not valid or it will be expired so using that access token client cannot access resources.
  • refreshTokenValiditySeconds indicate like of refresh token, after that refresh token will be expired. -1 means that refresh token will never expired. Generally like of refreshToken is more then accessToken.
  • refreshToken: Refresh token is used to generate another access token. Once access token has been expired using refreshToken new access token can be generated.
package com.javadeveloperzone;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;

/**
 * Created by JavaDeveloperZone on 04-08-2017.
 */
@Configuration
@EnableAuthorizationServer          // to enable auth 2.0 authentication server
public class SecurityAuth2Configuration extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer.tokenKeyAccess("permitAll()")
                   .checkTokenAccess("isAuthenticated()");
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
                clients.inMemory()
               .withClient("javadeveloperzone")
                       .secret("secret")
                       .accessTokenValiditySeconds(2000)        // expire time for access token
                       .refreshTokenValiditySeconds(-1)         // expire time for refresh token
               .scopes("read", "write")                         // scope related to resource server
                       .authorizedGrantTypes("password", "refresh_token");      // grant type
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager);
    }
}

2.3 SecurityConfig

Spring security in-memory configuration. Here is the blog to configure database authentication.

package com.javadeveloperzone;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

/**
 * Created by JavaDeveloperZone on 09-12-2017.
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .antMatcher("/**")
                .authorizeRequests()
                .antMatchers("/", "/login**")
                .permitAll()
                .anyRequest()
                .authenticated();
    }

    @Autowired      // here is configuration related to spring boot basic authentication
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()                                               // static users
            .withUser("zone1").password("mypassword").roles("USER")
            .and()
            .withUser("zone2").password("mypassword").roles("USER")
            .and()
            .withUser("zone3").password("mypassword").roles("USER")
            .and()
            .withUser("zone4").password("mypassword").roles("USER")
            .and()
            .withUser("zone5").password("mypassword").roles("USER");
    }
}

2.4 SpringBootApplication

package com.javadeveloperzone;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

/**
 * Created by JavaDeveloperZone on 19-07-2017.
 */

@org.springframework.boot.autoconfigure.SpringBootApplication
@ComponentScan({"com.javadeveloperzone"})

// Using a root package also allows the @ComponentScan annotation to be used without needing to specify a basePackage attribute
public class SpringBootConfig {
    public static void main(String[] args) throws Exception {
        SpringApplication.run(SpringBootConfig.class, args);            // it wil start application
    }
}

2.5 Build & Run application

mvn spring-boot:run

[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building spring-security-auth-2.0-authentication-server 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] >>> spring-boot-maven-plugin:1.5.4.RELEASE:run (default-cli) > test-compile @ spring-security-auth-2.0-authentication-server >>>
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ spring-security-auth-2.0-authentication-server ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 0 resource
[INFO] Copying 0 resource
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ spring-security-auth-2.0-authentication-server ---
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ spring-security-auth-2.0-authentication-server ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory F:\extrawork\spring-boot\spring-boot-spring-security-auth2.0-database\src\test\resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ spring-security-auth-2.0-authentication-server ---
[INFO] No sources to compile
[INFO] 
[INFO] <<< spring-boot-maven-plugin:1.5.4.RELEASE:run (default-cli) < test-compile @ spring-security-auth-2.0-authentication-server <<<
[INFO] 
[INFO] --- spring-boot-maven-plugin:1.5.4.RELEASE:run (default-cli) @ spring-security-auth-2.0-authentication-server ---

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.5.4.RELEASE)

2017-12-30 12:25:59.229  INFO 2568 --- [           main] c.j.SpringBootApplication                : Starting SpringBootApplication on Mahesh with PID 2568 (F:\extrawork\spring-boot\spring-boot-spring-security-auth2.0-database\target\classes started by Lenovo in F:\extrawork\spring-boot\spring-boot-spring-security-auth2.0-database)
2017-12-30 12:25:59.234  INFO 2568 --- [           main] c.j.SpringBootApplication                : No active profile set, falling back to default profiles: default
2017-12-30 12:25:59.430  INFO 2568 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot[email protected]5ee5280b: startup date [Sat Dec 30 12:25:59 IST 2017]; root of context hierarchy
2017-12-30 12:26:02.594  INFO 2568 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http)
2017-12-30 12:26:02.613  INFO 2568 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2017-12-30 12:26:02.613  INFO 2568 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.15
2017-12-30 12:26:02.782  INFO 2568 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2017-12-30 12:26:02.783  INFO 2568 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 3358 ms
2017-12-30 12:26:03.142  INFO 2568 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'characterEncodingFilter' to: [/*]
2017-12-30 12:26:03.143  INFO 2568 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2017-12-30 12:26:03.143  INFO 2568 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2017-12-30 12:26:03.143  INFO 2568 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]
2017-12-30 12:26:03.146  INFO 2568 --- [ost-startStop-1] .s.DelegatingFilterProxyRegistrationBean : Mapping filter: 'springSecurityFilterChain' to: [/*]
2017-12-30 12:26:03.146  INFO 2568 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'dispatcherServlet' to [/]
2017-12-30 12:26:03.905  INFO 2568 --- [           main] .s.o.p.e.FrameworkEndpointHandlerMapping : Mapped "{[/oauth/authorize],methods=[POST],params=[user_oauth_approval]}" onto public org.springframework.web.servlet.View org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint.approveOrDeny(java.util.Map<java.lang.String, java.lang.String>,java.util.Map<java.lang.String, ?>,org.springframework.web.bind.support.SessionStatus,java.security.Principal)
2017-12-30 12:26:03.907  INFO 2568 --- [           main] .s.o.p.e.FrameworkEndpointHandlerMapping : Mapped "{[/oauth/authorize]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint.authorize(java.util.Map<java.lang.String, java.lang.Object>,java.util.Map<java.lang.String, java.lang.String>,org.springframework.web.bind.support.SessionStatus,java.security.Principal)
2017-12-30 12:26:03.908  INFO 2568 --- [           main] .s.o.p.e.FrameworkEndpointHandlerMapping : Mapped "{[/oauth/token],methods=[POST]}" onto public org.springframework.http.ResponseEntity<org.springframework.security.oauth2.common.OAuth2AccessToken> org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(java.security.Principal,java.util.Map<java.lang.String, java.lang.String>) throws org.springframework.web.HttpRequestMethodNotSupportedException
2017-12-30 12:26:03.909  INFO 2568 --- [           main] .s.o.p.e.FrameworkEndpointHandlerMapping : Mapped "{[/oauth/token],methods=[GET]}" onto public org.springframework.http.ResponseEntity<org.springframework.security.oauth2.common.OAuth2AccessToken> org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.getAccessToken(java.security.Principal,java.util.Map<java.lang.String, java.lang.String>) throws org.springframework.web.HttpRequestMethodNotSupportedException
2017-12-30 12:26:03.910  INFO 2568 --- [           main] .s.o.p.e.FrameworkEndpointHandlerMapping : Mapped "{[/oauth/check_token]}" onto public java.util.Map<java.lang.String, ?> org.springframework.security.oauth2.provider.endpoint.CheckTokenEndpoint.checkToken(java.lang.String)
2017-12-30 12:26:03.914  INFO 2568 --- [           main] .s.o.p.e.FrameworkEndpointHandlerMapping : Mapped "{[/oauth/confirm_access]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.security.oauth2.provider.endpoint.WhitelabelApprovalEndpoint.getAccessConfirmation(java.util.Map<java.lang.String, java.lang.Object>,javax.servlet.http.HttpServletRequest) throws java.lang.Exception
2017-12-30 12:26:03.916  INFO 2568 --- [           main] .s.o.p.e.FrameworkEndpointHandlerMapping : Mapped "{[/oauth/error]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.security.oauth2.provider.endpoint.WhitelabelErrorEndpoint.handleError(javax.servlet.http.HttpServletRequest)
2017-12-30 12:26:04.917  INFO 2568 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot[email protected]5ee5280b: startup date [Sat Dec 30 12:25:59 IST 2017]; root of context hierarchy
2017-12-30 12:26:05.035  INFO 2568 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2017-12-30 12:26:05.035  INFO 2568 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2017-12-30 12:26:05.085  INFO 2568 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2017-12-30 12:26:05.085  INFO 2568 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2017-12-30 12:26:05.189  INFO 2568 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2017-12-30 12:26:05.851  INFO 2568 --- [           main] o.s.s.web.DefaultSecurityFilterChain     : Creating filter chain: OrRequestMatcher [requestMatchers=[Ant [pattern='/css/**'], Ant [pattern='/js/**'], Ant [pattern='/images/**'], Ant [pattern='/webjars/**'], Ant [pattern='/**/favicon.ico'], Ant [pattern='/error']]], []
2017-12-30 12:26:06.075  INFO 2568 --- [           main] o.s.s.web.DefaultSecurityFilterChain     : Creating filter chain: OrRequestMatcher [requestMatchers=[Ant [pattern='/oauth/token'], Ant [pattern='/oauth/token_key'], Ant [pattern='/oauth/check_token']]], [org.springframework.secu[email protected]7288ef2c, org.spring[email protected]1a73cf2f, [email protected]1fa, org.[email protected]7435d547, org.springfram[email protected]6b4fed3, org.sp[email protected]6b8c4622, org.springframework.[email protected]188841da, org.springfram[email protected]536bd5c8, o[email protected]6e821dd, org[email protected]ee945ca, org.springfr[email protected]71e52d8]
2017-12-30 12:26:06.087  INFO 2568 --- [           main] o.s.s.web.DefaultSecurityFilterChain     : Creating filter chain: Ant [pattern='/**'], [org.springframework.secu[email protected]5495385e, org.spring[email protected]42dc6315, [email protected]5c, [email protected], org.[email protected]251b73cd, org.sp[email protected]39482fad, org.springframework.[email protected]60e81980, org.springfram[email protected]13f2ff3b, o[email protected]77b65000, org[email protected]70316bc8, org.springfr[email protected]3181a75c]
2017-12-30 12:26:06.093  INFO 2568 --- [           main] o.s.s.web.DefaultSecurityFilterChain     : Creating filter chain: OrRequestMatcher [requestMatchers=[Ant [pattern='/**']]], [org.springframework.secu[email protected]d30632, org.spring[email protected]2e0f239a, [email protected]44f, org.[email protected]4e0c1ebe, org.springfram[email protected]1948e716, org.sp[email protected]6d8a60eb, org.springframework.[email protected]17d54409, org.springfram[email protected]2edbd442, o[email protected]7e84e085, org[email protected]5f4380b0, org.springfr[email protected]77793517]
2017-12-30 12:26:06.362  INFO 2568 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2017-12-30 12:26:06.513  INFO 2568 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2017-12-30 12:26:06.522  INFO 2568 --- [           main] c.j.SpringBootApplication                : Started SpringBootApplication in 7.996 seconds (JVM running for 13.581)

 

2.6 Demo:

How to access accessToken:

spring security Oauth 2.0 authentication server access token

spring security Oauth 2.0 authentication server access token

How to access accessToken from refreshToken

spring security Oauth 2.0 authentication server access refresh token

spring security Oauth 2.0 authentication server access refresh token

3. References

Spring boot  auth2.0 authentication server documentation 

Was this post helpful?
Let us know, if you liked the post. Only in this way, we can improve us.
Yes
No

2 comments. Leave new

First of all great article thanks for this.
My question is I am also getting the following exception in my console. Is it something to be taken cared of?

2017-12-30 12:26:03.907 INFO 2568 — [ main] .s.o.p.e.FrameworkEndpointHandlerMapping : Mapped “{[/oauth/authorize]}” onto public org.springframework.web.servlet.ModelAndView org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint.authorize(java.util.Map,java.util.Map,org.springframework.web.bind.support.SessionStatus,java.security.Principal)
2017-12-30 12:26:03.908 INFO 2568 — [ main] .s.o.p.e.FrameworkEndpointHandlerMapping : Mapped “{[/oauth/token],methods=[POST]}” onto public org.springframework.http.ResponseEntity org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(java.security.Principal,java.util.Map) throws org.springframework.web.HttpRequestMethodNotSupportedException
2017-12-30 12:26:03.909 INFO 2568 — [ main] .s.o.p.e.FrameworkEndpointHandlerMapping : Mapped “{[/oauth/token],methods=[GET]}” onto public org.springframework.http.ResponseEntity org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.getAccessToken(java.security.Principal,java.util.Map) throws org.springframework.web.HttpRequestMethodNotSupportedException

Thank you Arjun,
I am not sure why you are facing this issue:
Probability 1:
Check following configuration: OAuth2 automatically create endpoints, Make sure that @Configuration annotation at configuration class.

@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.tokenKeyAccess(“permitAll()”)
.checkTokenAccess(“isAuthenticated()”);
}
Probability 2:
Properly pass client username and password in basic authentication, That we have shown in images
Probability 3:
Check spring boot version, Our code is well tested in 1.5.4.RELEASE.

Leave a Reply

Your email address will not be published. Required fields are marked *