/kms-jwt

A Java library to sign and verify JSON Web Tokens (JWT) using Amazon Key Management Service (KMS)

Primary LanguageJavaApache License 2.0Apache-2.0

Java Version Download Codeship Status for julianghionoiu/kms-jwt Coverage Status

A Java library to sign and verify JSON Web Tokens (JWT) using Amazon Key Management Service (KMS) Inspired by codahale/kmssig https://github.com/codahale/kmssig

Token generation:

  • You construct a JWT with your claims
  • The JWT is signed with the HS256 algorithm using a newly generated symmetric key
  • The symmetric is encrypted using KMS and shared with the client as a JWT Header parameter (kid)

Token validation:

  • The header file is read and the encrypted key is extracted from the kid parameter
  • A call is made to KMS to decrypt the encrypted key
  • The decrypted key is then used to validate the JWT signature

More info about JWT: https://jwt.io/
More info about KMS: https://aws.amazon.com/documentation/kms/

To use as a library

Add as Maven dependency

Add a dependency to ro.ghionoiu:kms-jwt in compile scope. See bintray shield for latest release number.

<dependency>
  <groupId>ro.ghionoiu</groupId>
  <artifactId>kms-jwt</artifactId>
  <version>X.Y.Z</version>
</dependency>

Configure AWS user and KMS key

To run this you need:

For more info on IAM policies go to: http://docs.aws.amazon.com/kms/latest/developerguide/iam-policies.html#aws-managed-policies

To generate token

    AWSKMS kmsClient = AWSKMSClientBuilder.standard()
            .withRegion(region)
            .build();
    KMSEncrypt kmsEncrypt = new KMSEncrypt(kmsClient, keyARN);

    String jwt = JWTEncoder.builder(kmsEncrypt)
            .claim("usr", username)
            .claim("jrn", journey)
            .compact();
    System.out.println(jwt);

To validate token

    AWSKMS kmsClient = AWSKMSClientBuilder.standard()
            .withRegion(region)
            .build();
    KMSDecrypt kmsDecrypt = new KMSDecrypt(kmsClient, Collections.singleton(keyARN));

    Claims claims = new JWTDecoder(kmsDecrypt).decodeAndVerify(jwt);
    System.out.println(claims.get("usr"));

Development

Might need Java Cryptography Extension? https://cwiki.apache.org/confluence/display/STONEHENGE/Installing+Java+Cryptography+Extension+%28JCE%29+Unlimited+Strength+Jurisdiction+Policy+Files+6

Build and run as command-line app

./gradlew shadowJar
java -Dlogback.configurationFile=`pwd`/logback.xml  \
    -jar ./build/libs/kms-jwt-0.0.3-SNAPSHOT-all.jar \
    --region eu-west-2 \
    --key arn:aws:kms:eu-west-2:577770582757:key/7298331e-c199-4e15-9138-906d1c3d9363 \
    --username testuser \
    --journey "SUM,UPR"

Problems and solutions

On MAC, if Encoder spends around 5 seconds initialising, have a look at this: https://stackoverflow.com/questions/25321187/java-mac-getinstance-for-hmacsha1-slow