Reputation: 121
I'm reading the example folder for JWT i'm a bit unsure how things work for validating the token.
func ExampleNewWithClaims_customClaimsType() {
mySigningKey := []byte("AllYourBase")
type MyCustomClaims struct {
Foo string `json:"foo"`
jwt.StandardClaims
}
// Create the Claims
claims := MyCustomClaims{
"bar",
jwt.StandardClaims{
ExpiresAt: 15000,
Issuer: "test",
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
ss, err := token.SignedString(mySigningKey)
fmt.Printf("%v %v", ss, err)
//Output: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJleHAiOjE1MDAwLCJpc3MiOiJ0ZXN0In0.HE7fK0xOQwFEr4WDgRWj4teRPZ6i3GLwD5YCm6Pwu_c <nil>
}
Here it's straight forward and the token is being signed here token.SignedString(mySigningKey)
using "mySigningKey"
Now there unparsing is much less clear for me :
func ExampleParseWithClaims_customClaimsType() {
tokenString := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJleHAiOjE1MDAwLCJpc3MiOiJ0ZXN0In0.HE7fK0xOQwFEr4WDgRWj4teRPZ6i3GLwD5YCm6Pwu_c"
type MyCustomClaims struct {
Foo string `json:"foo"`
jwt.StandardClaims
}
// sample token is expired. override time so it parses as valid
at(time.Unix(0, 0), func() {
token, err := jwt.ParseWithClaims(tokenString, &MyCustomClaims{}, func(token *jwt.Token) (interface{}, error) {
return []byte("AllYourBase"), nil
})
if claims, ok := token.Claims.(*MyCustomClaims); ok && token.Valid {
fmt.Printf("%v %v", claims.Foo, claims.StandardClaims.ExpiresAt)
} else {
fmt.Println(err)
}
})
// Output: bar 15000
}
Is order to validate that the signature of the token string given back by the client is valid would you need to
But the example is just decoding the key and by "magic" the return is the secret/signing key?
It doesn't make sense to me at all. Also returning a valid claim for a public key is useless as it could have been done by any private key.
What am i missing ?
Upvotes: 1
Views: 1777
Reputation: 51512
Validation is not done by the public key included in the token.
HS256 is symmetric, so whatever key you used to sign the token, you have to use the same key to validate the signature, and that's what's happening. The function passed to ParseWithClaims
is returning the same key used to sign the token.
If an asymmetric signing algorithm was used, you'd use the private key to sign the token, and then the public key to validate it, and that nested function would have to return the public key so that ParseWithClaims
can validate it.
It sounds like the part that confused you is:
jwt.ParseWithClaims(tokenString, &MyCustomClaims{}, func(token *jwt.Token) (interface{}, error) {
return []byte("AllYourBase"), nil
})
The nested function passed to ParseWithClaims
is supposed to inspect the token passed, and return the correct key that can be used to verify the signature. For HS256, it is the same as the key used to sign it. For RSxxx, it'd be the public key, and which public key it should return can be retrieved from the token passed in. It usually contains a public key id so you can select the correct key.
Upvotes: 4