New Validation API
Some guidelines in designing the new validation API
* Previously, the `Valid` method was placed on the claim, which was always not entirely semantically correct, since the validity is concerning the token, not the claims. Although the validity of the token is based on the processing of the claims (such as `exp`). Therefore, the function `Valid` was removed from the `Claims` interface and the single canonical way to retrieve the validity of the token is to retrieve the `Valid` property of the `Token` struct.
* The previous fact was enhanced by the fact that most claims implementations had additional exported `VerifyXXX` functions, which are now removed
* All validation errors should be comparable with `errors.Is` to determine, why a particular validation has failed
* Developers want to adjust validation options. Popular options include:
* Leeway when processing exp, nbf, iat
* Not verifying `iat`, since this is actually just an informational claim. When purely looking at the standard, this should probably the default
* Verifying `aud` by default, which actually the standard sort of demands. We need to see how strong we want to enforce this
* Developers want to create their own claim types, mostly by embedding one of the existing types such as `RegisteredClaims`.
* Sometimes there is the need to further tweak the validation of a token by checking the value of a custom claim. Previously, this was possibly by overriding `Valid`. However, this was error-prone, e.g., if the original `Valid` was not called. Therefore, we should provide an easy way for *additional* checks, without by-passing the necessary validations
This leads to the following two major changes:
* The `Claims` interface now represents a set of functions that return the mandatory claims represented in a token, rather than just a `Valid` function. This is also more semantically correct.
* All validation tasks are offloaded to a new (optional) `Validator`, which can also be configured with appropriate options. If no custom validator was supplied, a default one is used.
2022-08-27 13:07:09 +03:00
|
|
|
package jwt
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/subtle"
|
|
|
|
"fmt"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
2022-08-27 14:36:45 +03:00
|
|
|
// Validator is the core of the new Validation API. It is
|
New Validation API
Some guidelines in designing the new validation API
* Previously, the `Valid` method was placed on the claim, which was always not entirely semantically correct, since the validity is concerning the token, not the claims. Although the validity of the token is based on the processing of the claims (such as `exp`). Therefore, the function `Valid` was removed from the `Claims` interface and the single canonical way to retrieve the validity of the token is to retrieve the `Valid` property of the `Token` struct.
* The previous fact was enhanced by the fact that most claims implementations had additional exported `VerifyXXX` functions, which are now removed
* All validation errors should be comparable with `errors.Is` to determine, why a particular validation has failed
* Developers want to adjust validation options. Popular options include:
* Leeway when processing exp, nbf, iat
* Not verifying `iat`, since this is actually just an informational claim. When purely looking at the standard, this should probably the default
* Verifying `aud` by default, which actually the standard sort of demands. We need to see how strong we want to enforce this
* Developers want to create their own claim types, mostly by embedding one of the existing types such as `RegisteredClaims`.
* Sometimes there is the need to further tweak the validation of a token by checking the value of a custom claim. Previously, this was possibly by overriding `Valid`. However, this was error-prone, e.g., if the original `Valid` was not called. Therefore, we should provide an easy way for *additional* checks, without by-passing the necessary validations
This leads to the following two major changes:
* The `Claims` interface now represents a set of functions that return the mandatory claims represented in a token, rather than just a `Valid` function. This is also more semantically correct.
* All validation tasks are offloaded to a new (optional) `Validator`, which can also be configured with appropriate options. If no custom validator was supplied, a default one is used.
2022-08-27 13:07:09 +03:00
|
|
|
type Validator struct {
|
2022-08-27 14:36:45 +03:00
|
|
|
// leeway is an optional leeway that can be provided to account for clock skew.
|
New Validation API
Some guidelines in designing the new validation API
* Previously, the `Valid` method was placed on the claim, which was always not entirely semantically correct, since the validity is concerning the token, not the claims. Although the validity of the token is based on the processing of the claims (such as `exp`). Therefore, the function `Valid` was removed from the `Claims` interface and the single canonical way to retrieve the validity of the token is to retrieve the `Valid` property of the `Token` struct.
* The previous fact was enhanced by the fact that most claims implementations had additional exported `VerifyXXX` functions, which are now removed
* All validation errors should be comparable with `errors.Is` to determine, why a particular validation has failed
* Developers want to adjust validation options. Popular options include:
* Leeway when processing exp, nbf, iat
* Not verifying `iat`, since this is actually just an informational claim. When purely looking at the standard, this should probably the default
* Verifying `aud` by default, which actually the standard sort of demands. We need to see how strong we want to enforce this
* Developers want to create their own claim types, mostly by embedding one of the existing types such as `RegisteredClaims`.
* Sometimes there is the need to further tweak the validation of a token by checking the value of a custom claim. Previously, this was possibly by overriding `Valid`. However, this was error-prone, e.g., if the original `Valid` was not called. Therefore, we should provide an easy way for *additional* checks, without by-passing the necessary validations
This leads to the following two major changes:
* The `Claims` interface now represents a set of functions that return the mandatory claims represented in a token, rather than just a `Valid` function. This is also more semantically correct.
* All validation tasks are offloaded to a new (optional) `Validator`, which can also be configured with appropriate options. If no custom validator was supplied, a default one is used.
2022-08-27 13:07:09 +03:00
|
|
|
leeway time.Duration
|
2022-08-27 14:36:45 +03:00
|
|
|
|
|
|
|
// timeFunc is used to supply the current time that is needed for
|
|
|
|
// validation. If unspecified, this defaults to time.Now.
|
|
|
|
timeFunc func() time.Time
|
|
|
|
|
|
|
|
// verifyIat specifies whether the iat (Issued At) claim will be verified.
|
|
|
|
// According to https://www.rfc-editor.org/rfc/rfc7519#section-4.1.6 this
|
|
|
|
// only specifies the age of the token, but no validation check is
|
|
|
|
// necessary. However, if wanted, it can be checked if the iat is
|
|
|
|
// unrealistic, i.e., in the future.
|
|
|
|
verifyIat bool
|
2022-08-27 14:42:01 +03:00
|
|
|
|
|
|
|
// expectedAud contains the audiences this token expects. Supplying an empty
|
|
|
|
// string will disable aud checking.
|
|
|
|
expectedAud string
|
2022-08-27 14:36:45 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
type customValidationType interface {
|
|
|
|
CustomValidation() error
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewValidator(opts ...ValidatorOption) *Validator {
|
|
|
|
v := &Validator{}
|
|
|
|
|
|
|
|
// Apply the validator options
|
|
|
|
for _, o := range opts {
|
|
|
|
o(v)
|
|
|
|
}
|
|
|
|
|
|
|
|
return v
|
New Validation API
Some guidelines in designing the new validation API
* Previously, the `Valid` method was placed on the claim, which was always not entirely semantically correct, since the validity is concerning the token, not the claims. Although the validity of the token is based on the processing of the claims (such as `exp`). Therefore, the function `Valid` was removed from the `Claims` interface and the single canonical way to retrieve the validity of the token is to retrieve the `Valid` property of the `Token` struct.
* The previous fact was enhanced by the fact that most claims implementations had additional exported `VerifyXXX` functions, which are now removed
* All validation errors should be comparable with `errors.Is` to determine, why a particular validation has failed
* Developers want to adjust validation options. Popular options include:
* Leeway when processing exp, nbf, iat
* Not verifying `iat`, since this is actually just an informational claim. When purely looking at the standard, this should probably the default
* Verifying `aud` by default, which actually the standard sort of demands. We need to see how strong we want to enforce this
* Developers want to create their own claim types, mostly by embedding one of the existing types such as `RegisteredClaims`.
* Sometimes there is the need to further tweak the validation of a token by checking the value of a custom claim. Previously, this was possibly by overriding `Valid`. However, this was error-prone, e.g., if the original `Valid` was not called. Therefore, we should provide an easy way for *additional* checks, without by-passing the necessary validations
This leads to the following two major changes:
* The `Claims` interface now represents a set of functions that return the mandatory claims represented in a token, rather than just a `Valid` function. This is also more semantically correct.
* All validation tasks are offloaded to a new (optional) `Validator`, which can also be configured with appropriate options. If no custom validator was supplied, a default one is used.
2022-08-27 13:07:09 +03:00
|
|
|
}
|
|
|
|
|
2022-10-15 23:21:15 +03:00
|
|
|
// Validate validates the given claims. It will also perform any custom validation if claims implements the CustomValidator interface.
|
New Validation API
Some guidelines in designing the new validation API
* Previously, the `Valid` method was placed on the claim, which was always not entirely semantically correct, since the validity is concerning the token, not the claims. Although the validity of the token is based on the processing of the claims (such as `exp`). Therefore, the function `Valid` was removed from the `Claims` interface and the single canonical way to retrieve the validity of the token is to retrieve the `Valid` property of the `Token` struct.
* The previous fact was enhanced by the fact that most claims implementations had additional exported `VerifyXXX` functions, which are now removed
* All validation errors should be comparable with `errors.Is` to determine, why a particular validation has failed
* Developers want to adjust validation options. Popular options include:
* Leeway when processing exp, nbf, iat
* Not verifying `iat`, since this is actually just an informational claim. When purely looking at the standard, this should probably the default
* Verifying `aud` by default, which actually the standard sort of demands. We need to see how strong we want to enforce this
* Developers want to create their own claim types, mostly by embedding one of the existing types such as `RegisteredClaims`.
* Sometimes there is the need to further tweak the validation of a token by checking the value of a custom claim. Previously, this was possibly by overriding `Valid`. However, this was error-prone, e.g., if the original `Valid` was not called. Therefore, we should provide an easy way for *additional* checks, without by-passing the necessary validations
This leads to the following two major changes:
* The `Claims` interface now represents a set of functions that return the mandatory claims represented in a token, rather than just a `Valid` function. This is also more semantically correct.
* All validation tasks are offloaded to a new (optional) `Validator`, which can also be configured with appropriate options. If no custom validator was supplied, a default one is used.
2022-08-27 13:07:09 +03:00
|
|
|
func (v *Validator) Validate(claims Claims) error {
|
2022-08-27 14:36:45 +03:00
|
|
|
var now time.Time
|
New Validation API
Some guidelines in designing the new validation API
* Previously, the `Valid` method was placed on the claim, which was always not entirely semantically correct, since the validity is concerning the token, not the claims. Although the validity of the token is based on the processing of the claims (such as `exp`). Therefore, the function `Valid` was removed from the `Claims` interface and the single canonical way to retrieve the validity of the token is to retrieve the `Valid` property of the `Token` struct.
* The previous fact was enhanced by the fact that most claims implementations had additional exported `VerifyXXX` functions, which are now removed
* All validation errors should be comparable with `errors.Is` to determine, why a particular validation has failed
* Developers want to adjust validation options. Popular options include:
* Leeway when processing exp, nbf, iat
* Not verifying `iat`, since this is actually just an informational claim. When purely looking at the standard, this should probably the default
* Verifying `aud` by default, which actually the standard sort of demands. We need to see how strong we want to enforce this
* Developers want to create their own claim types, mostly by embedding one of the existing types such as `RegisteredClaims`.
* Sometimes there is the need to further tweak the validation of a token by checking the value of a custom claim. Previously, this was possibly by overriding `Valid`. However, this was error-prone, e.g., if the original `Valid` was not called. Therefore, we should provide an easy way for *additional* checks, without by-passing the necessary validations
This leads to the following two major changes:
* The `Claims` interface now represents a set of functions that return the mandatory claims represented in a token, rather than just a `Valid` function. This is also more semantically correct.
* All validation tasks are offloaded to a new (optional) `Validator`, which can also be configured with appropriate options. If no custom validator was supplied, a default one is used.
2022-08-27 13:07:09 +03:00
|
|
|
vErr := new(ValidationError)
|
2022-08-27 14:36:45 +03:00
|
|
|
|
|
|
|
// Check, if we have a time func
|
|
|
|
if v.timeFunc != nil {
|
|
|
|
now = v.timeFunc()
|
|
|
|
} else {
|
|
|
|
now = time.Now()
|
|
|
|
}
|
New Validation API
Some guidelines in designing the new validation API
* Previously, the `Valid` method was placed on the claim, which was always not entirely semantically correct, since the validity is concerning the token, not the claims. Although the validity of the token is based on the processing of the claims (such as `exp`). Therefore, the function `Valid` was removed from the `Claims` interface and the single canonical way to retrieve the validity of the token is to retrieve the `Valid` property of the `Token` struct.
* The previous fact was enhanced by the fact that most claims implementations had additional exported `VerifyXXX` functions, which are now removed
* All validation errors should be comparable with `errors.Is` to determine, why a particular validation has failed
* Developers want to adjust validation options. Popular options include:
* Leeway when processing exp, nbf, iat
* Not verifying `iat`, since this is actually just an informational claim. When purely looking at the standard, this should probably the default
* Verifying `aud` by default, which actually the standard sort of demands. We need to see how strong we want to enforce this
* Developers want to create their own claim types, mostly by embedding one of the existing types such as `RegisteredClaims`.
* Sometimes there is the need to further tweak the validation of a token by checking the value of a custom claim. Previously, this was possibly by overriding `Valid`. However, this was error-prone, e.g., if the original `Valid` was not called. Therefore, we should provide an easy way for *additional* checks, without by-passing the necessary validations
This leads to the following two major changes:
* The `Claims` interface now represents a set of functions that return the mandatory claims represented in a token, rather than just a `Valid` function. This is also more semantically correct.
* All validation tasks are offloaded to a new (optional) `Validator`, which can also be configured with appropriate options. If no custom validator was supplied, a default one is used.
2022-08-27 13:07:09 +03:00
|
|
|
|
|
|
|
if !v.VerifyExpiresAt(claims, now, false) {
|
2022-08-27 14:07:17 +03:00
|
|
|
exp := claims.GetExpirationTime()
|
New Validation API
Some guidelines in designing the new validation API
* Previously, the `Valid` method was placed on the claim, which was always not entirely semantically correct, since the validity is concerning the token, not the claims. Although the validity of the token is based on the processing of the claims (such as `exp`). Therefore, the function `Valid` was removed from the `Claims` interface and the single canonical way to retrieve the validity of the token is to retrieve the `Valid` property of the `Token` struct.
* The previous fact was enhanced by the fact that most claims implementations had additional exported `VerifyXXX` functions, which are now removed
* All validation errors should be comparable with `errors.Is` to determine, why a particular validation has failed
* Developers want to adjust validation options. Popular options include:
* Leeway when processing exp, nbf, iat
* Not verifying `iat`, since this is actually just an informational claim. When purely looking at the standard, this should probably the default
* Verifying `aud` by default, which actually the standard sort of demands. We need to see how strong we want to enforce this
* Developers want to create their own claim types, mostly by embedding one of the existing types such as `RegisteredClaims`.
* Sometimes there is the need to further tweak the validation of a token by checking the value of a custom claim. Previously, this was possibly by overriding `Valid`. However, this was error-prone, e.g., if the original `Valid` was not called. Therefore, we should provide an easy way for *additional* checks, without by-passing the necessary validations
This leads to the following two major changes:
* The `Claims` interface now represents a set of functions that return the mandatory claims represented in a token, rather than just a `Valid` function. This is also more semantically correct.
* All validation tasks are offloaded to a new (optional) `Validator`, which can also be configured with appropriate options. If no custom validator was supplied, a default one is used.
2022-08-27 13:07:09 +03:00
|
|
|
delta := now.Sub(exp.Time)
|
|
|
|
vErr.Inner = fmt.Errorf("%s by %s", ErrTokenExpired, delta)
|
|
|
|
vErr.Errors |= ValidationErrorExpired
|
|
|
|
}
|
|
|
|
|
2022-08-27 14:36:45 +03:00
|
|
|
// Check iat if the option is enabled
|
|
|
|
if v.verifyIat && !v.VerifyIssuedAt(claims, now, false) {
|
New Validation API
Some guidelines in designing the new validation API
* Previously, the `Valid` method was placed on the claim, which was always not entirely semantically correct, since the validity is concerning the token, not the claims. Although the validity of the token is based on the processing of the claims (such as `exp`). Therefore, the function `Valid` was removed from the `Claims` interface and the single canonical way to retrieve the validity of the token is to retrieve the `Valid` property of the `Token` struct.
* The previous fact was enhanced by the fact that most claims implementations had additional exported `VerifyXXX` functions, which are now removed
* All validation errors should be comparable with `errors.Is` to determine, why a particular validation has failed
* Developers want to adjust validation options. Popular options include:
* Leeway when processing exp, nbf, iat
* Not verifying `iat`, since this is actually just an informational claim. When purely looking at the standard, this should probably the default
* Verifying `aud` by default, which actually the standard sort of demands. We need to see how strong we want to enforce this
* Developers want to create their own claim types, mostly by embedding one of the existing types such as `RegisteredClaims`.
* Sometimes there is the need to further tweak the validation of a token by checking the value of a custom claim. Previously, this was possibly by overriding `Valid`. However, this was error-prone, e.g., if the original `Valid` was not called. Therefore, we should provide an easy way for *additional* checks, without by-passing the necessary validations
This leads to the following two major changes:
* The `Claims` interface now represents a set of functions that return the mandatory claims represented in a token, rather than just a `Valid` function. This is also more semantically correct.
* All validation tasks are offloaded to a new (optional) `Validator`, which can also be configured with appropriate options. If no custom validator was supplied, a default one is used.
2022-08-27 13:07:09 +03:00
|
|
|
vErr.Inner = ErrTokenUsedBeforeIssued
|
|
|
|
vErr.Errors |= ValidationErrorIssuedAt
|
|
|
|
}
|
|
|
|
|
|
|
|
if !v.VerifyNotBefore(claims, now, false) {
|
|
|
|
vErr.Inner = ErrTokenNotValidYet
|
|
|
|
vErr.Errors |= ValidationErrorNotValidYet
|
|
|
|
}
|
|
|
|
|
2022-08-27 14:42:01 +03:00
|
|
|
if v.expectedAud != "" && !v.VerifyAudience(claims, v.expectedAud, false) {
|
|
|
|
vErr.Inner = ErrTokenNotValidYet
|
|
|
|
vErr.Errors |= ValidationErrorNotValidYet
|
|
|
|
}
|
|
|
|
|
2022-08-27 14:36:45 +03:00
|
|
|
// Finally, we want to give the claim itself some possibility to do some
|
|
|
|
// additional custom validation based on their custom claims
|
|
|
|
cvt, ok := claims.(customValidationType)
|
|
|
|
if ok {
|
|
|
|
if err := cvt.CustomValidation(); err != nil {
|
|
|
|
vErr.Inner = err
|
|
|
|
vErr.Errors |= ValidationErrorClaimsInvalid
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
New Validation API
Some guidelines in designing the new validation API
* Previously, the `Valid` method was placed on the claim, which was always not entirely semantically correct, since the validity is concerning the token, not the claims. Although the validity of the token is based on the processing of the claims (such as `exp`). Therefore, the function `Valid` was removed from the `Claims` interface and the single canonical way to retrieve the validity of the token is to retrieve the `Valid` property of the `Token` struct.
* The previous fact was enhanced by the fact that most claims implementations had additional exported `VerifyXXX` functions, which are now removed
* All validation errors should be comparable with `errors.Is` to determine, why a particular validation has failed
* Developers want to adjust validation options. Popular options include:
* Leeway when processing exp, nbf, iat
* Not verifying `iat`, since this is actually just an informational claim. When purely looking at the standard, this should probably the default
* Verifying `aud` by default, which actually the standard sort of demands. We need to see how strong we want to enforce this
* Developers want to create their own claim types, mostly by embedding one of the existing types such as `RegisteredClaims`.
* Sometimes there is the need to further tweak the validation of a token by checking the value of a custom claim. Previously, this was possibly by overriding `Valid`. However, this was error-prone, e.g., if the original `Valid` was not called. Therefore, we should provide an easy way for *additional* checks, without by-passing the necessary validations
This leads to the following two major changes:
* The `Claims` interface now represents a set of functions that return the mandatory claims represented in a token, rather than just a `Valid` function. This is also more semantically correct.
* All validation tasks are offloaded to a new (optional) `Validator`, which can also be configured with appropriate options. If no custom validator was supplied, a default one is used.
2022-08-27 13:07:09 +03:00
|
|
|
if vErr.valid() {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return vErr
|
|
|
|
}
|
|
|
|
|
|
|
|
// VerifyAudience compares the aud claim against cmp.
|
|
|
|
// If required is false, this method will return true if the value matches or is unset
|
|
|
|
func (v *Validator) VerifyAudience(claims Claims, cmp string, req bool) bool {
|
|
|
|
return verifyAud(claims.GetAudience(), cmp, req)
|
|
|
|
}
|
|
|
|
|
|
|
|
// VerifyExpiresAt compares the exp claim against cmp (cmp < exp).
|
|
|
|
// If req is false, it will return true, if exp is unset.
|
|
|
|
func (v *Validator) VerifyExpiresAt(claims Claims, cmp time.Time, req bool) bool {
|
2022-08-27 14:07:17 +03:00
|
|
|
exp := claims.GetExpirationTime()
|
New Validation API
Some guidelines in designing the new validation API
* Previously, the `Valid` method was placed on the claim, which was always not entirely semantically correct, since the validity is concerning the token, not the claims. Although the validity of the token is based on the processing of the claims (such as `exp`). Therefore, the function `Valid` was removed from the `Claims` interface and the single canonical way to retrieve the validity of the token is to retrieve the `Valid` property of the `Token` struct.
* The previous fact was enhanced by the fact that most claims implementations had additional exported `VerifyXXX` functions, which are now removed
* All validation errors should be comparable with `errors.Is` to determine, why a particular validation has failed
* Developers want to adjust validation options. Popular options include:
* Leeway when processing exp, nbf, iat
* Not verifying `iat`, since this is actually just an informational claim. When purely looking at the standard, this should probably the default
* Verifying `aud` by default, which actually the standard sort of demands. We need to see how strong we want to enforce this
* Developers want to create their own claim types, mostly by embedding one of the existing types such as `RegisteredClaims`.
* Sometimes there is the need to further tweak the validation of a token by checking the value of a custom claim. Previously, this was possibly by overriding `Valid`. However, this was error-prone, e.g., if the original `Valid` was not called. Therefore, we should provide an easy way for *additional* checks, without by-passing the necessary validations
This leads to the following two major changes:
* The `Claims` interface now represents a set of functions that return the mandatory claims represented in a token, rather than just a `Valid` function. This is also more semantically correct.
* All validation tasks are offloaded to a new (optional) `Validator`, which can also be configured with appropriate options. If no custom validator was supplied, a default one is used.
2022-08-27 13:07:09 +03:00
|
|
|
if exp == nil {
|
|
|
|
return verifyExp(nil, cmp, req, v.leeway)
|
|
|
|
}
|
|
|
|
|
|
|
|
return verifyExp(&exp.Time, cmp, req, v.leeway)
|
|
|
|
}
|
|
|
|
|
|
|
|
// VerifyIssuedAt compares the iat claim against cmp (cmp >= iat).
|
|
|
|
// If req is false, it will return true, if iat is unset.
|
|
|
|
func (v *Validator) VerifyIssuedAt(claims Claims, cmp time.Time, req bool) bool {
|
|
|
|
iat := claims.GetIssuedAt()
|
|
|
|
if iat == nil {
|
|
|
|
return verifyIat(nil, cmp, req, v.leeway)
|
|
|
|
}
|
|
|
|
|
|
|
|
return verifyIat(&iat.Time, cmp, req, v.leeway)
|
|
|
|
}
|
|
|
|
|
|
|
|
// VerifyNotBefore compares the nbf claim against cmp (cmp >= nbf).
|
|
|
|
// If req is false, it will return true, if nbf is unset.
|
|
|
|
func (v *Validator) VerifyNotBefore(claims Claims, cmp time.Time, req bool) bool {
|
|
|
|
nbf := claims.GetNotBefore()
|
|
|
|
if nbf == nil {
|
|
|
|
return verifyNbf(nil, cmp, req, v.leeway)
|
|
|
|
}
|
|
|
|
|
|
|
|
return verifyNbf(&nbf.Time, cmp, req, v.leeway)
|
|
|
|
}
|
|
|
|
|
|
|
|
// VerifyIssuer compares the iss claim against cmp.
|
|
|
|
// If required is false, this method will return true if the value matches or is unset
|
|
|
|
func (v *Validator) VerifyIssuer(claims Claims, cmp string, req bool) bool {
|
|
|
|
return verifyIss(claims.GetIssuer(), cmp, req)
|
|
|
|
}
|
|
|
|
|
|
|
|
// ----- helpers
|
|
|
|
|
|
|
|
func verifyAud(aud []string, cmp string, required bool) bool {
|
|
|
|
if len(aud) == 0 {
|
|
|
|
return !required
|
|
|
|
}
|
|
|
|
// use a var here to keep constant time compare when looping over a number of claims
|
|
|
|
result := false
|
|
|
|
|
|
|
|
var stringClaims string
|
|
|
|
for _, a := range aud {
|
|
|
|
if subtle.ConstantTimeCompare([]byte(a), []byte(cmp)) != 0 {
|
|
|
|
result = true
|
|
|
|
}
|
|
|
|
stringClaims = stringClaims + a
|
|
|
|
}
|
|
|
|
|
|
|
|
// case where "" is sent in one or many aud claims
|
2022-10-15 23:21:15 +03:00
|
|
|
if stringClaims == "" {
|
New Validation API
Some guidelines in designing the new validation API
* Previously, the `Valid` method was placed on the claim, which was always not entirely semantically correct, since the validity is concerning the token, not the claims. Although the validity of the token is based on the processing of the claims (such as `exp`). Therefore, the function `Valid` was removed from the `Claims` interface and the single canonical way to retrieve the validity of the token is to retrieve the `Valid` property of the `Token` struct.
* The previous fact was enhanced by the fact that most claims implementations had additional exported `VerifyXXX` functions, which are now removed
* All validation errors should be comparable with `errors.Is` to determine, why a particular validation has failed
* Developers want to adjust validation options. Popular options include:
* Leeway when processing exp, nbf, iat
* Not verifying `iat`, since this is actually just an informational claim. When purely looking at the standard, this should probably the default
* Verifying `aud` by default, which actually the standard sort of demands. We need to see how strong we want to enforce this
* Developers want to create their own claim types, mostly by embedding one of the existing types such as `RegisteredClaims`.
* Sometimes there is the need to further tweak the validation of a token by checking the value of a custom claim. Previously, this was possibly by overriding `Valid`. However, this was error-prone, e.g., if the original `Valid` was not called. Therefore, we should provide an easy way for *additional* checks, without by-passing the necessary validations
This leads to the following two major changes:
* The `Claims` interface now represents a set of functions that return the mandatory claims represented in a token, rather than just a `Valid` function. This is also more semantically correct.
* All validation tasks are offloaded to a new (optional) `Validator`, which can also be configured with appropriate options. If no custom validator was supplied, a default one is used.
2022-08-27 13:07:09 +03:00
|
|
|
return !required
|
|
|
|
}
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
func verifyExp(exp *time.Time, now time.Time, required bool, skew time.Duration) bool {
|
|
|
|
if exp == nil {
|
|
|
|
return !required
|
|
|
|
}
|
|
|
|
|
|
|
|
return now.Before((*exp).Add(+skew))
|
|
|
|
}
|
|
|
|
|
|
|
|
func verifyIat(iat *time.Time, now time.Time, required bool, skew time.Duration) bool {
|
|
|
|
if iat == nil {
|
|
|
|
return !required
|
|
|
|
}
|
|
|
|
|
|
|
|
t := (*iat).Add(-skew)
|
|
|
|
return now.After(t) || now.Equal(t)
|
|
|
|
}
|
|
|
|
|
|
|
|
func verifyNbf(nbf *time.Time, now time.Time, required bool, skew time.Duration) bool {
|
|
|
|
if nbf == nil {
|
|
|
|
return !required
|
|
|
|
}
|
|
|
|
|
|
|
|
t := (*nbf).Add(-skew)
|
|
|
|
return now.After(t) || now.Equal(t)
|
|
|
|
}
|
|
|
|
|
|
|
|
func verifyIss(iss string, cmp string, required bool) bool {
|
|
|
|
if iss == "" {
|
|
|
|
return !required
|
|
|
|
}
|
|
|
|
if subtle.ConstantTimeCompare([]byte(iss), []byte(cmp)) != 0 {
|
|
|
|
return true
|
|
|
|
} else {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|