From 7e82f33cee33b5a80563bfdf2da104c646d9b900 Mon Sep 17 00:00:00 2001 From: Christian Banse Date: Sun, 28 Aug 2022 18:17:04 +0200 Subject: [PATCH] Remove `StandardClaims` in favor of `RegisteredClaims` (#235) This PR removes the old legacy standard claims, which have been deprecated since the beginning of the `v4` module in favor of the newer `RegisteredClaims`. Removing them before any further changes to the validation API is quite useful, as less code needs to be adapated. --- claims.go | 96 -------------------------------------------------- parser_test.go | 23 ++---------- token_test.go | 4 +-- 3 files changed, 5 insertions(+), 118 deletions(-) diff --git a/claims.go b/claims.go index 9d95cad..b115d5e 100644 --- a/claims.go +++ b/claims.go @@ -119,102 +119,6 @@ func (c *RegisteredClaims) VerifyIssuer(cmp string, req bool) bool { return verifyIss(c.Issuer, cmp, req) } -// StandardClaims are a structured version of the JWT Claims Set, as referenced at -// https://datatracker.ietf.org/doc/html/rfc7519#section-4. They do not follow the -// specification exactly, since they were based on an earlier draft of the -// specification and not updated. The main difference is that they only -// support integer-based date fields and singular audiences. This might lead to -// incompatibilities with other JWT implementations. The use of this is discouraged, instead -// the newer RegisteredClaims struct should be used. -// -// Deprecated: Use RegisteredClaims instead for a forward-compatible way to access registered claims in a struct. -type StandardClaims struct { - Audience string `json:"aud,omitempty"` - ExpiresAt int64 `json:"exp,omitempty"` - Id string `json:"jti,omitempty"` - IssuedAt int64 `json:"iat,omitempty"` - Issuer string `json:"iss,omitempty"` - NotBefore int64 `json:"nbf,omitempty"` - Subject string `json:"sub,omitempty"` -} - -// Valid validates time based claims "exp, iat, nbf". There is no accounting for clock skew. -// As well, if any of the above claims are not in the token, it will still -// be considered a valid claim. -func (c StandardClaims) Valid() error { - vErr := new(ValidationError) - now := TimeFunc().Unix() - - // The claims below are optional, by default, so if they are set to the - // default value in Go, let's not fail the verification for them. - if !c.VerifyExpiresAt(now, false) { - delta := time.Unix(now, 0).Sub(time.Unix(c.ExpiresAt, 0)) - vErr.Inner = fmt.Errorf("%s by %s", ErrTokenExpired, delta) - vErr.Errors |= ValidationErrorExpired - } - - if !c.VerifyIssuedAt(now, false) { - vErr.Inner = ErrTokenUsedBeforeIssued - vErr.Errors |= ValidationErrorIssuedAt - } - - if !c.VerifyNotBefore(now, false) { - vErr.Inner = ErrTokenNotValidYet - vErr.Errors |= ValidationErrorNotValidYet - } - - 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 (c *StandardClaims) VerifyAudience(cmp string, req bool) bool { - return verifyAud([]string{c.Audience}, cmp, req) -} - -// VerifyExpiresAt compares the exp claim against cmp (cmp < exp). -// If req is false, it will return true, if exp is unset. -func (c *StandardClaims) VerifyExpiresAt(cmp int64, req bool) bool { - if c.ExpiresAt == 0 { - return verifyExp(nil, time.Unix(cmp, 0), req) - } - - t := time.Unix(c.ExpiresAt, 0) - return verifyExp(&t, time.Unix(cmp, 0), req) -} - -// VerifyIssuedAt compares the iat claim against cmp (cmp >= iat). -// If req is false, it will return true, if iat is unset. -func (c *StandardClaims) VerifyIssuedAt(cmp int64, req bool) bool { - if c.IssuedAt == 0 { - return verifyIat(nil, time.Unix(cmp, 0), req) - } - - t := time.Unix(c.IssuedAt, 0) - return verifyIat(&t, time.Unix(cmp, 0), req) -} - -// VerifyNotBefore compares the nbf claim against cmp (cmp >= nbf). -// If req is false, it will return true, if nbf is unset. -func (c *StandardClaims) VerifyNotBefore(cmp int64, req bool) bool { - if c.NotBefore == 0 { - return verifyNbf(nil, time.Unix(cmp, 0), req) - } - - t := time.Unix(c.NotBefore, 0) - return verifyNbf(&t, time.Unix(cmp, 0), req) -} - -// VerifyIssuer compares the iss claim against cmp. -// If required is false, this method will return true if the value matches or is unset -func (c *StandardClaims) VerifyIssuer(cmp string, req bool) bool { - return verifyIss(c.Issuer, cmp, req) -} - // ----- helpers func verifyAud(aud []string, cmp string, required bool) bool { diff --git a/parser_test.go b/parser_test.go index 460ee50..9b09b16 100644 --- a/parser_test.go +++ b/parser_test.go @@ -199,19 +199,6 @@ var jwtTestData = []struct { &jwt.Parser{UseJSONNumber: true}, jwt.SigningMethodRS256, }, - { - "Standard Claims", - "", - defaultKeyFunc, - &jwt.StandardClaims{ - ExpiresAt: time.Now().Add(time.Second * 10).Unix(), - }, - true, - 0, - nil, - &jwt.Parser{UseJSONNumber: true}, - jwt.SigningMethodRS256, - }, { "JSON Number - basic expired", "", // autogen @@ -360,8 +347,6 @@ func TestParser_Parse(t *testing.T) { switch data.claims.(type) { case jwt.MapClaims: token, err = parser.ParseWithClaims(data.tokenString, jwt.MapClaims{}, data.keyfunc) - case *jwt.StandardClaims: - token, err = parser.ParseWithClaims(data.tokenString, &jwt.StandardClaims{}, data.keyfunc) case *jwt.RegisteredClaims: token, err = parser.ParseWithClaims(data.tokenString, &jwt.RegisteredClaims{}, data.keyfunc) } @@ -454,8 +439,6 @@ func TestParser_ParseUnverified(t *testing.T) { switch data.claims.(type) { case jwt.MapClaims: token, _, err = parser.ParseUnverified(data.tokenString, jwt.MapClaims{}) - case *jwt.StandardClaims: - token, _, err = parser.ParseUnverified(data.tokenString, &jwt.StandardClaims{}) case *jwt.RegisteredClaims: token, _, err = parser.ParseUnverified(data.tokenString, &jwt.RegisteredClaims{}) } @@ -605,9 +588,9 @@ func BenchmarkParseUnverified(b *testing.B) { b.Run("map_claims", func(b *testing.B) { benchmarkParsing(b, parser, data.tokenString, jwt.MapClaims{}) }) - case *jwt.StandardClaims: - b.Run("standard_claims", func(b *testing.B) { - benchmarkParsing(b, parser, data.tokenString, &jwt.StandardClaims{}) + case *jwt.RegisteredClaims: + b.Run("registered_claims", func(b *testing.B) { + benchmarkParsing(b, parser, data.tokenString, &jwt.RegisteredClaims{}) }) } } diff --git a/token_test.go b/token_test.go index cc75725..52a0021 100644 --- a/token_test.go +++ b/token_test.go @@ -30,7 +30,7 @@ func TestToken_SigningString(t1 *testing.T) { "typ": "JWT", "alg": jwt.SigningMethodHS256.Alg(), }, - Claims: jwt.StandardClaims{}, + Claims: jwt.RegisteredClaims{}, Signature: "", Valid: false, }, @@ -67,7 +67,7 @@ func BenchmarkToken_SigningString(b *testing.B) { "typ": "JWT", "alg": jwt.SigningMethodHS256.Alg(), }, - Claims: jwt.StandardClaims{}, + Claims: jwt.RegisteredClaims{}, } b.Run("BenchmarkToken_SigningString", func(b *testing.B) { b.ResetTimer()