package jwt import ( "errors" ) // Error constants var ( ErrInvalidKey = errors.New("key is invalid") ErrInvalidKeyType = errors.New("key is of invalid type") ErrHashUnavailable = errors.New("the requested hash function is unavailable") 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") ) // 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 // 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 ) // NewValidationError is a helper for constructing a ValidationError with a string error message func NewValidationError(errorText string, errorFlags uint32) *ValidationError { return &ValidationError{ text: errorText, Errors: errorFlags, } } // ValidationError represents an error from Parse if token is not valid type ValidationError struct { Inner error // stores the error returned by external dependencies, i.e.: KeyFunc Errors uint32 // bitfield. see ValidationError... constants text string // errors that do not have a valid error just have text } // Error is the implementation of the err interface. func (e ValidationError) Error() string { if e.Inner != nil { return e.Inner.Error() } else if e.text != "" { return e.text } else { return "token is invalid" } } // Unwrap gives errors.Is and errors.As access to the inner error. func (e *ValidationError) Unwrap() error { return e.Inner } // No errors func (e *ValidationError) valid() bool { return e.Errors == 0 } // 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 }