On this page
Spring Security has evolved a lot regarding OAuth2 and OIDC. This tutorial shows how to let the framework validate a JWT and make use of claims in your API. Spring will validate the token and make sure the correct scope is used for the specific endpoint. The API can use the claims in the JWT to make additional decisions.
Note
Curity Identity Server is used in this example, but other OAuth servers can also be used.
Prerequisites
This tutorial covers the API side, meaning that how to obtain a JWT is out of scope.
Please look at the separate tutorial OIDC Client with Spring Security for information how to create a client using Spring Boot.
We assume the JWT contains the following scope, services:read
and the following claim, role=developer
or role=something else
.
Create a Spring Boot Application
We will create a simple Spring Boot application from scratch using Spring Initialzr, a website helping you to create a new Spring Boot application with the necessary dependencies.
Open start.spring.io in your browser to access Spring Initialzr.
In the configuration window that opens, select gradle
, enter io.curity.example
for the name of the group and call the artifact secureapi
.
Search for and add the following dependencies:
- Spring Web
- OAuth2 Resource Server

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.
More Dependencies
We have to add an extra dependency for us to be able to work with the JWT.
Open build.grade
and add implementation 'org.springframework.security:spring-security-oauth2-jose'
.
Adding a Controller
Now it is time to create our controller. Create the file src/main/java/io/curity/example/secureapi/ExampleController.java
.
Paste the following in the file:
package io.curity.example.secureapi;import org.springframework.security.core.annotation.AuthenticationPrincipal;import org.springframework.security.oauth2.jwt.Jwt;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import java.util.ArrayList;import java.util.List;@RestControllerpublic class ExampleController {@GetMapping("/services")public List<String> jwtProtected(@AuthenticationPrincipal Jwt jwt) {String role = jwt.getClaimAsString("role");return getServices("developer".equals(role));}private List<String> getServices(boolean developer) {List<String> services = new ArrayList<>();services.add("https://localhost/service/email");services.add("https://localhost/service/support");if (developer) {services.add("https://localhost/service/devportal");}return services;}}
This will create an endpoint /services
. It will return a list of URLs. If your JWT has a claim role
set to developer
you will have an extra URL returned.
Use Spring Security to Authorize the Request
For this tutorial the OpenID Connect metadata of the Curity Identity Server must be published. We will make use of the location of the OpenID Connect Provider to load the essential configuration for the integration. The Curity Identity Provider publishes the metadata at {issuerUri}/.well-known/openid-configuration
. We define the issuer URI as follows:
Parameter Name | Value in tutorial |
---|---|
OpenID Provider Issuer Uri | https://idsvr.example.com/oauth/v2/oauth-anonymous |
With this URL Spring Security will be able to find the public key to be able to validate the JWTs issued.
Make sure Curity Identity Server is up and running
Your Spring application will fetch the public key when starting up an will fail if there is no response.
Rename src/main/resources/application.properties
to application.yml
and paste this into it:
spring:security:oauth2:resourceserver:jwt:issuer-uri: https://idsvr.example.com/oauth/v2/oauth-anonymous
Then we create the src/main/java/io/curity/example/secureapi/SecurityConfiguration.java
and paste:
package io.curity.example.secureapi;import org.springframework.beans.factory.annotation.Value;import org.springframework.security.config.annotation.web.builders.HttpSecurity;import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;import org.springframework.security.oauth2.jwt.JwtDecoders;@EnableWebSecuritypublic class SecurityConfiguration extends WebSecurityConfigurerAdapter {@Value("${spring.security.oauth2.resourceserver.jwt.issuer-uri}")String issuerUri;@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests(authorizeRequests ->authorizeRequests.antMatchers("/services").hasAuthority("SCOPE_services:read").anyRequest().authenticated()).oauth2ResourceServer(oauth2ResourceServer ->oauth2ResourceServer.jwt(jwt ->jwt.decoder(JwtDecoders.fromIssuerLocation(issuerUri))));}}
This configuration will make sure that all requests are authenticated. It will also make sure that calls to /services
have the scope services:read
. Spring appends SCOPE_
to all scopes and add them as an authority.
Run the Demo Application
Start the Application in your IDE or by running ./gradlew bootRun
. The default configuration will start a listener on localhost:8080
.
Truststore issues
The Curity Identity Server ssl certificate must be trusted, otherwise your API will fail to introspect the token. Look at the jvm arguments -Djavax.net.ssl.trustStore
and -Djavax.net.ssl.trustStorePassword
on how to configure your trust store.
Get a JWT from your Curity Identity Server.
Test the API with your favorite tool. In cURL it would look something like this:
curl --request GET 'http://localhost:8080/services' \ --header 'Authorization: Bearer eyJraWQiOi...Gba'
Expected out is ["https://localhost/service/email","https://localhost/service/support","https://localhost/service/devportal"]
if you have the role
claim set to developer
.
Conclusion
By using Spring Security developing your APIs you can setup a convenient configuration for your authorization. The authorization decisions can be made base on both scopes and properties in claims.
In this tutorial we used the authority
concept of Spring Security. Another concept worth looking into is role
.
For further examples and help regarding OAuth2 and Spring Security visit Spring Security Reference.
Other tutorials regarding how to integrate Curity Identity Server with the Spring framework: