RogerParkinson
RogerParkinson

Reputation: 569

Why do I get SignatureVerificationException when trying to validate a JWT with PS256?

I'm trying to verify a signature on a JWT. This is (part of) my code:

DecodedJWT jwt = JWT.decode(token);
...
JwkProvider provider = new JwkProviderBuilder(jwksUrl).build();
Jwk jwk = provider.get(jwt.getKeyId());         
Algorithm algorithm = Algorithm.RSA256((RSAPublicKey) jwk.getPublicKey(), null);
algorithm.verify(jwt);

and I just get this error:

com.auth0.jwt.exceptions.SignatureVerificationException: The Token's Signature resulted invalid when verified using the Algorithm: SHA256withRSA

However I can see in the jwt the algorithm shows as PS256 rather than RSA256. Is this the problem? How can I get this to verify the JWT? There isn't an enum option for PS256 on Algorithm. saw somewhere that it might be RSASSA-PS but I don't see an option for that either

More info: The JWT is passed to me in an odd way by an external provider, it isn't just a bearer token in an HTTP header so I need to do this myself rather than relying on a framework to handle it. I'm using Java 17. Relevant dependencies:

        <dependency>
          <groupId>com.auth0</groupId>
          <artifactId>java-jwt</artifactId>
          <version>4.0.0</version>
        </dependency>
        <dependency>
          <groupId>com.auth0</groupId>
          <artifactId>jwks-rsa</artifactId>
          <version>0.21.2</version>
        </dependency>

Upvotes: 1

Views: 1333

Answers (1)

RogerParkinson
RogerParkinson

Reputation: 569

I worked out the answer using Baeldung but I did have to add some value of my own. Here's the solution:

DecodedJWT jwt = JWT.decode(token);
URL url = new
JwkProvider provider = new JwkProviderBuilder(jwksUrl)
  .build();
 Jwk jwk = provider.get(jwt.getKeyId());
SignatureAlgorithm sa = SignatureAlgorithm
  .forName(jwt.getAlgorithm());
DefaultJwtSignatureValidator validator = 
  new DefaultJwtSignatureValidator(sa, jwk.getPublicKey());
if (!validator.isValid(jwt.getHeader()+"."+jwt.getPayload(), jwt.getSignature())) {
    throw new Exception("Could not verify JWT token integrity!");
}

To make this work I had to add jjwt to my dependencies:

<dependency>
  <groupId>io.jsonwebtoken</groupId>
  <artifactId>jjwt</artifactId>
  <version>0.7.0</version>
</dependency>

The .forName() call means that it handles different algorithms, depending on what alg is specified in the JWT.

Upvotes: 1

Related Questions