Search code examples
spring-bootspring-securityoauth-2.0azure-active-directory

Configuring spring-boot-starter-oauth2-client to authenticate with Azure AD


I want to add Azure AD as an OAuth2 provider in Spring Boot 2.4. I followed Spring Boot's OAuth2 docs and came up with the following configuration:

spring.security.oauth2.client.provider.azuread.issuer-uri=https://login.microsoftonline.com/<tenant uuid>/v2.0
spring.security.oauth2.client.registration.azuread.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.azuread.client-id=<client uuid>
spring.security.oauth2.client.registration.azuread.client-name=Azure AD
spring.security.oauth2.client.registration.azuread.client-secret=<client secret>
spring.security.oauth2.client.registration.azuread.provider=azuread
spring.security.oauth2.client.registration.azuread.scope=openid

Just for completeness, this is my web security configuration:

@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        http
            .authorizeRequests(a -> a
                .antMatchers("/", "/login", "/error", "/webjars/**").permitAll()
                .anyRequest().authenticated()
            )
            .oauth2Login();
        // @formatter:on
    }
}

When coming back from entering the credentials on https://login.microsoftonline.com, I get the following error:

[invalid_id_token] An error occurred while attempting to decode the Jwt: Signed JWT rejected: Another algorithm expected, or no matching key(s) found.

The problem originates in DefaultJWTProcessor.java from Nimus-JOSE-JWT.

Looking through the requests in Firefox's network inspector, Spring Boot picks up the right URLs from the Issuer URI. I'm at a loss what's going wrong and appreciate any pointers.


Solution

  • Azure AD has some pretty unintuitive (in my opinion) default behaviour - I think this is what you are experiencing:

    YOUR PROBLEM CAUSE (I THINK)

    • You are using standard OpenID Connect scopes
    • This causes Azure AD to issue an access token intended for the Graph API
    • This token fails standards based validation in Custom APIs since it is only designed for Graph APIs to use - it is recognisable by the nonce field in the JWT header

    WHAT YOU NEED TO DO

    • Expose an API scope such as 'default'
    • Use the full value of this scope in your web client, with a value such as 'api://cb398b43-96e8-48e6-8e8e-b168d5816c0e/default', where the long identifier is that of the API
    • You will then get a normal OAuth token that Spring can validate - with no nonce field in the JWT header

    FURTHER INFO