2015-04-09 23:20:10 +03:00
|
|
|
package jwt
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Error constants
|
|
|
|
var (
|
2016-06-07 20:34:06 +03:00
|
|
|
ErrInvalidKey = errors.New("key is invalid")
|
|
|
|
ErrInvalidKeyType = errors.New("key is of invalid type")
|
2016-04-08 23:58:29 +03:00
|
|
|
ErrHashUnavailable = errors.New("the requested hash function is unavailable")
|
2022-01-20 00:55:19 +03:00
|
|
|
|
|
|
|
ErrTokenMalformed = errors.New("token is malformed")
|
|
|
|
ErrTokenUnverifiable = errors.New("token is unverifiable")
|
|
|
|
ErrTokenSignatureInvalid = errors.New("token signature is invalid")
|
|
|
|
|
|
|
|
ErrTokenInvalidAudience = errors.New("token has invalid audience")
|
|
|
|
ErrTokenExpired = errors.New("token is expired")
|
|
|
|
ErrTokenUsedBeforeIssued = errors.New("token used before issued")
|
|
|
|
ErrTokenInvalidIssuer = errors.New("token has invalid issuer")
|
|
|
|
ErrTokenNotValidYet = errors.New("token is not valid yet")
|
|
|
|
ErrTokenInvalidId = errors.New("token has invalid id")
|
|
|
|
ErrTokenInvalidClaims = errors.New("token has invalid claims")
|
2015-04-09 23:20:10 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
// The errors that might occur when parsing and validating a token
|
|
|
|
const (
|
|
|
|
ValidationErrorMalformed uint32 = 1 << iota // Token is malformed
|
|
|
|
ValidationErrorUnverifiable // Token could not be verified because of signing problems
|
|
|
|
ValidationErrorSignatureInvalid // Signature validation failed
|
2015-07-17 22:40:52 +03:00
|
|
|
|
|
|
|
// Standard Claim validation errors
|
|
|
|
ValidationErrorAudience // AUD validation failed
|
|
|
|
ValidationErrorExpired // EXP validation failed
|
|
|
|
ValidationErrorIssuedAt // IAT validation failed
|
|
|
|
ValidationErrorIssuer // ISS validation failed
|
|
|
|
ValidationErrorNotValidYet // NBF validation failed
|
|
|
|
ValidationErrorId // JTI validation failed
|
|
|
|
ValidationErrorClaimsInvalid // Generic claims validation error
|
2015-04-09 23:20:10 +03:00
|
|
|
)
|
|
|
|
|
2021-08-03 16:51:01 +03:00
|
|
|
// NewValidationError is a helper for constructing a ValidationError with a string error message
|
2016-04-13 03:31:30 +03:00
|
|
|
func NewValidationError(errorText string, errorFlags uint32) *ValidationError {
|
|
|
|
return &ValidationError{
|
2016-06-16 02:42:50 +03:00
|
|
|
text: errorText,
|
2016-04-13 03:31:30 +03:00
|
|
|
Errors: errorFlags,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-03 16:51:01 +03:00
|
|
|
// ValidationError represents an error from Parse if token is not valid
|
2015-04-09 23:20:10 +03:00
|
|
|
type ValidationError struct {
|
2015-12-31 18:48:39 +03:00
|
|
|
Inner error // stores the error returned by external dependencies, i.e.: KeyFunc
|
2015-04-09 23:20:10 +03:00
|
|
|
Errors uint32 // bitfield. see ValidationError... constants
|
2016-06-16 02:42:50 +03:00
|
|
|
text string // errors that do not have a valid error just have text
|
2015-04-09 23:20:10 +03:00
|
|
|
}
|
|
|
|
|
2021-08-03 16:51:01 +03:00
|
|
|
// Error is the implementation of the err interface.
|
2015-04-09 23:20:10 +03:00
|
|
|
func (e ValidationError) Error() string {
|
2016-06-16 02:42:50 +03:00
|
|
|
if e.Inner != nil {
|
|
|
|
return e.Inner.Error()
|
|
|
|
} else if e.text != "" {
|
|
|
|
return e.text
|
|
|
|
} else {
|
2015-04-09 23:20:10 +03:00
|
|
|
return "token is invalid"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-15 17:25:32 +03:00
|
|
|
// Unwrap gives errors.Is and errors.As access to the inner error.
|
|
|
|
func (e *ValidationError) Unwrap() error {
|
|
|
|
return e.Inner
|
|
|
|
}
|
|
|
|
|
2015-04-09 23:20:10 +03:00
|
|
|
// No errors
|
|
|
|
func (e *ValidationError) valid() bool {
|
2016-11-01 19:52:33 +03:00
|
|
|
return e.Errors == 0
|
2015-04-09 23:20:10 +03:00
|
|
|
}
|
2022-01-20 00:55:19 +03:00
|
|
|
|
|
|
|
// Is checks if this ValidationError is of the supplied error. We are first checking for the exact error message
|
|
|
|
// by comparing the inner error message. If that fails, we compare using the error flags. This way we can use
|
|
|
|
// custom error messages (mainly for backwards compatability) and still leverage errors.Is using the global error variables.
|
|
|
|
func (e *ValidationError) Is(err error) bool {
|
|
|
|
// Check, if our inner error is a direct match
|
|
|
|
if errors.Is(errors.Unwrap(e), err) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, we need to match using our error flags
|
|
|
|
switch err {
|
|
|
|
case ErrTokenMalformed:
|
|
|
|
return e.Errors&ValidationErrorMalformed != 0
|
|
|
|
case ErrTokenUnverifiable:
|
|
|
|
return e.Errors&ValidationErrorUnverifiable != 0
|
|
|
|
case ErrTokenSignatureInvalid:
|
|
|
|
return e.Errors&ValidationErrorSignatureInvalid != 0
|
|
|
|
case ErrTokenInvalidAudience:
|
|
|
|
return e.Errors&ValidationErrorAudience != 0
|
|
|
|
case ErrTokenExpired:
|
|
|
|
return e.Errors&ValidationErrorExpired != 0
|
|
|
|
case ErrTokenUsedBeforeIssued:
|
|
|
|
return e.Errors&ValidationErrorIssuedAt != 0
|
|
|
|
case ErrTokenInvalidIssuer:
|
|
|
|
return e.Errors&ValidationErrorIssuer != 0
|
|
|
|
case ErrTokenNotValidYet:
|
|
|
|
return e.Errors&ValidationErrorNotValidYet != 0
|
|
|
|
case ErrTokenInvalidId:
|
|
|
|
return e.Errors&ValidationErrorId != 0
|
|
|
|
case ErrTokenInvalidClaims:
|
|
|
|
return e.Errors&ValidationErrorClaimsInvalid != 0
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|