forked from mirror/jwt
GetExpiresAt() -> GetExpirationTime()
This commit is contained in:
parent
3098ea8845
commit
1d88540186
59
claims.go
59
claims.go
|
@ -7,66 +7,9 @@ package jwt
|
||||||
// https://datatracker.ietf.org/doc/html/rfc7519#section-4.1 namely `exp`,
|
// https://datatracker.ietf.org/doc/html/rfc7519#section-4.1 namely `exp`,
|
||||||
// `iat`, `nbf`, `iss` and `aud`.
|
// `iat`, `nbf`, `iss` and `aud`.
|
||||||
type Claims interface {
|
type Claims interface {
|
||||||
GetExpiryAt() *NumericDate
|
GetExpirationTime() *NumericDate
|
||||||
GetIssuedAt() *NumericDate
|
GetIssuedAt() *NumericDate
|
||||||
GetNotBefore() *NumericDate
|
GetNotBefore() *NumericDate
|
||||||
GetIssuer() string
|
GetIssuer() string
|
||||||
GetAudience() ClaimStrings
|
GetAudience() ClaimStrings
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisteredClaims are a structured version of the JWT Claims Set,
|
|
||||||
// restricted to Registered Claim Names, as referenced at
|
|
||||||
// https://datatracker.ietf.org/doc/html/rfc7519#section-4.1
|
|
||||||
//
|
|
||||||
// This type can be used on its own, but then additional private and
|
|
||||||
// public claims embedded in the JWT will not be parsed. The typical use-case
|
|
||||||
// therefore is to embedded this in a user-defined claim type.
|
|
||||||
//
|
|
||||||
// See examples for how to use this with your own claim types.
|
|
||||||
type RegisteredClaims struct {
|
|
||||||
// the `iss` (Issuer) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.1
|
|
||||||
Issuer string `json:"iss,omitempty"`
|
|
||||||
|
|
||||||
// the `sub` (Subject) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.2
|
|
||||||
Subject string `json:"sub,omitempty"`
|
|
||||||
|
|
||||||
// the `aud` (Audience) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.3
|
|
||||||
Audience ClaimStrings `json:"aud,omitempty"`
|
|
||||||
|
|
||||||
// the `exp` (Expiration Time) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4
|
|
||||||
ExpiresAt *NumericDate `json:"exp,omitempty"`
|
|
||||||
|
|
||||||
// the `nbf` (Not Before) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.5
|
|
||||||
NotBefore *NumericDate `json:"nbf,omitempty"`
|
|
||||||
|
|
||||||
// the `iat` (Issued At) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.6
|
|
||||||
IssuedAt *NumericDate `json:"iat,omitempty"`
|
|
||||||
|
|
||||||
// the `jti` (JWT ID) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.7
|
|
||||||
ID string `json:"jti,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetExpiryAt implements the Claims interface.
|
|
||||||
func (c RegisteredClaims) GetExpiryAt() *NumericDate {
|
|
||||||
return c.ExpiresAt
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetNotBefore implements the Claims interface.
|
|
||||||
func (c RegisteredClaims) GetNotBefore() *NumericDate {
|
|
||||||
return c.NotBefore
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetIssuedAt implements the Claims interface.
|
|
||||||
func (c RegisteredClaims) GetIssuedAt() *NumericDate {
|
|
||||||
return c.IssuedAt
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetAudience implements the Claims interface.
|
|
||||||
func (c RegisteredClaims) GetAudience() ClaimStrings {
|
|
||||||
return c.Audience
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetIssuer implements the Claims interface.
|
|
||||||
func (c RegisteredClaims) GetIssuer() string {
|
|
||||||
return c.Issuer
|
|
||||||
}
|
|
||||||
|
|
|
@ -8,8 +8,8 @@ import (
|
||||||
// This is the default claims type if you don't supply one
|
// This is the default claims type if you don't supply one
|
||||||
type MapClaims map[string]interface{}
|
type MapClaims map[string]interface{}
|
||||||
|
|
||||||
// GetExpiryAt implements the Claims interface.
|
// GetExpirationTime implements the Claims interface.
|
||||||
func (m MapClaims) GetExpiryAt() *NumericDate {
|
func (m MapClaims) GetExpirationTime() *NumericDate {
|
||||||
return m.ParseNumericDate("exp")
|
return m.ParseNumericDate("exp")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,6 +33,9 @@ func (m MapClaims) GetIssuer() string {
|
||||||
return m.ParseString("iss")
|
return m.ParseString("iss")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseNumericDate tries to parse a key in the map claims type as a number
|
||||||
|
// date. This will succeed, if the underlying type is either a [float64] or a
|
||||||
|
// [json.Number]. Otherwise, nil will be returned.
|
||||||
func (m MapClaims) ParseNumericDate(key string) *NumericDate {
|
func (m MapClaims) ParseNumericDate(key string) *NumericDate {
|
||||||
v, ok := m[key]
|
v, ok := m[key]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -55,6 +58,8 @@ func (m MapClaims) ParseNumericDate(key string) *NumericDate {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseClaimsString tries to parse a key in the map claims type as a
|
||||||
|
// [ClaimsStrings] type, which can either be a string or an array of string.
|
||||||
func (m MapClaims) ParseClaimsString(key string) ClaimStrings {
|
func (m MapClaims) ParseClaimsString(key string) ClaimStrings {
|
||||||
var cs []string
|
var cs []string
|
||||||
switch v := m[key].(type) {
|
switch v := m[key].(type) {
|
||||||
|
@ -75,6 +80,8 @@ func (m MapClaims) ParseClaimsString(key string) ClaimStrings {
|
||||||
return cs
|
return cs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseString tries to parse a key in the map claims type as a
|
||||||
|
// [string] type. Otherwise, an empty string is returned.
|
||||||
func (m MapClaims) ParseString(key string) string {
|
func (m MapClaims) ParseString(key string) string {
|
||||||
iss, _ := m[key].(string)
|
iss, _ := m[key].(string)
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ package jwt_test
|
||||||
import (
|
import (
|
||||||
"crypto"
|
"crypto"
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
@ -55,7 +56,7 @@ var jwtTestData = []struct {
|
||||||
parser *jwt.Parser
|
parser *jwt.Parser
|
||||||
signingMethod jwt.SigningMethod // The method to sign the JWT token for test purpose
|
signingMethod jwt.SigningMethod // The method to sign the JWT token for test purpose
|
||||||
}{
|
}{
|
||||||
/*{
|
{
|
||||||
"basic",
|
"basic",
|
||||||
"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.FhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg",
|
"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.FhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg",
|
||||||
defaultKeyFunc,
|
defaultKeyFunc,
|
||||||
|
@ -317,7 +318,7 @@ var jwtTestData = []struct {
|
||||||
[]error{jwt.ErrTokenNotValidYet},
|
[]error{jwt.ErrTokenNotValidYet},
|
||||||
jwt.NewParser(jwt.WithValidator(jwt.NewValidator(jwt.WithLeeway(time.Minute)))),
|
jwt.NewParser(jwt.WithValidator(jwt.NewValidator(jwt.WithLeeway(time.Minute)))),
|
||||||
jwt.SigningMethodRS256,
|
jwt.SigningMethodRS256,
|
||||||
},*/
|
},
|
||||||
{
|
{
|
||||||
"RFC7519 Claims - nbf with 120s skew",
|
"RFC7519 Claims - nbf with 120s skew",
|
||||||
"", // autogen
|
"", // autogen
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
package jwt
|
||||||
|
|
||||||
|
// RegisteredClaims are a structured version of the JWT Claims Set,
|
||||||
|
// restricted to Registered Claim Names, as referenced at
|
||||||
|
// https://datatracker.ietf.org/doc/html/rfc7519#section-4.1
|
||||||
|
//
|
||||||
|
// This type can be used on its own, but then additional private and
|
||||||
|
// public claims embedded in the JWT will not be parsed. The typical use-case
|
||||||
|
// therefore is to embedded this in a user-defined claim type.
|
||||||
|
//
|
||||||
|
// See examples for how to use this with your own claim types.
|
||||||
|
type RegisteredClaims struct {
|
||||||
|
// the `iss` (Issuer) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.1
|
||||||
|
Issuer string `json:"iss,omitempty"`
|
||||||
|
|
||||||
|
// the `sub` (Subject) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.2
|
||||||
|
Subject string `json:"sub,omitempty"`
|
||||||
|
|
||||||
|
// the `aud` (Audience) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.3
|
||||||
|
Audience ClaimStrings `json:"aud,omitempty"`
|
||||||
|
|
||||||
|
// the `exp` (Expiration Time) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4
|
||||||
|
ExpiresAt *NumericDate `json:"exp,omitempty"`
|
||||||
|
|
||||||
|
// the `nbf` (Not Before) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.5
|
||||||
|
NotBefore *NumericDate `json:"nbf,omitempty"`
|
||||||
|
|
||||||
|
// the `iat` (Issued At) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.6
|
||||||
|
IssuedAt *NumericDate `json:"iat,omitempty"`
|
||||||
|
|
||||||
|
// the `jti` (JWT ID) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.7
|
||||||
|
ID string `json:"jti,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetExpirationTime implements the Claims interface.
|
||||||
|
func (c RegisteredClaims) GetExpirationTime() *NumericDate {
|
||||||
|
return c.ExpiresAt
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNotBefore implements the Claims interface.
|
||||||
|
func (c RegisteredClaims) GetNotBefore() *NumericDate {
|
||||||
|
return c.NotBefore
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetIssuedAt implements the Claims interface.
|
||||||
|
func (c RegisteredClaims) GetIssuedAt() *NumericDate {
|
||||||
|
return c.IssuedAt
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAudience implements the Claims interface.
|
||||||
|
func (c RegisteredClaims) GetAudience() ClaimStrings {
|
||||||
|
return c.Audience
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetIssuer implements the Claims interface.
|
||||||
|
func (c RegisteredClaims) GetIssuer() string {
|
||||||
|
return c.Issuer
|
||||||
|
}
|
|
@ -15,7 +15,7 @@ func (v *Validator) Validate(claims Claims) error {
|
||||||
now := TimeFunc()
|
now := TimeFunc()
|
||||||
|
|
||||||
if !v.VerifyExpiresAt(claims, now, false) {
|
if !v.VerifyExpiresAt(claims, now, false) {
|
||||||
exp := claims.GetExpiryAt()
|
exp := claims.GetExpirationTime()
|
||||||
delta := now.Sub(exp.Time)
|
delta := now.Sub(exp.Time)
|
||||||
vErr.Inner = fmt.Errorf("%s by %s", ErrTokenExpired, delta)
|
vErr.Inner = fmt.Errorf("%s by %s", ErrTokenExpired, delta)
|
||||||
vErr.Errors |= ValidationErrorExpired
|
vErr.Errors |= ValidationErrorExpired
|
||||||
|
@ -47,7 +47,7 @@ func (v *Validator) VerifyAudience(claims Claims, cmp string, req bool) bool {
|
||||||
// VerifyExpiresAt compares the exp claim against cmp (cmp < exp).
|
// VerifyExpiresAt compares the exp claim against cmp (cmp < exp).
|
||||||
// If req is false, it will return true, if exp is unset.
|
// If req is false, it will return true, if exp is unset.
|
||||||
func (v *Validator) VerifyExpiresAt(claims Claims, cmp time.Time, req bool) bool {
|
func (v *Validator) VerifyExpiresAt(claims Claims, cmp time.Time, req bool) bool {
|
||||||
exp := claims.GetExpiryAt()
|
exp := claims.GetExpirationTime()
|
||||||
if exp == nil {
|
if exp == nil {
|
||||||
return verifyExp(nil, cmp, req, v.leeway)
|
return verifyExp(nil, cmp, req, v.leeway)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue