Last active
April 12, 2018 05:33
-
-
Save tmaiaroto/e2ee5e88fc6ae035307d7c5ee71a99cf to your computer and use it in GitHub Desktop.
Example Cognito JWT Verification
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// The following pakcages are used by the function below | |
// https://github.com/dgrijalva/jwt-go | |
// https://github.com/lestrrat/go-jwx | |
// ParseAndVerifyJWT will parse and verify a JWT, if an error is returned the token is invalid, | |
// only a valid token will be returned. | |
// | |
// 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. | |
// - The audience ("aud") in the payload matches the app client ID created in the Cognito user pool. | |
func (c *CognitoAppClient) ParseAndVerifyJWT(t string) (*jwt.Token, error) { | |
// 3 tokens are returned from the Cognito TOKEN endpoint; "id_token" "access_token" and "refresh_token" | |
token, err := jwt.Parse(t, func(token *jwt.Token) (interface{}, error) { | |
// Looking up the key id will return an array of just one key | |
keys := c.WellKnownJWKs.LookupKeyID(token.Header["kid"].(string)) | |
if len(keys) == 0 { | |
log.Println("Failed to look up JWKs") | |
return nil, errors.New("could not find matching `kid` in well known tokens") | |
} | |
// Build the public RSA key | |
key, err := keys[0].Materialize() | |
if err != nil { | |
log.Printf("Failed to create public key: %s", err) | |
return nil, err | |
} | |
rsaPublicKey := key.(*rsa.PublicKey) | |
return rsaPublicKey, nil | |
}) | |
// Populated when you Parse/Verify a token | |
// First verify the token itself is a valid format | |
if err == nil && token.Valid { | |
if claims, ok := token.Claims.(jwt.MapClaims); ok { | |
// Then check time based claims; exp, iat, nbf | |
err = claims.Valid() | |
if err == nil { | |
// Then check that `aud` matches the app client id | |
// (if `aud` even exists on the token, second arg is a "required" option) | |
if claims.VerifyAudience(c.ClientID, false) { | |
return token, nil | |
} else { | |
err = errors.New("token audience does not match client id") | |
log.Println("Invalid audience for id token") | |
} | |
} else { | |
log.Println("Invalid claims for id token") | |
log.Println(err) | |
} | |
} | |
} else { | |
log.Println("Invalid token:", err) | |
} | |
return nil, err | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment