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

  1. Suthentication server
  2. Resource server

Authentication server is responsible for give grant to access resources.

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

Technology stack

We have use 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

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>

SecurityAuth2Configuration

  • @EnableAuthorizationServer indicate that this service consider as 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 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 life of access token, after that access token will not valid or it will be expired so using that access token client can not 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);
    }
}

SecurityConfig

Spring security in-memory configuration. Here is 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");
    }
}

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
    }
}

Bulild & 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.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@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.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@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.security.web.context.request.async.WebAsyncManagerIntegrationFilter@7288ef2c, org.springframework.security.web.context.SecurityContextPersistenceFilter@1a73cf2f, org.springframework.security.web.header.HeaderWriterFilter@3210a1fa, org.springframework.security.web.authentication.logout.LogoutFilter@7435d547, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@6b4fed3, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@6b8c4622, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@188841da, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@536bd5c8, org.springframework.security.web.session.SessionManagementFilter@6e821dd, org.springframework.security.web.access.ExceptionTranslationFilter@ee945ca, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@71e52d8]
2017-12-30 12:26:06.087  INFO 2568 --- [           main] o.s.s.web.DefaultSecurityFilterChain     : Creating filter chain: Ant [pattern='/**'], [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@5495385e, org.springframework.security.web.context.SecurityContextPersistenceFilter@42dc6315, org.springframework.security.web.header.HeaderWriterFilter@4bbb85c, org.springframework.security.web.csrf.CsrfFilter@176128a0, org.springframework.security.web.authentication.logout.LogoutFilter@251b73cd, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@39482fad, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@60e81980, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@13f2ff3b, org.springframework.security.web.session.SessionManagementFilter@77b65000, org.springframework.security.web.access.ExceptionTranslationFilter@70316bc8, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@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.security.web.context.request.async.WebAsyncManagerIntegrationFilter@d30632, org.springframework.security.web.context.SecurityContextPersistenceFilter@2e0f239a, org.springframework.security.web.header.HeaderWriterFilter@4107644f, org.springframework.security.web.authentication.logout.LogoutFilter@4e0c1ebe, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@1948e716, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@6d8a60eb, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@17d54409, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@2edbd442, org.springframework.security.web.session.SessionManagementFilter@7e84e085, org.springframework.security.web.access.ExceptionTranslationFilter@5f4380b0, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@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)

 

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

References:

Spring boot  auth2.0 authentication server documentation 

Leave a Reply

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