Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any java example of verification of JWT for aws cognito API?

Tags:

I am using aws cognito user pool, after user signed in, I got an id token at my single page application, which is expected, then for each request, I need to verify the id token at my backend rest API, which is in java, the aws doc didn't mention too much about how to do it.

Is there any example for it?

Confusions include:

  1. the id token seems not just a signed JWT, it's also encrypted, when use nimbus library, I need to specify a secret for an encrypted JWT, where can I get the secret? my understanding is this should come from aws, do I needed to download something and then put in my jvm keystore?

  2. there is a well-known jwts.json can be downloaded from aws, it looks like:

`

{     "keys": [         {             "alg": "RS256",             "e": "AQAB",             "kid": "HFPWHdsrG5WyulOwH5dai69YTsWz2KBB1NHbAcVx7M0=",             "kty": "RSA",             "n": "...",             "use": "sig"         },         {             "alg": "RS256",             "e": "AQAB",             "kid": "kSwTdVq/qD4Ra4Q8dJqUTlvOA7eiLxezOZ3mJKI61zU=",             "kty": "RSA",             "n": "....",             "use": "sig"         }     ] } 

`

how to understand this, what does each property used for? is that every user in the user pool represents one key?

  1. Is there any example java code for the aws cognito service verification, can I use aws sdk or I have to use library like nimbus to do the verification on my own?
like image 542
Jakim Avatar asked Jan 20 '18 12:01

Jakim


People also ask

How do you verify JWT from AWS Cognito in the API backend?

To verify the signature of a JWT token You can use AWS Lambda to decode user pool JWTs. For more information, see Decode and verify Amazon Cognito JWT tokens using AWS Lambda . The OpenID Foundation also maintains a list of libraries for working with JWT tokens . Compare the local key ID ( kid ) to the public kid.

How can I decode and verify the signature of an Amazon Cognito JSON Web Token?

To verify the signature of an Amazon Cognito JWT, search for the key with a key ID that matches the key ID of the JWT, then use libraries to decode the token and verify the signature. Be sure to also verify that: The token is not expired.

How JWT token is verified?

When validating a JWT, generally, the current hash value and the original hash value are parsed, or decoded, then compared to verify the token signature is authentic. All of our backend API quickstarts use SDKs that perform JWT validation and parsing for you.


1 Answers

I just struggled with this and thought I share it.

If you use maven add this to your pom.xml

<dependency>     <groupId>com.auth0</groupId>     <artifactId>java-jwt</artifactId>     <version>3.3.0</version> </dependency> <dependency>     <groupId>com.auth0</groupId>     <artifactId>jwks-rsa</artifactId>     <version>0.4.0</version> </dependency> 

If you use gradle add

compile 'com.auth0:jwks-rsa:0.4.0' compile 'com.auth0:java-jwt:3.3.0' 

Create a class that implements RSAKeyProvider

import com.auth0.jwk.JwkException; import com.auth0.jwk.JwkProvider; import com.auth0.jwk.JwkProviderBuilder; import com.auth0.jwt.interfaces.RSAKeyProvider;  import java.net.MalformedURLException; import java.net.URL; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey;  public class AwsCognitoRSAKeyProvider implements RSAKeyProvider {      private final URL aws_kid_store_url;     private final JwkProvider provider;      public AwsCognitoRSAKeyProvider(String aws_cognito_region, String aws_user_pools_id) {         String url = String.format("https://cognito-idp.%s.amazonaws.com/%s/.well-known/jwks.json", aws_cognito_region, aws_user_pools_id);         try {             aws_kid_store_url = new URL(url);         } catch (MalformedURLException e) {             throw new RuntimeException(String.format("Invalid URL provided, URL=%s", url));         }         provider = new JwkProviderBuilder(aws_kid_store_url).build();     }       @Override     public RSAPublicKey getPublicKeyById(String kid) {         try {             return (RSAPublicKey) provider.get(kid).getPublicKey();         } catch (JwkException e) {             throw new RuntimeException(String.format("Failed to get JWT kid=%s from aws_kid_store_url=%s", kid, aws_kid_store_url));         }     }      @Override     public RSAPrivateKey getPrivateKey() {         return null;     }      @Override     public String getPrivateKeyId() {         return null;     } } 

Now you can verify your token by

String aws_cognito_region = "us-east-1"; // Replace this with your aws cognito region String aws_user_pools_id = "us-east-1_7DEw1nt5r"; // Replace this with your aws user pools id RSAKeyProvider keyProvider = new AwsCognitoRSAKeyProvider(aws_cognito_region, aws_user_pools_id); Algorithm algorithm = Algorithm.RSA256(keyProvider); JWTVerifier jwtVerifier = JWT.require(algorithm)     //.withAudience("2qm9sgg2kh21masuas88vjc9se") // Validate your apps audience if needed     .build();  String token = "eyJraWQiOiJjdE.eyJzdWIiOiI5NTMxN2E.VX819z1A1rJij2"; // Replace this with your JWT token jwtVerifier.verify(token); 

Note that JwkProviderBuilder will build a JwkProvider with a LRU cache that caches keys retreived from the aws key store which is quite neat! The cache rules can be change with the builder.

[UPDATE] Moved creation JwkProvider to constructor so caching is respected as @danieln commented

like image 112
AndiDev Avatar answered Sep 21 '22 17:09

AndiDev