From bf741ad3815e844626a3d0e77d25a4f5f21a6ead Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 1 Aug 2022 10:23:47 +0800 Subject: [PATCH] feature: Use RegisteredClaims instead of deprecated staruct StandardClaims (#16206) Signed-off-by: wujw39640 --- src/core/service/token/authutils.go | 12 ++++++------ src/core/service/token/token_test.go | 4 ++-- src/pkg/token/claims/robot/robot.go | 8 ++++++-- src/pkg/token/claims/v2/claims.go | 11 ++++++++--- src/pkg/token/claims/v2/claims_test.go | 4 ++-- src/pkg/token/token_test.go | 14 +++++++------- 6 files changed, 31 insertions(+), 22 deletions(-) diff --git a/src/core/service/token/authutils.go b/src/core/service/token/authutils.go index 0f5dfffc3..419e780a6 100644 --- a/src/core/service/token/authutils.go +++ b/src/core/service/token/authutils.go @@ -122,14 +122,14 @@ func MakeToken(ctx context.Context, username, service string, access []*token.Re now := time.Now().UTC() claims := &v2.Claims{ - StandardClaims: jwt.StandardClaims{ + RegisteredClaims: jwt.RegisteredClaims{ Issuer: options.Issuer, Subject: username, - Audience: service, - ExpiresAt: now.Add(time.Duration(expiration) * time.Minute).Unix(), - NotBefore: now.Unix(), - IssuedAt: now.Unix(), - Id: utils.GenerateRandomStringWithLen(16), + Audience: jwt.ClaimStrings([]string{service}), + ExpiresAt: jwt.NewNumericDate(now.Add(time.Duration(expiration) * time.Minute)), + NotBefore: jwt.NewNumericDate(now), + IssuedAt: jwt.NewNumericDate(now), + ID: utils.GenerateRandomStringWithLen(16), }, Access: access, } diff --git a/src/core/service/token/token_test.go b/src/core/service/token/token_test.go index ae4d10a09..90d980f00 100644 --- a/src/core/service/token/token_test.go +++ b/src/core/service/token/token_test.go @@ -123,7 +123,7 @@ func getPublicKey(crtPath string) (*rsa.PublicKey, error) { } type harborClaims struct { - jwt.StandardClaims + jwt.RegisteredClaims // Private claims Access []*token.ResourceActions `json:"access"` } @@ -160,7 +160,7 @@ func TestMakeToken(t *testing.T) { } claims := tok.Claims.(*harborClaims) assert.Equal(t, *(claims.Access[0]), *(ra[0]), "Access mismatch") - assert.Equal(t, claims.Audience, svc, "Audience mismatch") + assert.Equal(t, claims.Audience, jwt.ClaimStrings([]string{svc}), "Audience mismatch") } type parserTestRec struct { diff --git a/src/pkg/token/claims/robot/robot.go b/src/pkg/token/claims/robot/robot.go index ff0a0ba4e..d477ed800 100644 --- a/src/pkg/token/claims/robot/robot.go +++ b/src/pkg/token/claims/robot/robot.go @@ -8,9 +8,13 @@ import ( "github.com/goharbor/harbor/src/pkg/permission/types" ) +func init() { + jwt.MarshalSingleStringAsArray = false +} + // Claim implements the interface of jwt.Claims type Claim struct { - jwt.StandardClaims + jwt.RegisteredClaims TokenID int64 `json:"id"` ProjectID int64 `json:"pid"` Access []*types.Policy `json:"access"` @@ -27,7 +31,7 @@ func (rc Claim) Valid() error { if rc.Access == nil { return errors.New("the access info cannot be nil") } - stdErr := rc.StandardClaims.Valid() + stdErr := rc.RegisteredClaims.Valid() if stdErr != nil { return stdErr } diff --git a/src/pkg/token/claims/v2/claims.go b/src/pkg/token/claims/v2/claims.go index bf6f7158f..fb350be46 100644 --- a/src/pkg/token/claims/v2/claims.go +++ b/src/pkg/token/claims/v2/claims.go @@ -1,12 +1,17 @@ package v2 import ( + "crypto/subtle" "fmt" "github.com/docker/distribution/registry/auth/token" "github.com/golang-jwt/jwt/v4" ) +func init() { + jwt.MarshalSingleStringAsArray = false +} + const ( // Issuer is the only valid issuer for jwt token sent to /v2/xxxx Issuer = "harbor-token-issuer" @@ -14,16 +19,16 @@ const ( // Claims represents the token claims that encapsulated in a JWT token for registry/notary resources type Claims struct { - jwt.StandardClaims + jwt.RegisteredClaims Access []*token.ResourceActions `json:"access"` } // Valid checks if the issuer is harbor func (c *Claims) Valid() error { - if err := c.StandardClaims.Valid(); err != nil { + if err := c.RegisteredClaims.Valid(); err != nil { return err } - if !c.VerifyIssuer(Issuer, true) { + if subtle.ConstantTimeCompare([]byte(c.Issuer), []byte(Issuer)) == 0 { return fmt.Errorf("invalid token issuer: %s", c.Issuer) } return nil diff --git a/src/pkg/token/claims/v2/claims_test.go b/src/pkg/token/claims/v2/claims_test.go index e8ff4277d..6af09ae22 100644 --- a/src/pkg/token/claims/v2/claims_test.go +++ b/src/pkg/token/claims/v2/claims_test.go @@ -15,7 +15,7 @@ func TestValid(t *testing.T) { }{ { claims: Claims{ - StandardClaims: jwt.StandardClaims{ + RegisteredClaims: jwt.RegisteredClaims{ Issuer: "anonymous", }, Access: []*token.ResourceActions{}, @@ -24,7 +24,7 @@ func TestValid(t *testing.T) { }, { claims: Claims{ - StandardClaims: jwt.StandardClaims{ + RegisteredClaims: jwt.RegisteredClaims{ Issuer: Issuer, }, Access: []*token.ResourceActions{}, diff --git a/src/pkg/token/token_test.go b/src/pkg/token/token_test.go index 417f62a57..fa87d7518 100644 --- a/src/pkg/token/token_test.go +++ b/src/pkg/token/token_test.go @@ -33,13 +33,13 @@ func TestNew(t *testing.T) { tokenID := int64(123) projectID := int64(321) tokenExpiration := time.Duration(10) * 24 * time.Hour - expiresAt := time.Now().UTC().Add(tokenExpiration).Unix() + expiresAt := time.Now().UTC().Add(tokenExpiration) robot := robot_claim.Claim{ TokenID: tokenID, ProjectID: projectID, Access: policies, - StandardClaims: jwt.StandardClaims{ - ExpiresAt: expiresAt, + RegisteredClaims: jwt.RegisteredClaims{ + ExpiresAt: jwt.NewNumericDate(expiresAt), }, } defaultOpt := DefaultTokenOptions() @@ -60,20 +60,20 @@ func TestRaw(t *testing.T) { Resource: "/project/library/repository", Action: "pull", } - policies := []*types.Policy{} + var policies []*types.Policy policies = append(policies, rbacPolicy) tokenID := int64(123) projectID := int64(321) tokenExpiration := time.Duration(10) * 24 * time.Hour - expiresAt := time.Now().UTC().Add(tokenExpiration).Unix() + expiresAt := time.Now().UTC().Add(tokenExpiration) robot := robot_claim.Claim{ TokenID: tokenID, ProjectID: projectID, Access: policies, - StandardClaims: jwt.StandardClaims{ - ExpiresAt: expiresAt, + RegisteredClaims: jwt.RegisteredClaims{ + ExpiresAt: jwt.NewNumericDate(expiresAt), }, } defaultOpt := DefaultTokenOptions()