Get ahead
VMware offers training and certification to turbo-charge your progress.
Learn moreToday, I'm excited to announce that you have a new superpower: creating applications with Spring Authorization Server on Spring Initializr!
That's right, it's time to begin your OAuth2 journey and become the hero you always knew you could be! In this post, I'll explain how you can get the most from your new superpower and where to go to learn more.
Spring Authorization Server is an open-source framework built on top of Spring Security that allows you to create your own standards-based OAuth2 Authorization Server or OpenID Connect Provider. It implements many of the protocol endpoints available in the various OAuth2 and OIDC-related specifications, allowing you to focus more on your applications and users and less on flows and specifications. Because it sits atop Spring Security, it can also be used to create an authentication hub for adapting other authentication protocols to OAuth2.
You can learn more about Spring Authorization Server in the Overview on the Reference Guide.
The journey to save the world from an evil creature attempting to extinguish all life has to start somewhere, and your journey to becoming an OAuth2 hero is no different! To get started, download this sample application or head to start.spring.io and add the OAuth2 Authorization Server dependency to your project.
Then, open the project in your favorite IDE and add the following to application.properties
:
spring.security.oauth2.authorizationserver.client.client-1.registration.client-id=admin-client
# the client secret is "secret" (without quotes)
spring.security.oauth2.authorizationserver.client.client-1.registration.client-secret={bcrypt}$2a$10$jdJGhzsiIqYFpjJiYWMl/eKDOd8vdyQis2aynmFN0dgJ53XvpzzwC
spring.security.oauth2.authorizationserver.client.client-1.registration.client-authentication-methods=client_secret_basic
spring.security.oauth2.authorizationserver.client.client-1.registration.authorization-grant-types=client_credentials
spring.security.oauth2.authorizationserver.client.client-1.registration.scopes=user.read,user.write
Alternatively, you can rename application.properties
to application.yml
and add the following:
spring:
security:
oauth2:
authorizationserver:
client:
client-1:
registration:
client-id: "admin-client"
# the client secret is "secret" (without quotes)
client-secret: "{bcrypt}$2a$10$jdJGhzsiIqYFpjJiYWMl/eKDOd8vdyQis2aynmFN0dgJ53XvpzzwC"
client-authentication-methods: "client_secret_basic"
authorization-grant-types: "client_credentials"
scopes: "user.read,user.write"
To start the application, run the following command:
./gradlew bootRun
This gives you an application with the following features out of the box:
Of course, there's more than this but you can check the feature list for the complete list.
So what can we do with this? Using the above example, we'll start with the Client Credentials flow which is the easiest to understand. I'll use HTTPie on the command line to demonstrate, and you can follow along at home (or work).
Run the following command:
http -f POST :8080/oauth2/token grant_type=client_credentials scope='user.read' -a admin-client:secret
This produces a response similar to the following:
{
"access_token": "eyJraWQiOiJhMWZjM2JhOC0zY2IwLTRkZjAtYTQwNS03ZDhhY2YxYTY4NGIiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJhZG1pbi1jbGllbnQiLCJhdWQiOiJhZG1pbi1jbGllbnQiLCJuYmYiOjE2ODQ1MjYzOTgsInNjb3BlIjpbInVzZXIucmVhZCJdLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAiLCJleHAiOjE2ODQ1MjY2OTgsImlhdCI6MTY4NDUyNjM5OH0.sHDGoQGDpdBuhvdiIpFeeCtTUeU860FBeV23rS6Zqb8tjq_Pytj_Y4Xl6pBB2R5rTAZdMg0cwLvICVYBz-x-hGz2UbHFtYGmo24byb3iKGqBb2BjtY5mMuYQOdnW_PgUVV4vtElhTYkkN_uET4CZ3zxIhgPEc2Yvtt0-d2lGwXzkDiHb_US1zDSUO36nqs4cesMD-yzy5tVmr1e2c6Klojyv6nFN1edfTn7Ci5GvEeB4lDnQdm3ZJr4fyxSiSrq7T34ghj6fMqYn_-lazpoc-wWPB5I35NM0TkUyDw2e_XobqIm6oXG0tBDujL2SK6P05n5MDKkGhgsQlT_ER9gmqA",
"expires_in": 299,
"scope": "user.read",
"token_type": "Bearer"
}
The access_token
in the response is a signed JWT that can be used to make an authenticated request to an OAuth2 resource server with the user.read
scope to access protected resources. In other words, with a Spring Boot app and just a few properties, we are able to easily mint signed JWTs and begin securing applications with OAuth2. Of course, it's equally trivial to set up a resource server with Spring Security, but I'll leave that up to you as a test of the superpowers you didn't know you had.
To keep things simple, let's test this token out using the Introspection Endpoint.
NOTE: Keep in mind that the token will expire after 5 minutes.
Run the following commands, making sure to paste the actual access_token
in place of the example:
export TOKEN=eyJraW...
http -f POST :8080/oauth2/introspect token=$TOKEN -a admin-client:secret
This produces a response similar to the following:
{
"active": true,
"aud": [
"admin-client"
],
"client_id": "admin-client",
"exp": 1684526698,
"iat": 1684526398,
"iss": "http://localhost:8080",
"nbf": 1684526398,
"scope": "user.read",
"sub": "admin-client",
"token_type": "Bearer"
}
If instead you see this response:
{
"active": false
}
then the token likely expired.
If you'd like to dive a little deeper and explore what's happening, you can enable trace logging to get additional debugging details. You can also shorten the expiration time of the token to something extremely short, like 30 seconds, to make it easier to get an expired token.
Add the following to your application.properties
:
logging.level.org.springframework.security=trace
spring.security.oauth2.authorizationserver.client.client-1.token.access-token-time-to-live=30s
Or if you're using application.yml
, add the following:
logging:
level:
org.springframework.security: trace
spring:
security:
oauth2:
authorizationserver:
client:
client-1:
registration:
...
token:
access-token-time-to-live: 30s
Then restart the application, and try the above steps again. After making the introspection request, you will see lines like:
FilterChainProxy : Trying to match request against DefaultSecurityFilterChain [...] (1/2)
FilterChainProxy : Securing POST /oauth2/introspect
FilterChainProxy : Invoking DisableEncodeUrlFilter (1/25)
...
There are two interesting things happening. Several lines later in the logs, you will see output like the following:
...
FilterChainProxy : Invoking OAuth2ClientAuthenticationFilter (14/25)
ProviderManager : Authenticating request with JwtClientAssertionAuthenticationProvider (1/18)
ProviderManager : Authenticating request with ClientSecretAuthenticationProvider (2/18)
ClientSecretAuthenticationProvider : Retrieved registered client
ClientSecretAuthenticationProvider : Validated client authentication parameters
ClientSecretAuthenticationProvider : Authenticated client secret
OAuth2ClientAuthenticationFilter : Set SecurityContextHolder authentication to OAuth2ClientAuthenticationToken
...
This tells us that the client (our own CLI) successfully authenticated with HTTP basic authentication via the ClientSecretAuthenticationProvider
. This is why we receive a 200 OK
response, but it would be nice to confirm via the logs that the token introspection request was successful. Several lines later, you will see output like this:
...
FilterChainProxy : Invoking OAuth2TokenIntrospectionEndpointFilter (22/25)
ProviderManager : Authenticating request with OAuth2TokenIntrospectionAuthenticationProvider (1/18)
TokenIntrospectionAuthenticationProvider : Retrieved authorization with token
TokenIntrospectionAuthenticationProvider : Did not introspect token since not active
...
Here we see the OAuth2TokenIntrospectionAuthenticationProvider
processing the request, but the token was not active. So, we can confirm that the request was successful and the token is expired.
We've only scratched the surface of what you can do with your new superpower! The main thing I hope you take away is that you can now use Spring Initializr to create your own personal OAuth2 and OpenID Connect playground with Spring Authorization Server.
When you're ready, I'd encourage you to read the Reference Guide which contains detailed information on each and every feature and configuration option available. I'd particularly recommend the guide How-to: Authenticate with Social Login as a great way to learn and explore.
Perhaps the best way to learn about OAuth2 and Spring Authorization Server is to build a sample OAuth2 architecture with (at least) three apps:
Take a look at the available samples which demonstrate all three of these apps, and try to build your own using nothing but Spring Initializr! Once you've accomplished that, the future is really up to you!
Now go save the world!
Project Page | GitHub Issues | ZenHub Board
Notes: