Skip to content
This repository has been archived by the owner on May 21, 2022. It is now read-only.

Add an example for parsing RS256 tokens #438

Open
mieubrisse opened this issue Oct 24, 2020 · 4 comments
Open

Add an example for parsing RS256 tokens #438

mieubrisse opened this issue Oct 24, 2020 · 4 comments

Comments

@mieubrisse
Copy link

The major point of confusion comes from what the key func should be returning, since the examples only have HS256 tokens that return a string (but which errors for the RSA alg). I had to do a decent amount of code-diving to discover that the expected type is actually rsa.PublicKey.

@vidolch
Copy link

vidolch commented Nov 2, 2020

@mieubrisse can you add the working code here since I am wondering how to get it working as well...

@mieubrisse
Copy link
Author

mieubrisse commented Nov 2, 2020

Sure:

const (
    // Key in the Headers hashmap of the token that points to the key ID
    keyIdTokenHeaderKey = "kid"

    // Header and footer to attach to base64-encoded key data that we receive from Auth0
    pubKeyHeader = "-----BEGIN CERTIFICATE-----"
    pubKeyFooter = "-----END CERTIFICATE-----"
)

// Provided by Auth0 via https://auth0.com/docs/tokens/json-web-tokens/json-web-key-sets
var RsaPublicKeyBase64 = map[string]string{
	"some-key-id1": "MIIDD......",
	"some-key-id2": "MIIDD......",
}

token, err := new(jwt.Parser).ParseWithClaims(
    tokenStr,
    &auth0_authorizer.Auth0TokenClaims{}, // This is a custom claims object
    func(token *jwt.Token) (interface{}, error) {
            // IMPORTANT: Validating the algorithm per https://godoc.org/github.com/dgrijalva/jwt-go#example-Parse--Hmac
            if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
                    return nil, stacktrace.NewError(
                            "Expected token algorithm '%v' but got '%v'",
                            jwt.SigningMethodRS256.Name,
                            token.Header)
            }

            untypedKeyId, found := token.Header[keyIdTokenHeaderKey]
            if !found {
                    return nil, stacktrace.NewError("No key ID key '%v' found in token header", keyIdTokenHeaderKey)
            }
            keyId, ok := untypedKeyId.(string)
            if !ok {
                    return nil, stacktrace.NewError("Found key ID, but value was not a string")
            }

            keyBase64, found := auth0_constants.RsaPublicKeyBase64[keyId]
            if !found {
                    return nil, stacktrace.NewError("No public RSA key found corresponding to key ID from token '%v'", keyId)
            }
            keyStr := pubKeyHeader + "\n" + keyBase64 + "\n" + pubKeyFooter

            // Since the token is RSA (which we validated at the start of this function), the return type of this function actually has to be rsa.PublicKey!
            pubKey, err := jwt.ParseRSAPublicKeyFromPEM([]byte(keyStr))
            if err != nil {
                    return nil, stacktrace.Propagate(err, "An error occurred parsing the public key base64 for key ID '%v'; this is a code bug", keyId)
            }

            return pubKey, nil
    },
)

The non-obvious parts:

  1. The "kid" is a reference ID, which will be used to tell you which public key you should return from the function. In my case, Auth0 provides a set of public keys and the "kid" will point to one of those
  2. The token extractor function needs to validate that the signing algorithm is what we expect
  3. The token extractor function for RSA tokens needs to return type rsa.PublicKey (I only found this by diving through jwt-go code)

@lggomez
Copy link

lggomez commented Aug 3, 2021

Hi @mieubrisse per #462 this repo has been deprecated and migrated to a new organization: https://github.com/golang-jwt/jwt

As stated in golang-jwt/jwt#7, none if the new maintainers will be copying the original contributions of interest to respect the authors, but will rather encourage them to migrate to the new repo (and also check if their contribution is still applicable)

Regards

@lggomez
Copy link

lggomez commented Aug 3, 2021

Related issue: golang-jwt/jwt#58

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants