I have a Spring Boot application where I'm trying to filter the incoming Access Token based on the roles defined in our Azure Active Directory. The Access Token validates correctly, but I seem unable to filter on the roles.
What am I missing? Do I need to add my own filtering of the incoming Access Token for Spring to detect the roles?
Debug output:
[nio-8444-exec-3] o.s.security.web.FilterChainProxy : Securing GET /api/v1/control/list
[nio-8444-exec-3] s.s.w.c.SecurityContextPersistenceFilter : Set SecurityContextHolder to empty SecurityContext
[nio-8444-exec-3] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to common.controller.ControlRestController#getControlList(Integer, Integer, String, String)
[nio-8444-exec-3] o.s.web.client.RestTemplate : HTTP GET https://login.windows.net/common/discovery/keys
[nio-8444-exec-3] o.s.web.client.RestTemplate : Accept=[text/plain, application/json, application/*+json, */*]
[nio-8444-exec-3] o.s.web.client.RestTemplate : Response 200 OK
[nio-8444-exec-3] o.s.web.client.RestTemplate : Reading to [java.lang.String] as "application/json;charset=utf-8"
[nio-8444-exec-3] o.s.s.o.s.r.a.JwtAuthenticationProvider : Authenticated token
[nio-8444-exec-3] .o.s.r.w.BearerTokenAuthenticationFilter : Set SecurityContextHolder to JwtAuthenticationToken [Principal=org.springframework.security.oauth2.jwt.Jwt@f884058d, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=null], Granted Authorities=[SCOPE_User.Read]]
[nio-8444-exec-3] o.s.s.w.a.i.FilterSecurityInterceptor : Failed to authorize filter invocation [GET /api/v1/control/list] with attributes [hasAnyRole('Role-1')]
[nio-8444-exec-3] s.s.w.c.SecurityContextPersistenceFilter : Cleared SecurityContextHolder to complete request
Web Security Configurer:
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
public class JWTSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and()
.authorizeRequests().antMatchers("**").hasAnyRole("Role-1")
.and()
.oauth2ResourceServer().jwt();
}
}
Dependencies in application.properties:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>${spring-security.version}</version>
</dependency>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>azure-spring-boot-starter-active-directory</artifactId>
<version>3.9.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
<version>2.5.5</version>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
Example of Access Token payload:
{
"aud": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"iss": "https://sts.windows.net/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/",
"iat": 1637836195,
"nbf": 1637836195,
"exp": 1637840650,
"acr": "1",
"aio": "AVQAq/8TAAAA8y1Ih2o5+C1xcchX2nVt1PllQ8jEQGrO5iqhuS0sTQ75E7oB2wpYBV2nOHgv+gTfWjyKcd8pMAE/F6+QTQ2U8Q1Oz2mP1i9BCuG0rIyEj00=",
"amr": [
"pwd",
"mfa"
],
"appid": "xxxxxxxx-xxxx-xxxx-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"appidacr": "1",
"family_name": "Doe",
"given_name": "John",
"ipaddr": "x.x.x.x",
"name": "Doe John",
"oid": "b590b433-b825-4ff2-8efc-b705e8d41408",
"onprem_sid": "S-1-9-25-2282756759-60046336-13015914-96287",
"rh": "0.AXMAnEh5FnJct0a6Y5q5DEqtRKvm2tigXA1PmabHelrn8M5zAI8.",
"roles": [
"Role-1",
"Role-2"
],
"scp": "User.Read",
"sub": "Se1ew9fPjO-ltCQBTEftFQBycjNRzD1YZ1aHqqerx-A",
"tid": "xxxxxxxx-xxxx-xxx-xxxxxxxxxxxxxxxxx",
"unique_name": "john@doe.com",
"upn": "john@doe.com",
"uti": "z_ugyP6aH1Sje8bFQl1rAA",
"ver": "1.0"
}