Skip to content

Commit

Permalink
Merge commit from fork
Browse files Browse the repository at this point in the history
* Initial draft of adding text to ParseWithClaims

* Adjusted example and referring to the example in Parse functions

* Backporting logic from v5

* Added a test
  • Loading branch information
oxisto authored Nov 3, 2024
1 parent 9358574 commit 7b1c1c0
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 22 deletions.
6 changes: 5 additions & 1 deletion example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func ExampleParseWithClaims_customClaimsType() {
// 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() {
// Token from another example. This token is expired
var tokenString = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJleHAiOjE1MDAwLCJpc3MiOiJ0ZXN0In0.HE7fK0xOQwFEr4WDgRWj4teRPZ6i3GLwD5YCm6Pwu_c"
Expand All @@ -106,6 +106,10 @@ func ExampleParse_errorChecking() {
fmt.Println("You look nice today")
} else if errors.Is(err, jwt.ErrTokenMalformed) {
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) {
// Token is either expired or not active yet
fmt.Println("Timing is everything")
Expand Down
41 changes: 20 additions & 21 deletions parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,21 @@ func NewParser(options ...ParserOption) *Parser {
return p
}

// Parse parses, validates, verifies the signature and returns the parsed token.
// keyFunc will receive the parsed token and should return the key for validating.
// Parse parses, validates, verifies the signature and returns the parsed token. keyFunc will
// receive the parsed token and should return the key for validating.
func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, error) {
return p.ParseWithClaims(tokenString, MapClaims{}, keyFunc)
}

// ParseWithClaims parses, validates, and verifies like Parse, but supplies a default object implementing the Claims
// interface. This provides default values which can be overridden and allows a caller to use their own type, rather
// than the default MapClaims implementation of Claims.
// ParseWithClaims parses, validates, and verifies like Parse, but supplies a default object
// implementing the Claims interface. This provides default values which can be overridden and
// 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),
// make sure that a) you either embed a non-pointer version of the claims or 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.
// Note: If you provide a custom claim implementation that embeds one of the standard claims (such
// as RegisteredClaims), make sure that a) you either embed a non-pointer version of the claims or
// 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) {
token, parts, err := p.ParseUnverified(tokenString, claims)
if err != nil {
Expand Down Expand Up @@ -85,35 +87,32 @@ func (p *Parser) ParseWithClaims(tokenString string, claims Claims, keyFunc Keyf
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{}

// Validate Claims
if !p.SkipClaimsValidation {
if err := token.Claims.Valid(); err != nil {

// 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 e, ok := err.(*ValidationError); !ok {
vErr = &ValidationError{Inner: err, Errors: ValidationErrorClaimsInvalid}
} else {
vErr = e
}
return token, vErr
}
}

// 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
}
// No errors so far, token is valid.
token.Valid = true

return token, vErr
return token, nil
}

// ParseUnverified parses the token but doesn't validate the signature.
Expand Down
11 changes: 11 additions & 0 deletions parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,17 @@ var jwtTestData = []struct {
nil,
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",
"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.FhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg",
Expand Down

0 comments on commit 7b1c1c0

Please sign in to comment.