VOOZH about

URL: https://dzone.com/articles/spring-oauth-server-default-configuration

⇱ Spring OAuth Server: Default Configuration


Related

  1. DZone
  2. Software Design and Architecture
  3. Security
  4. Spring OAuth Server: Default Configuration

Spring OAuth Server: Default Configuration

Explore Spring Authorization server's default configuration: registration of new clients, testing endpoints, JWT customization, and reference/self-contained tokens.

By Nov. 10, 23 · Tutorial
Likes
Comment
Save
7.3K Views

Join the DZone community and get the full member experience.

Join For Free

Spring has come out with an OAuth2 solution, and in this article, we will look at the default configuration that comes bundled with the spring-oauth server. Details about how OAuth2.0 works are out of the scope of this article and the audience of this article is expected to have a basic understanding of it. You can find more details on it here.

In this and other articles, I will talk more about the technical aspects of the Spring OAuth2.0 solution.

Default Configuration

Spring OAuth server comes with some default settings. One can customize it by configuring the server/clients in the application.yml config file. The following flows (grant types) are supported:

  1. Client Credentials flow (/oauth2/token endpoint)
  2. Authorization Code flow (Including PKCE)
  3. Resource Owner Credential Flow (Deprecated)
  4. Implicit flow (Code flow without code :))
  5. Device Authorization flow

Details around the configuration can be found at the GitHub. This is a sample codebase. 

Regarding default configuration, you can refer to the server configuration here where we can see how configuration can be done to use the default server configuration.

AuthorizationServerTest can be referred to see how we can verify different endpoints through functional testing. To make this test run successfully, the OAuth server should be running. To run the server, you can use the AuthorizationServerApplication class using IDE or from the command prompt as well using the command below:

Shell
mvn spring-boot:run


Let's look at the sample client "spring" (you can name it anything you want to) configuration and talk about the significance of each property below.

YAML
spring:
 security:
 oauth2:
 authorizationserver:
 client:
 spring:
 registration:
 client-id: "spring-test" #The name to be used in different configurations to refer this client. 
 client-secret: "sMJ1ltm5wxdcOeEJGaE6WdFj9ArR75wkBqUgVE7vwwo=" ##Using D3PasswordEncoder
 client-authentication-methods: #methods supported to authenticate the client
 - "client_secret_basic"
 - "client_secret_post"
 authorization-grant-types: #The flows this client support
 - "authorization_code"
 - "refresh_token"
 - "client_credentials"
 redirect-uris: # The Url to be used at the end of successful authentication 
 - "https://127.0.0.1:9443/"
 - "https://127.0.0.1:9443/login/oauth2/code/spring"
 post-logout-redirect-uris:
 - "http://127.0.0.1:8080/"
 scopes:
 - "openid"
 - "profile"
 - "email"
 require-authorization-consent: true


  • client-id: A unique ID assigned to the client; it will be used to identify the client and configuration whenever the client makes a call to the authorization server.
  • client-secret: Secret to be used by the client to authenticate itself when making a call to the authorization server
  • client-authentication-methods: Authentication methods that the client uses to authenticate itself
    • client_secret_basic: Basic authentication approach where credentials are provided as headers (httpHeaders -> httpHeaders.setBasicAuth(TEST_CLIENT_ID, TEST_SECRET))
    • client_secret_post: Authentication by providing credentials in the request body (application/x-www-form-urlencoded)
  • authorization-grant-types: The grant types supported by the client
  • redirect-uris: The redirect-uri(s) that is/are supported by the client and allow redirects that the client can use while starting the authorize_code flow
  • post-logout-redirect-uris:  redirect-uri(s) after successful logout from openId
  • scopes: Supported scopes by the client
  • require-authorization-consent: If consent is required during the authorization code flow

Some of the default configurations that are good to know and not there by default in different examples are:

  1. Access token format by default is self-contained (jwt) and can be configured to opaque (reference) token through configuration.
  2. The refresh token TTL is 60min.
  3. The access token TTL is 5min.
  4. The authorization code TTL is 5min.
  5. The consent form is disabled by default.

We can override the above default behavior by overriding the configuration in the application.yml file as:

