0

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.

Ace of Spade
  • 388
  • 3
  • 22

1 Answers1

2

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.

Ace of Spade
  • 388
  • 3
  • 22
Gary Archer
  • 22,534
  • 2
  • 12
  • 24
  • Changing the issuer didn't help. I looked up your blog post but I don't understand why I can't verify a token with a nonce. What is the point of a nonce if I can't verify it? – Ace of Spade Mar 02 '22 at 07:41
  • I don't know why but the scope fixed my problem. My issuer was correct, if you update your answer I will accept it. Bonus points if you can explain why I need to add the scope. – Ace of Spade Mar 02 '22 at 10:02
  • It is MS specific behavior, and a little unusual - I have always found it a little unintuitive though it is related to standards. You have to accept it when using Azure AD. I added some more background to my answer. – Gary Archer Mar 02 '22 at 10:25