-
Notifications
You must be signed in to change notification settings - Fork 420
-
Hi all, I am migrating my project from github.com/dgrijalva/jwt-go. I found that now the Claims interface includes a bunch of getters compares to the old version which only has Valid() for customer provided validation. I am confused as those getters seems trivial (maybe it is a stupid question) and my project uses custom claims and we don't even need those unnecessary claims like iss, sub, aud, etc,.
My project uses a custom struct for claims, like this:
type MyClaims struct {
OAuthID string `json:"oauthId,omitempty"`
UserID string `json:"userId,omitempty"`
UserEmail string `json:"userEmail,omitempty"`
Roles []string `json:"roles,omitempty"`
ExpiresAt int64 `json:"exp,omitempty"`
}
func (mc MyClaims) Validate() error {
now := time.Now().Unix()
if now > pc.ExpiresAt {
return errors.New("token expired")
}
if pc.UserID == "" || pc.UserEmail == "" || pc.OAuthID == "" {
return errors.New("token doesn't have all the required claims set.")
}
return nil
}
When migrating to v5 jwt-go, compiler complains that the MyClaims doesn't implement Claims interface. So, to make it happy I added those functions:
type MyClaims struct {
jwt.RegisteredClaims
OAuthID string `json:"oauthId,omitempty"`
UserID string `json:"userId,omitempty"`
UserEmail string `json:"userEmail,omitempty"`
Roles []string `json:"roles,omitempty"`
ExpiresAt int64 `json:"exp,omitempty"`
}
func (mc MyClaims) GetExpirationTime() (*jwtgo.NumericDate, error) {
return pc.ExpiresAt, nil
}
func (mc MyClaims) GetIssuedAt() (*jwtgo.NumericDate, error) {
return pc.IssuedAt, nil
}
func (mc MyClaims) GetNotBefore() (*jwtgo.NumericDate, error) {
return pc.NotBefore, nil
}
func (mc MyClaims) GetIssuer() (string, error) {
return pc.Issuer, nil
}
func (mc MyClaims) GetSubject() (string, error) {
return pc.Subject, nil
}
func (mc MyClaims) GetAudience() (jwtgo.ClaimStrings, error) {
return pc.Audience, nil
}
I am confused since those new added getters are just return corresponding fields introduced by RegisteredClaims, my custom token even doesn't want claims like iss, sub, aud, etc., Why do we need to be forced to implement those getters? Is it just to strictly follow the RFC standard?
Also, since those getters just return the corresponding fields, I cannot imagine when those getters could throw error, when could those getters return error?
Thanks.
Beta Was this translation helpful? Give feedback.
All reactions
Ok a couple of points
I am confused since those new added getters are just return corresponding fields introduced by
RegisteredClaims, my custom token even doesn't want claims likeiss,sub,aud, etc., Why do we need to be forced to implement those getters? Is it just to strictly follow the RFC standard?
Yes, it is primarily to follow the RFC standard. All fields which are optional in the RFC are optional though and can either be set to nil, e.g, for date-fields or an empty string or an empty array. Since you already embedding jwt.RegisteredClaims in your new example, you don't need to implement the interface. Go will check embedded structs, whether they implement the necessary function...
Replies: 2 comments
-
Ok a couple of points
I am confused since those new added getters are just return corresponding fields introduced by
RegisteredClaims, my custom token even doesn't want claims likeiss,sub,aud, etc., Why do we need to be forced to implement those getters? Is it just to strictly follow the RFC standard?
Yes, it is primarily to follow the RFC standard. All fields which are optional in the RFC are optional though and can either be set to nil, e.g, for date-fields or an empty string or an empty array. Since you already embedding jwt.RegisteredClaims in your new example, you don't need to implement the interface. Go will check embedded structs, whether they implement the necessary functions for the interface.
The only function you might want to implement is Validate, if you want to check additional fields (such as your user ID, user email). See also this example here:
Lines 127 to 134 in 1691aa9
Note: that this is performed in addition to regular validation, so you don't need to check the exp field on your own, it is already done by the validation helper.
Also, since those getters just return the corresponding fields, I cannot imagine when those getters could throw error, when could those getters return error?
There are specific corner-cases and those are the MapClaims, which are based fields in a map. Those could potentially be of the wrong type and we need to distinguish between a value that is empty (e.g., not present) and present but of wrong type.
Thanks.
You are welcome :)
PS: It might be worth to have another look in the JWT RFCs and possible the ouath ones, there are a couple of "standard" fields that you could re-use, for example sub (Subject) is the principal that the token was created for, usually either your userID or a username.
Beta Was this translation helpful? Give feedback.
All reactions
-
Thanks @oxisto for your quick response!
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 1