mirror of https://github.com/golang-jwt/jwt.git
Merge commit from fork
* Initial draft of adding text to ParseWithClaims * Adjusted example and referring to the example in Parse functions * Backporting logic from v5 * Added a test
This commit is contained in:
parent
9358574a7a
commit
7b1c1c00a1
|
@ -93,7 +93,7 @@ func ExampleParseWithClaims_customClaimsType() {
|
||||||
// Output: bar test
|
// Output: bar test
|
||||||
}
|
}
|
||||||
|
|
||||||
// An example of parsing the error types using bitfield checks
|
// An example of parsing the error types using [errors.Is].
|
||||||
func ExampleParse_errorChecking() {
|
func ExampleParse_errorChecking() {
|
||||||
// Token from another example. This token is expired
|
// Token from another example. This token is expired
|
||||||
var tokenString = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJleHAiOjE1MDAwLCJpc3MiOiJ0ZXN0In0.HE7fK0xOQwFEr4WDgRWj4teRPZ6i3GLwD5YCm6Pwu_c"
|
var tokenString = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJleHAiOjE1MDAwLCJpc3MiOiJ0ZXN0In0.HE7fK0xOQwFEr4WDgRWj4teRPZ6i3GLwD5YCm6Pwu_c"
|
||||||
|
@ -106,6 +106,10 @@ func ExampleParse_errorChecking() {
|
||||||
fmt.Println("You look nice today")
|
fmt.Println("You look nice today")
|
||||||
} else if errors.Is(err, jwt.ErrTokenMalformed) {
|
} else if errors.Is(err, jwt.ErrTokenMalformed) {
|
||||||
fmt.Println("That's not even a token")
|
fmt.Println("That's not even a token")
|
||||||
|
} else if errors.Is(err, jwt.ErrTokenUnverifiable) {
|
||||||
|
fmt.Println("We could not verify this token")
|
||||||
|
} else if errors.Is(err, jwt.ErrTokenSignatureInvalid) {
|
||||||
|
fmt.Println("This token has an invalid signature")
|
||||||
} else if errors.Is(err, jwt.ErrTokenExpired) || errors.Is(err, jwt.ErrTokenNotValidYet) {
|
} else if errors.Is(err, jwt.ErrTokenExpired) || errors.Is(err, jwt.ErrTokenNotValidYet) {
|
||||||
// Token is either expired or not active yet
|
// Token is either expired or not active yet
|
||||||
fmt.Println("Timing is everything")
|
fmt.Println("Timing is everything")
|
||||||
|
|
47
parser.go
47
parser.go
|
@ -36,19 +36,21 @@ func NewParser(options ...ParserOption) *Parser {
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse parses, validates, verifies the signature and returns the parsed token.
|
// Parse parses, validates, verifies the signature and returns the parsed token. keyFunc will
|
||||||
// keyFunc will receive the parsed token and should return the key for validating.
|
// receive the parsed token and should return the key for validating.
|
||||||
func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, error) {
|
func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, error) {
|
||||||
return p.ParseWithClaims(tokenString, MapClaims{}, keyFunc)
|
return p.ParseWithClaims(tokenString, MapClaims{}, keyFunc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseWithClaims parses, validates, and verifies like Parse, but supplies a default object implementing the Claims
|
// ParseWithClaims parses, validates, and verifies like Parse, but supplies a default object
|
||||||
// interface. This provides default values which can be overridden and allows a caller to use their own type, rather
|
// implementing the Claims interface. This provides default values which can be overridden and
|
||||||
// than the default MapClaims implementation of Claims.
|
// allows a caller to use their own type, rather than the default MapClaims implementation of
|
||||||
|
// Claims.
|
||||||
//
|
//
|
||||||
// Note: If you provide a custom claim implementation that embeds one of the standard claims (such as RegisteredClaims),
|
// Note: If you provide a custom claim implementation that embeds one of the standard claims (such
|
||||||
// make sure that a) you either embed a non-pointer version of the claims or b) if you are using a pointer, allocate the
|
// as RegisteredClaims), make sure that a) you either embed a non-pointer version of the claims or
|
||||||
// proper memory for it before passing in the overall claims, otherwise you might run into a panic.
|
// b) if you are using a pointer, allocate the proper memory for it before passing in the overall
|
||||||
|
// claims, otherwise you might run into a panic.
|
||||||
func (p *Parser) ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) {
|
func (p *Parser) ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) {
|
||||||
token, parts, err := p.ParseUnverified(tokenString, claims)
|
token, parts, err := p.ParseUnverified(tokenString, claims)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -85,12 +87,17 @@ func (p *Parser) ParseWithClaims(tokenString string, claims Claims, keyFunc Keyf
|
||||||
return token, &ValidationError{Inner: err, Errors: ValidationErrorUnverifiable}
|
return token, &ValidationError{Inner: err, Errors: ValidationErrorUnverifiable}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Perform validation
|
||||||
|
token.Signature = parts[2]
|
||||||
|
if err := token.Method.Verify(strings.Join(parts[0:2], "."), token.Signature, key); err != nil {
|
||||||
|
return token, &ValidationError{Inner: err, Errors: ValidationErrorSignatureInvalid}
|
||||||
|
}
|
||||||
|
|
||||||
vErr := &ValidationError{}
|
vErr := &ValidationError{}
|
||||||
|
|
||||||
// Validate Claims
|
// Validate Claims
|
||||||
if !p.SkipClaimsValidation {
|
if !p.SkipClaimsValidation {
|
||||||
if err := token.Claims.Valid(); err != nil {
|
if err := token.Claims.Valid(); err != nil {
|
||||||
|
|
||||||
// If the Claims Valid returned an error, check if it is a validation error,
|
// If the Claims Valid returned an error, check if it is a validation error,
|
||||||
// If it was another error type, create a ValidationError with a generic ClaimsInvalid flag set
|
// If it was another error type, create a ValidationError with a generic ClaimsInvalid flag set
|
||||||
if e, ok := err.(*ValidationError); !ok {
|
if e, ok := err.(*ValidationError); !ok {
|
||||||
|
@ -98,23 +105,15 @@ func (p *Parser) ParseWithClaims(tokenString string, claims Claims, keyFunc Keyf
|
||||||
} else {
|
} else {
|
||||||
vErr = e
|
vErr = e
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perform validation
|
|
||||||
token.Signature = parts[2]
|
|
||||||
if err = token.Method.Verify(strings.Join(parts[0:2], "."), token.Signature, key); err != nil {
|
|
||||||
vErr.Inner = err
|
|
||||||
vErr.Errors |= ValidationErrorSignatureInvalid
|
|
||||||
}
|
|
||||||
|
|
||||||
if vErr.valid() {
|
|
||||||
token.Valid = true
|
|
||||||
return token, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return token, vErr
|
return token, vErr
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No errors so far, token is valid.
|
||||||
|
token.Valid = true
|
||||||
|
|
||||||
|
return token, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ParseUnverified parses the token but doesn't validate the signature.
|
// ParseUnverified parses the token but doesn't validate the signature.
|
||||||
//
|
//
|
||||||
|
|
|
@ -111,6 +111,17 @@ var jwtTestData = []struct {
|
||||||
nil,
|
nil,
|
||||||
jwt.SigningMethodRS256,
|
jwt.SigningMethodRS256,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"basic invalid and expired",
|
||||||
|
"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIiLCJleHAiOjEyMzR9.IbFvatLIJ2Z7B_MAaeIaRZsRSQF1CDzmAE0osHII3WfRTbPavonrDXz-p2Ap_oh9LT2lyohL_jCLoVcpTyu7K3Rt-hdgxZ1_r1StwM1we0SqW2BFFeXCzyS9SLf2YTaVR35lVvfwwlCpPBgOw1SBbczm9m6yPgA9Afsvw_lG_GU2civvG0UzHXxbzWWvJoflGokJDuoHQiku2bfxReyNsoUGcLjx5tfkY7cPihM3CffPpRFYCVjv_abHYelZWpVjdGULQyJDInGYqO8oANqNTtjui7aqxBpcFCUBwVVgktM4Q6Dvj-o5LrdPyJSEl0b_R2JstFE5CbEZGN5anN1yHa",
|
||||||
|
defaultKeyFunc,
|
||||||
|
jwt.MapClaims{"foo": "bar", "exp": 1234.0},
|
||||||
|
false,
|
||||||
|
jwt.ValidationErrorSignatureInvalid,
|
||||||
|
[]error{jwt.ErrTokenSignatureInvalid, rsa.ErrVerification},
|
||||||
|
nil,
|
||||||
|
jwt.SigningMethodRS256,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"basic nokeyfunc",
|
"basic nokeyfunc",
|
||||||
"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.FhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg",
|
"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.FhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg",
|
||||||
|
|
Loading…
Reference in New Issue