OpenID Connect Client with Spring Security
On this page
One of the key features of Spring Security 5 was the native support for OAuth2 and OIDC. Making use of the OIDC configuration information (OIDC metadata), integrating with the Curity Identity Server gets super easy. This tutorial shows how to use a registered OAuth client to login via Curity Identity Server and access the user details within an ID-token.
Note
This example is based on the Curity Identity Server, but any server that supports OIDC flows would do.
This tutorial illustrates two different ways for client authentication:
- Basic authentication with a client ID and client secret
- JWT client assertion with a client ID and client key pair
Prerequisites
Make sure you configure a client in the Curity Identity Server before getting started. You must be familiar with the following details:
- Client Id
- Client Secret
- Scopes
- Authorization Grant Type (Capability)
- Redirect URI
Commonly, the authorization server provides you with the client ID and secret as well as the supported scopes for the client. This tutorial runs a client with the Code Flow. Spring Boot generates the redirect URI automatically with the form {baseUrl}/login/oauth2/code/{registrationId}
.
In this example, the application is deployed locally and the following values apply:
Parameter Name | Value in Tutorial |
---|---|
Client ID | demo-basic-client |
Client Secret | Secr3t |
Scopes | openid, profile |
Authorization Grant Type | authorization_code |
Redirect Uri | http://localhost:8080/login/oauth2/code/demo-basic-client |
Provider | idsvr |
To configure a new client using basic authentication follow the tutorial here: Setup a Client.
Instead of creating the client manually you can merge the following XML with your current configuration.
<config xmlns="http://tail-f.com/ns/config/1.0"><profiles xmlns="https://curity.se/ns/conf/base"><profile><id>token-service</id><type xmlns:as="https://curity.se/ns/conf/profile/oauth">as:oauth-service</type><settings><authorization-server xmlns="https://curity.se/ns/conf/profile/oauth"><client-store><config-backed><client><id>demo-basic-client</id><secret>Secr3t</secret><redirect-uris>http://localhost:8080/login/oauth2/code/demo-basic-client</redirect-uris><scope>openid</scope><scope>profile</scope><user-authentication></user-authentication><capabilities><code/></capabilities><validate-port-on-loopback-interfaces>true</validate-port-on-loopback-interfaces></client></config-backed></client-store></authorization-server></settings></profile></profiles></config>
For this tutorial the OpenID Connect metadata of the Curity Identity Server must be published. Spring Boot makes use of the location of the OpenID Connect Provider to load the essential configuration for the integration. In this way you do not have to keep track of all the endpoints. The Curity Identity Server publishes the metadata at {issuerUri}/.well-known/openid-configuration
and the value for the issuer URI in this tutorial is as follows:
Parameter Name | Value in Tutorial |
---|---|
OpenID Provider Issuer Uri | https://idsvr.example.com/oauth/v2/oauth-anonymous |
Create a Spring Boot Application
Use the Spring Initializr to create a simple Spring Boot application from scratch. It is a website that assists you to create a new Spring Boot application with the necessary dependencies.
Open start.spring.io in your browser to access Spring Initializr.
In the configuration window that opens, enter io.curity.example
for the name of the group and call the artifact demo-client
.
Search for and add the following dependencies:
- Spring Security
- OAuth2 Client
- Spring Reactive Web
- Thymeleaf
Generate the application. Spring Initializr creates an archive with a bootstrap application that includes the selected dependencies. Download and extract the archive, and import the project in an IDE of your choice.
Add a Starting Site
Provide a starting site that is publicly available. Create the file src/main/resources/templates/index.html
. Add a link to the protected resource /user
.
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Spring Boot OIDC Demo</title></head><body><h1>Welcome</h1><p>Show me my <a href="/user">user name</a></p></body></html>
Add a Controller
When the user logs in show the username. For that create a controller that handles requests for the endpoint /
and /user
. Create the file src/java/main/io/curity/example/oidcClient/UserController.java
:
@Controllerpublic class UserController {@GetMapping("/")public String index(){return "index";}@GetMapping("/user")public String user(Model model,@AuthenticationPrincipal OidcUser oidcUser) {model.addAttribute("userName", oidcUser.getName());model.addAttribute("audience", oidcUser.getAudience());return "user";}}
For demonstration purpose, print out the application that triggered the login.
Create a template called user.html
next to index.html
. Output the attributes for the username and client ID.
<!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head><title>Spring Boot OIDC Demo - Login</title><meta charset="utf-8" /></head><body><h1>Your Login Details</h1><div>Welcome <span style="font-weight:bold" th:text="${userName}"/>!You logged in at the OAuth 2.0 Client <span style="font-weight:bold" th:text="${audience}"/>.</div></body></html>
Protect the User Area
So far there are two endpoints: /
and /user
. However, both are still unprotected. Create another class, that enforces OAuth for certain paths. Create the file src/java/main/io/curity/example/democlient/OAuth2SecurityConfig.java
with the following content:
@Configurationpublic class OAuth2SecurityConfig {@BeanSecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {http.authorizeExchange(exchanges ->exchanges.pathMatchers("/", "/error").permitAll().anyExchange().authenticated()).oauth2Login(withDefaults());return http.build();}}
This enables and configures Spring Web Security. The endpoints /
and /error
are public. Any other requests must be authenticated using OAuth. Spring Security creates a default login page at /login
that lists all the login options. When running the example from GitHub, there are two options:
- Login with the Curity Identity Server (Basic Client)
- Login with the Curity Identity Server (Private JWT Client)
Configure the OAuth Client
Define the following client in src/main/resources/application.yml
:
spring:security:oauth2:client:registration:demo-basic-client:client-name: Login with the Curity Identity Server (Basic Client)client-id: demo-basic-clientclient-secret: Secr3tauthorization-grant-type: authorization_coderedirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"scope: openid, profileprovider: idsvrprovider:idsvr:issuer-uri: https://idsvr.example.com/oauth/v2/oauth-anonymous
This triggers Spring Boot to register a client. The client registration gets the id demo-basic-client
which is part of the (default) redirect-uri
.
The remaining properties, client-id
, client-secret
, authorization-grant-type
and scope
, have been defined when configuring the client in the Curity Identity Server (see Prerequisites). You can choose any descriptive client-name
. This is the string that is used in the default login page setup at /login
.
Spring Boot Security loads all the necessary OpenID configuration from the metadata at https://idsvr.example.com/oauth/v2/oauth-anonymous/.well-known/openid-configuration
and ensures that the user-agent gets redirected to the right endpoints for authentication.
Run the Demo Application
Start the demo application with ./gradlew bootRun
Navigate to http://localhost:8080
to access the index site.
Click on the link to access http://localhost:8080/user
that triggers a login.
After successful login the page shows details retrieved from the ID token.
You can also navigate to http://localhost:8080/login
to directly access the default login page created by Spring Security.
Conclusion
Using Spring Security together with the Curity Identity Server you can easily secure your application with OAuth2 and OpenID Connect. As a developer you only have to add a client registration using the parameters received from an administrator of the Curity Identity Server and enable OAuth2 support for your application. You can access any attributes in the ID token through @AuthenticationPrincipal
and OidcUser.class
or use @RegisteredOAuth2AuthorizedClient
and OAuth2AuthorizedClient.class
for retrieving the access token obtained by the client that you may forward to downstream APIs.
For further examples and help regarding OAuth2 and Spring Security for a reactive web application visit Spring Security Reference Documentation.
Also check out the tutorial on mutual TLS client authentication using Spring Boot: OIDC Client with Mutual TLS Client Authentication
Join our Newsletter
Get the latest on identity management, API Security and authentication straight to your inbox.
Start Free Trial
Try the Curity Identity Server for Free. Get up and running in 10 minutes.
Start Free Trial