Skip to content

Instantly share code, notes, and snippets.

@tmaiaroto
Last active April 12, 2018 05:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tmaiaroto/e2ee5e88fc6ae035307d7c5ee71a99cf to your computer and use it in GitHub Desktop.
Save tmaiaroto/e2ee5e88fc6ae035307d7c5ee71a99cf to your computer and use it in GitHub Desktop.
Example Cognito JWT Verification
// 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