YAML
spring:
 security:
 oauth2:
 authorizationserver:
 client:
 spring-client:
 require-authorization-consent: true
 token:
 access-token-format: reference
 authorization-code-time-to-live: PT10M
 access-token-time-to-live: PT10M
 refresh-token-time-to-live: PT2H


Default Security FilterChain

Sometimes I think about how the security framework is configured to make it work, so here is what I tried to put together on how the application is configured using different configurations, filters, and properties to make it work.

Starting With Application FilterChain

Filters(5):

  1. ApplicationFilterConfig (characterEncodingFilter)
  2. ApplicationFilterConfig (formContentFilter)
  3. ApplicationFilterConfig (requestContextFilter)
  4. ApplicationFilterConfig (springSecurityFilterChain)
  5. ApplicationFilterConfig (Tomcat WebsocketFilter-JSR356)

ApplicationFilterConfig (springSecurityFilterChain)

Application filter config "springSecurityFilterChain" is the main class that holds the filter (Spring Security) instances which are instantiated when a web application is started.

The filter instance it (springSecurityFilterChain-ApplicationFilterConfig) holds is DelegatingFilterProxyRegistrationBean. DelegatingFilterProxyRegistrationBean is a ServletContextInitializer; it registers DelegatingFilterProxy and holds the name of the actual delegate.

