azure AD spring boot token generation not valid signature

I am using Azure AD to carry out the users authentication of a spring boot app. I need to generate the token for some reasons from spring boot code and return it. So far this is what I have achieve.

1 Azure Ad config. I have config a app within azure Ad and I have register One user and one group. enter image description here -b enter image description here

within the app i also have create a secret

Now in my spring boot app i have added the JWT filter and some config (I am not going to explain the full config because it will take a while)

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@Profile("AzureAdSecurized")
public class AzureSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private RestAuthenticationExceptionHandler restAuthenticationExceptionHandler;

    @Autowired
    private AADAppRoleStatelessAuthenticationFilter aadAuthenticationFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.csrf().disable().sessionManagement().sessionCreationPolicy( SessionCreationPolicy.STATELESS );
        http.headers().frameOptions().disable();

        http.addFilterAfter(aadAuthenticationFilter, UsernamePasswordAuthenticationFilter.class );

        http.addFilterBefore( new CorsFilter(), ChannelProcessingFilter.class );

        http.exceptionHandling().authenticationEntryPoint( restAuthenticationExceptionHandler );

        //Configuracion Endpoints
        http.authorizeRequests().antMatchers( "/auth/login**" ).permitAll()
            .antMatchers( "/v2/api-docs", "/configuration/**", "/swagger*/**", "/webjars/**" ).permitAll()
            .antMatchers( "/actuator/**" ).permitAll().anyRequest().authenticated();
    }

I also have added the following properties:

azure:
  activedirectory:
    tenant-id: 7XXXXX
    client-id: 5XXXXX
    session-stateless: true

spring:
  security:
    oauth2:
      client:
        registration:
          azure:
            client-id: 5XXX
            client-secret: dXXXX

if I go to the following URL of microsoft: https://login.microsoftonline.com//oauth2/authorize?client_id=&response_type=id_token&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Flogin&nonce=7362CAEA-9CA5–4B43–9BA3–34D7C303EBA7

I get a perfect Token in a redirection like: http://localhost:8080/login#id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IllNRUxIVDBndmIwbXhvU0RvWWZvbWp

enter image description here

with this token I perfectly pass the aadAuthenticationFilter of spring boot security.

The point is that i have to generate this token from the app.

In my spring boot app I have algo add: I have follow a tutorial but i dont no remeber url

@RestController
@RequestMapping(LoginPaths.AUTH)
@Profile("AzureAdSecurized")
public class AADLoginController {

    private static final Logger LOG = LoggerFactory.getLogger( AADLoginController.class );

    @RequestMapping(value = LoginPaths.LOGIN, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public String generateTokenAzureAD() throws MalformedURLException, ExecutionException, InterruptedException {
        ExecutorService service = Executors.newFixedThreadPool( 1 );
        AuthenticationContext context = new AuthenticationContext(
            "https://login.microsoftonline.com/<My-tenant>/oauth2/v2.0/authorize", false,
            service );
        Future<AuthenticationResult> future = context
            .acquireToken( "https://graph.microsoft.com",
                "<app-id>", "<username>",
                "<pass>", null );
        AuthenticationResult result = future.get();
        LOG.info( "Access Token - " + result.getAccessToken() );
        LOG.info( "Refresh Token - " + result.getRefreshToken() );
        LOG.info( "ID Token - " + result.getIdToken() );
        return "Bearer " + result.getAccessToken();
    }
}

by passing username and password with classes of library "com.microsoft.aad.adal4j" I am trying to generate I token.

The token I receive is the following:

As you can see the token has information related with my user and so on and it seems to be correct, but the signature is not valid and if a send a request to my app with such token. obviously it gives me and error for invalid signature.

enter image description here

What I am doing wrong?

Thank you very much

Upvotes: 1

Views: 1998

Answers (2)

I am usisng the dependency instead:

<dependency>
            <groupId>com.microsoft.azure</groupId>
            <artifactId>msal4j</artifactId>
        </dependency>

And generating tokens this way:

public TokenDTO generateTokenAzureAD(CredentialsDTO credentialsDTO) {

        LoginValidator.validateLoginRequest( credentialsDTO );

        PublicClientApplication app;
        String AUTHORITY = authorityUrl + addTenantId;
        try {
            app = PublicClientApplication.builder( addAppId ).authority( AUTHORITY ).build();
        } catch (MalformedURLException e) {
            throw new MyException( ErrorCodes.ERROR_ADD_AUTHORITY_URL_NOT_VALID );
        }

        Set<String> scopes = Collections.singleton( addAppId + addAppScope );
        UserNamePasswordParameters parameters = UserNamePasswordParameters
            .builder( scopes, credentialsDTO.getUsername(), credentialsDTO.getPassword().toCharArray() ).build();

        Future<IAuthenticationResult> result = app.acquireToken( parameters );
        IAuthenticationResult auth;
        try {
            auth = result.get();
        } catch (InterruptedException | ExecutionException e) {
            throw new MyException( ErrorCodes.ERROR_ADD_AUTHORITY_URL_NOT_VALID );
        }

        return TokenUtils.fromAddAuthToTokenDTO( auth );
    }

Where

authorityUrl = https://login.microsoftonline.com/

addTenantId = azureID tenant

addAppId = azureID app ID

addAppScope = /User.Read

for scopes yo can create a new one in "Expose API" option of azure AD app menu

Thanks also to @TonyJu

Upvotes: 1

Tony Ju
Tony Ju

Reputation: 15619

Your token is correct. It is just a specific token for graph api. You will see a nonce in Jwt.Header. This means you need special processing. Normal processing will fail.

Update:

Access tokens are opaque blobs of text that are for the resource only. If you're a client getting a token for Graph, assume that it's an encrypted string that you should never look at - sometimes it will be. We use a special token format for Graph that they know how to validate - you shouldn't be looking at access tokens if they're not for you.

Reference:

https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/609#issuecomment-529537264

Upvotes: 1

Related Questions