diff --git a/errors.go b/errors.go index eb30a93..a6b60a3 100644 --- a/errors.go +++ b/errors.go @@ -20,19 +20,26 @@ const ( ValidationErrorNotValidYet // NBF validation failed ) +// Helper for constructing a ValidationError with a string error message +func NewValidationError(errorText string, errorFlags uint32) *ValidationError { + return &ValidationError{ + Inner: errors.New(errorText), + Errors: errorFlags, + } +} + // The error from Parse if token is not valid type ValidationError struct { - err string Inner error // stores the error returned by external dependencies, i.e.: KeyFunc Errors uint32 // bitfield. see ValidationError... constants } // Validation error is an error type func (e ValidationError) Error() string { - if e.err == "" { + if e.Inner == nil { return "token is invalid" } - return e.err + return e.Inner.Error() } // No errors diff --git a/none.go b/none.go index d697578..f04d189 100644 --- a/none.go +++ b/none.go @@ -13,10 +13,8 @@ type unsafeNoneMagicConstant string func init() { SigningMethodNone = &signingMethodNone{} - NoneSignatureTypeDisallowedError = &ValidationError{ - "'none' signature type is not allowed", - ValidationErrorSignatureInvalid, - } + NoneSignatureTypeDisallowedError = NewValidationError("'none' signature type is not allowed", ValidationErrorSignatureInvalid) + RegisterSigningMethod(SigningMethodNone.Alg(), func() SigningMethod { return SigningMethodNone }) @@ -35,10 +33,10 @@ func (m *signingMethodNone) Verify(signingString, signature string, key interfac } // If signing method is none, signature must be an empty string if signature != "" { - return &ValidationError{ + return NewValidationError( "'none' signing method with non-empty signature", ValidationErrorSignatureInvalid, - } + ) } // Accept 'none' signing method. diff --git a/parser.go b/parser.go index c859393..a1accc2 100644 --- a/parser.go +++ b/parser.go @@ -18,7 +18,7 @@ type Parser struct { func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, error) { parts := strings.Split(tokenString, ".") if len(parts) != 3 { - return nil, &ValidationError{err: "token contains an invalid number of segments", Errors: ValidationErrorMalformed} + return nil, NewValidationError("token contains an invalid number of segments", ValidationErrorMalformed) } var err error @@ -27,34 +27,34 @@ func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, error) { var headerBytes []byte if headerBytes, err = DecodeSegment(parts[0]); err != nil { if strings.HasPrefix(strings.ToLower(tokenString), "bearer ") { - return token, &ValidationError{err: "tokenstring should not contain 'bearer '", Errors: ValidationErrorMalformed} + return token, NewValidationError("tokenstring should not contain 'bearer '", ValidationErrorMalformed) } - return token, &ValidationError{err: err.Error(), Errors: ValidationErrorMalformed} + return token, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} } if err = json.Unmarshal(headerBytes, &token.Header); err != nil { - return token, &ValidationError{err: err.Error(), Errors: ValidationErrorMalformed} + return token, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} } // parse Claims var claimBytes []byte if claimBytes, err = DecodeSegment(parts[1]); err != nil { - return token, &ValidationError{err: err.Error(), Errors: ValidationErrorMalformed} + return token, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} } dec := json.NewDecoder(bytes.NewBuffer(claimBytes)) if p.UseJSONNumber { dec.UseNumber() } if err = dec.Decode(&token.Claims); err != nil { - return token, &ValidationError{err: err.Error(), Errors: ValidationErrorMalformed} + return token, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} } // Lookup signature method if method, ok := token.Header["alg"].(string); ok { if token.Method = GetSigningMethod(method); token.Method == nil { - return token, &ValidationError{err: "signing method (alg) is unavailable.", Errors: ValidationErrorUnverifiable} + return token, NewValidationError("signing method (alg) is unavailable.", ValidationErrorUnverifiable) } } else { - return token, &ValidationError{err: "signing method (alg) is unspecified.", Errors: ValidationErrorUnverifiable} + return token, NewValidationError("signing method (alg) is unspecified.", ValidationErrorUnverifiable) } // Verify signing method is in the required set @@ -69,7 +69,7 @@ func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, error) { } if !signingMethodValid { // signing method is not in the listed set - return token, &ValidationError{err: fmt.Sprintf("signing method %v is invalid", alg), Errors: ValidationErrorSignatureInvalid} + return token, NewValidationError(fmt.Sprintf("signing method %v is invalid", alg), ValidationErrorSignatureInvalid) } } @@ -77,11 +77,11 @@ func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, error) { var key interface{} if keyFunc == nil { // keyFunc was not provided. short circuiting validation - return token, &ValidationError{err: "no Keyfunc was provided.", Errors: ValidationErrorUnverifiable} + return token, NewValidationError("no Keyfunc was provided.", ValidationErrorUnverifiable) } if key, err = keyFunc(token); err != nil { // keyFunc returned an error - return token, &ValidationError{err: err.Error(), Errors: ValidationErrorUnverifiable, Inner: err} + return token, &ValidationError{Inner: err, Errors: ValidationErrorUnverifiable} } // Check expiration times @@ -113,19 +113,19 @@ func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, error) { } if vexp && now > exp { - vErr.err = "token is expired" + vErr.Inner = fmt.Errorf("token is expired") vErr.Errors |= ValidationErrorExpired } if vnbf && now < nbf { - vErr.err = "token is not valid yet" + vErr.Inner = fmt.Errorf("token is not valid yet") vErr.Errors |= ValidationErrorNotValidYet } // Perform validation token.Signature = parts[2] if err = token.Method.Verify(strings.Join(parts[0:2], "."), token.Signature, key); err != nil { - vErr.err = err.Error() + vErr.Inner = err vErr.Errors |= ValidationErrorSignatureInvalid }