Filter (DelegatingFilterProxyRegistrationBean) [springSecurityFilterChain urls=[/*] order=-100]:

Java
public class DelegatingFilterProxyRegistrationBean
extends AbstractFilterRegistrationBean<DelegatingFilterProxy>
implements ApplicationContextAware


DelegatingFilterProxy

Spring provided filter implementation, a bridge between the servlet container and Spring's ApplicationContext.

  • TargetBeanName: springSecurityFilterChain
  • Delegate: FilterChainProxy 

FilterChainProxy

This holds the Spring Security filter chain(s). Concerning the OAuth authorization server, there are two security filter chains (DefaultSecurityFilterChain): one for the OAuth endpoint and one for the rest.

  • FilterChains: An overview of the oauth2filter chain
    • DefaultSecurityFilterChain (OAuth2 endpoints)
    • RequestMatcher (OAuth2AuthorizationServerConfigurer)
Plain Text
Or [
 OAuth2ClientuthenticationConfigurer
 Or [ 
 Ant [pattern='/oauth2/token', POST], 
 Ant [pattern='/oauth2/introspect', POST], 
 Ant [pattern='/oauth2/revoke', POST], 
 Ant [pattern='/oauth2/device_authorization', POST]
 ], 
 OAuth2AuthorizationServerMetadataEndpointConfigurer
 Ant [pattern='/.well-known/oauth-authorization-server', GET], 
 OAuth2AuthorizationEndpointConfigurer
 Or [
 Ant [pattern='/oauth2/authorize', GET], 
 Ant [pattern='/oauth2/authorize', POST]
 ], 
 OAuth2TokenEndpointConfigurer
 Ant [pattern='/oauth2/token', POST], 
 OAuth2TokenIntrospectionEndpointConfigurer
 Ant [pattern='/oauth2/introspect', POST], 
 OAuth2TokenRevocationEndpointConfigurer
 Ant [pattern='/oauth2/revoke', POST], 
 OAuth2DeviceAuthorizationEndpointConfigurer
 Ant [pattern='/oauth2/device_authorization', POST], 
 OAuth2DeviceVerificationEndpointConfigurer
 Or [
 Ant [pattern='/oauth2/device_verification', GET], 
 Ant [pattern='/oauth2/device_verification', POST]
 ], 
 OidcConfigurer
 Or [
 OidcProviderConfigurationEndpointConfigurer
 Ant [pattern='/.well-known/openid-configuration', GET], 
 OidcLogoutEndpointConfigurer
 Or [
 Ant [pattern='/connect/logout', GET], 
 Ant [pattern='/connect/logout', POST]
 ], 
 OidcUserInfoEndpointConfigurer
 Or [
 Ant [pattern='/userinfo', GET], 
 Ant [pattern='/userinfo', POST]]
 ], 
 NimbusJwkSetEndpointFilter
 Ant [pattern='/oauth2/jwks', GET]
  ]


  • Filters (25)
Plain Text
0 = {DisableEncodeUrlFilter} 
1 = {WebAsyncManagerIntegrationFilter} 
2 = {SecurityContextHolderFilter} 
3 = {AuthorizationServerContextFilter} 
4 = {HeaderWriterFilter} 
5 = {CsrfFilter} 
6 = {OidcLogoutEndpointFilter} 
7 = {LogoutFilter} 
8 = {OAuth2AuthorizationServerMetadataEndpointFilter} 
9 = {OAuth2AuthorizationEndpointFilter} 
10 = {OAuth2DeviceVerificationEndpointFilter} 
11 = {OidcProviderConfigurationEndpointFilter} 
12 = {NimbusJwkSetEndpointFilter} 
13 = {OAuth2ClientAuthenticationFilter} 
14 = {BearerTokenAuthenticationFilter} 
15 = {RequestCacheAwareFilter} 
16 = {SecurityContextHolderAwareRequestFilter} 
17 = {AnonymousAuthenticationFilter} 
18 = {ExceptionTranslationFilter} 
19 = {AuthorizationFilter} 
20 = {OAuth2TokenEndpointFilter} 
21 = {OAuth2TokenIntrospectionEndpointFilter} 
22 = {OAuth2TokenRevocationEndpointFilter} 
23 = {OAuth2DeviceAuthorizationEndpointFilter} 
24 = {OidcUserInfoEndpointFilter} 


  • DefaultSecurityFilterChain (other endpoints)
    • RequestMatcher (AnyRequestMatcher)
    • Filters (14)
Plain Text
0 = {DisableEncodeUrlFilter@8893} 
1 = {WebAsyncManagerIntegrationFilter@8894} 
2 = {SecurityContextHolderFilter@8895} 
3 = {HeaderWriterFilter@8896} 
4 = {CsrfFilter@8897} 
5 = {LogoutFilter@8898} 
6 = {UsernamePasswordAuthenticationFilter@8899} 
7 = {DefaultLoginPageGeneratingFilter@8900} 
8 = {DefaultLogoutPageGeneratingFilter@8901} 
9 = {RequestCacheAwareFilter@8902} 
10 = {SecurityContextHolderAwareRequestFilter@8903} 
11 = {AnonymousAuthenticationFilter@8904} 
12 = {ExceptionTranslationFilter@8905} 
13 = {AuthorizationFilter@8906} 


Default Response

Token Endpoint

By default, the token response for the /oauth2/token endpoint will be:

JSON
{
 "access_token":"eyJraWQiOiJiOTM0NjIyMy00ZWJiLTQyZjItYTAyYy1hNDlkNDQwOWRlMjEiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjYwNjAiLCJzdWIiOiJzcHJpbmctdGVzdCIsImF1ZCI6InNwcmluZy10ZXN0IiwibmJmIjoxNjk3MTgzODU2LCJleHAiOjE2OTcxODQxNTYsImlhdCI6MTY5NzE4Mzg1Nn0.KzYvm4YAuLRvpF9eco-z1ESbYU-MCChvxbdEPuGgQN-8seco8MgLWWoGM4dbbMRBJLe3Rv3YAEGhJ9qqenNtpFmVnysAUFqw_S8GEUpPlXzzRTnV_qoeqY9YVazCn9TonJJkjzj_RATTHgDx4TD6ZXSP963L5fwNjLtQ2Cp_yoi5R8WDgMkpvOubmuhjAxYpRH7rBH3qzNWo3vqRPuWreeoyaRyK-9HNOTKxT3vj7aLkTK1wyxzfPxliXXXMJ4IsxjxUOTfzzfHF9qmOYZCoCCgVtNlopsSKmjJKRID8UVugzmYQx1pZkUSPMOxiz1AloEX1-6DhgoC3lMi0-Ez6pQ",
 "token_type":"Bearer",
 "expires_in":299
}


If you parse the access_token using https://jwt.io/, you can view the claims issued in the token. The default set of claims are:

JSON
{
 "iss": "http://localhost:6060",
 "sub": "spring-test",
 "aud": "spring-test",
 "nbf": 1697183856,
 "exp": 1697184156,
 "iat": 1697183856
}


Metadata Endpoints

1. http://localhost:6060/.well-known/oauth-authorization-server

2. http://localhost:6060/.well-known/openid-configuration

Metadata endpoints provide the details around the authorization-server and openId current configuration and endpoints exposed. 

Code Flow Token response (/oauth2/token)

JSON
{
 "access_token":"eyJraWQiOiI4M2ZiMmRhYy1hZGNlLTRkNzgtODlhYy0wOGQzM2U3OGRmNGMiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ1c2VyMSIsImF1ZCI6InNwcmluZy10ZXN0IiwibmJmIjoxNjk4MTUxODMzLCJzY29wZSI6WyJvcGVuaWQiLCJwcm9maWxlIl0sImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6NjA2MCIsImV4cCI6MTY5ODE1MjEzMywiaWF0IjoxNjk4MTUxODMzfQ.jbNg1MyrL-9kHpfhhkarNfSq1VuS3fPJUZyXjSaliuaziKZzSrma2OyUtVrrPJYzv7FMk-pGrTZVJLZ8f6Jayq2IbHkuWl2XYexRRQmUUDSeC3WMxDhWqezqRc-AEyrTQXm2d0HNs0zdJX9H28bSpGg_SADuKuN-vLuFp3_5w2utveuYxq1e2Ts-IXE-9ulf9O19Mj0Wf9hgENTOZiKbqUWvvoZwXhsx4LzPXqGKM0MbZTS6kFpdSZIgzcbaPzcMX_Vq_B2AU9_UAlJua2Vzxh-9rdJ7SPDVxT-ezoUGp61c1s5eDop2zNszjDqd7kE4qepCiJy6bUuwvP7yewdreg",
 "refresh_token":"ARM4_nA8LFzFajbTOzJjN1OTGByZAFu9HGoDeZ9mfciY9vEv5XbWc7MuzcQnAArZMMnB_ydsCxsLRC4HY4u0oh9DscHySysYPXb1BE-7JBwcdH_hVKM3pXWmO4NEiDY",
 "scope":"openid profile",
 "id_token":"eyJraWQiOiI4M2ZiMmRhYy1hZGNlLTRkNzgtODlhYy0wOGQzM2U3OGRmNGMiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ1c2VyMSIsImF1ZCI6InNwcmluZy10ZXN0IiwiYXpwIjoic3ByaW5nLXRlc3QiLCJhdXRoX3RpbWUiOjE2OTgxNTE4MzMsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6NjA2MCIsImV4cCI6MTY5ODE1MzYzMywiaWF0IjoxNjk4MTUxODMzLCJzaWQiOiJfVmYzY1ZTREd1UDQtMEN6czNzR1BxQTZkaUk1ZjB1TE1pT1BkUzd3Z0c4In0.QDHOUa2p8RZKHVuhnHUsvMX-HmEvsGXXQ6QgfidXEMO0vDxJilmYIWW90z9Etc2cJ1SjfFk4OrUZWQF2foa2secatuAeffTbUx_9lTPD4KT_xzg9SsP69tHt55J2U35FcFef2WHuGF06MOj2hr6dVqlk8B5ORV0z_XiBM9FBEmnraLvXWtXtlwp_-jGA95O7y2U8SZt9H8wns-IpatXshB8lnUk-P5NjV8-CUwqtb9FHKOr9ie4KSXHQ8IpY2FaBMI0nA4E_hCUV2xpP_nBAb7Prh5EDYoCFkjHtO5ZXe-VYhyff9AydPzFsdSmEeF6BEK6SeJPBXRUvtL_bZykjdA",
 "token_type":"Bearer",
 "expires_in":299
}


In the code flow at the end of the flow when code is issued to the client at redirect_uri, the backend service will collect the code and call the token endpoint /oauth2/token.

Introspection Response When the Token Is Active

JSON
{
	"active": true,
	"client_id": "spring-test",
	"iat": 1698151833,
	"exp": 1698155433
}


Introspection Response Post Revoke

JSON
{
	"active": false,
	"iat": 0,
	"exp": 0
}


I hope you found this article informative. I will put more details in another post on how to customize the token response by adding new claims to JWT.

Integrated development environment authentication JWT (JSON Web Token) security

Opinions expressed by DZone contributors are their own.

Related

  • Secure Your API With JWT: Kong OpenID Connect
  • Securing REST APIs With Nest.js: A Step-by-Step Guide
  • Navigating the API Seas: A Product Manager's Guide to Authentication
  • Spring OAuth Server: Token Claim Customization

Partner Resources

×

Comments

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

Let's be friends: