Search code examples
javaazurejwtaccess-tokennimbus-jose-jwt

Can't verify access token signature from azure using nimbus


following this example I wrote some code to validate an access token return by implicit flow from azure.

RemoteJWKSet remoteJWKSet = new RemoteJWKSet(new URL(jwksUri));
JWSKeySelector keySelector = new JWSVerificationKeySelector(JWSAlgorithm.RS256, remoteJWKSet);

ConfigurableJWTProcessor jwtProcessor = new DefaultJWTProcessor<>();

jwtProcessor.setJWTClaimsSetVerifier(new DefaultJWTClaimsVerifier(
      new JWTClaimsSet.Builder().issuer("https://sts.windows.net/3283e312-f73b-47d0-81c6-75e3ac726c21/").build(),
                new HashSet<>(Arrays.asList("sub", "iat", "exp", "scp"))));

jwtProcessor.setJWSKeySelector(keySelector);

JWTClaimsSet claimsSet = jwtProcessor.process(accessToken.getValue(), null);

But the verification fails and I get:

com.nimbusds.jose.proc.BadJWSException: Signed JWT rejected: Invalid signature
    at com.nimbusds.jwt.proc.DefaultJWTProcessor.process(DefaultJWTProcessor.java:378)
    at com.nimbusds.jwt.proc.DefaultJWTProcessor.process(DefaultJWTProcessor.java:303)
    at com.nimbusds.jwt.proc.DefaultJWTProcessor.process(DefaultJWTProcessor.java:294)

I think I don't need DefaultJWTClaimsVerifier part, but removing it doesn't change anything. I iust keept it to stick with the example.

Do you know why this happends?

Thanks for your help.

PS: Can't verify with jwt.io. I pasted access_token and the first entry from "keys" section from jwk.


Solution

  • You need to expose an API scope in Azure, and get the client to use that. Also ensure that there is no nonce field in the JWT header of the access token. My blog post has further info.

    AZURE AD BEHAVIOR

    The above behavior is quite specific to Microsoft, and is required when using Azure AD as a provider:

    • Tokens with a nonce field in the JWT header are designed only for MS APIs, eg Graph, and use an in-house validation mechanism. The intent is for these to always fail validation in custom APIs.

    • Tokens for your own custom APIs must be retrieved via clients that request custom scopes. Note that the OAuth client configured in Azure AD can be a logical entry, rather than needing to maintain one for each individual API.

    I believe the MS behavior is based on OAuth resource indicators, though my personal preference is to use more mainstream techniques of scopes, claims and audience checks when receiving access tokens in APIs.