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

Viewed 7523

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.

3 Answers

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

I had a similar problem and if I remember correctly there was an issue with scope. Don't know whether this is also your issue but in any case following configuration is working for me (note I'm using client credentials not auth code):

spring:
  security:
    oauth2:
      client:
        provider:
          azure:
            token-uri: https://login.microsoftonline.com/${custom.azure.account.tenant-id}/oauth2/token
        registration:
          azure:
            client-id: ${custom.azure.service-principal.client-id}
            client-secret: ${custom.azure.service-principal.client-secret}
            authorization-grant-type: client_credentials
            scope:
              - https://graph.microsoft.com/.default

According to your description, it seems that you wanna use azure ad as the an OAuth2 provider in Spring Boot, and I found a doc said that 'Spring Starter for Azure Active Directory (AD) is now integrated with Spring Security 5.0'. It also offered a sample of springboot web app. I also tried it and it did work.

What I think need to note is, the tutorial said the redirect url setted in azure ad is 'http://localhost:8080/login/oauth2/code/', but when my tested, it proved to be 'http://localhost:8080/login/oauth2/code/azure'.

enter image description here

Upon your error, I'm not sure but maybe you can change your configuration of 'scope' to 'openid,profile,offline_access'.

Related