From 44deae8f3dfcbdc9edda5a817c168e110864266b Mon Sep 17 00:00:00 2001
From: zeripath <art27@cantab.net>
Date: Thu, 20 Jan 2022 21:52:56 +0000
Subject: [PATCH] Refactor jwt.StandardClaims to RegisteredClaims (#18344)

* Refactor jwt.StandardClaims to RegisteredClaims

go-jwt/jwt has deprecated the StandardClaims interface to use RegisteredClaims
instead. This PR migrates to use this new format.

Signed-off-by: Andrew Thornton <art27@cantab.net>

* Apply suggestions from code review

Co-authored-by: Gusted <williamzijl7@hotmail.com>

Co-authored-by: 6543 <6543@obermui.de>
Co-authored-by: Gusted <williamzijl7@hotmail.com>
---
 cmd/serv.go                          |  7 +++----
 routers/web/auth/oauth.go            | 24 ++++++++++--------------
 services/auth/oauth2.go              |  2 +-
 services/auth/source/oauth2/token.go | 10 ++++------
 services/lfs/server.go               |  3 +--
 5 files changed, 19 insertions(+), 27 deletions(-)

diff --git a/cmd/serv.go b/cmd/serv.go
index e42213cb98..b4ef37f1dc 100644
--- a/cmd/serv.go
+++ b/cmd/serv.go
@@ -253,10 +253,9 @@ func runServ(c *cli.Context) error {
 
 		now := time.Now()
 		claims := lfs.Claims{
-			// FIXME: we need to migrate to RegisteredClaims
-			StandardClaims: jwt.StandardClaims{ // nolint
-				ExpiresAt: now.Add(setting.LFS.HTTPAuthExpiry).Unix(),
-				NotBefore: now.Unix(),
+			RegisteredClaims: jwt.RegisteredClaims{
+				ExpiresAt: jwt.NewNumericDate(now.Add(setting.LFS.HTTPAuthExpiry)),
+				NotBefore: jwt.NewNumericDate(now),
 			},
 			RepoID: results.RepoID,
 			Op:     lfsVerb,
diff --git a/routers/web/auth/oauth.go b/routers/web/auth/oauth.go
index 7bf1adf308..7793a408d8 100644
--- a/routers/web/auth/oauth.go
+++ b/routers/web/auth/oauth.go
@@ -149,9 +149,8 @@ func newAccessTokenResponse(grant *auth.OAuth2Grant, serverKey, clientKey oauth2
 	accessToken := &oauth2.Token{
 		GrantID: grant.ID,
 		Type:    oauth2.TypeAccessToken,
-		// FIXME: Migrate to RegisteredClaims
-		StandardClaims: jwt.StandardClaims{ //nolint
-			ExpiresAt: expirationDate.AsTime().Unix(),
+		RegisteredClaims: jwt.RegisteredClaims{
+			ExpiresAt: jwt.NewNumericDate(expirationDate.AsTime()),
 		},
 	}
 	signedAccessToken, err := accessToken.SignToken(serverKey)
@@ -163,14 +162,13 @@ func newAccessTokenResponse(grant *auth.OAuth2Grant, serverKey, clientKey oauth2
 	}
 
 	// generate refresh token to request an access token after it expired later
-	refreshExpirationDate := timeutil.TimeStampNow().Add(setting.OAuth2.RefreshTokenExpirationTime * 60 * 60).AsTime().Unix()
+	refreshExpirationDate := timeutil.TimeStampNow().Add(setting.OAuth2.RefreshTokenExpirationTime * 60 * 60).AsTime()
 	refreshToken := &oauth2.Token{
 		GrantID: grant.ID,
 		Counter: grant.Counter,
 		Type:    oauth2.TypeRefreshToken,
-		// FIXME: Migrate to RegisteredClaims
-		StandardClaims: jwt.StandardClaims{ // nolint
-			ExpiresAt: refreshExpirationDate,
+		RegisteredClaims: jwt.RegisteredClaims{ // nolint
+			ExpiresAt: jwt.NewNumericDate(refreshExpirationDate),
 		},
 	}
 	signedRefreshToken, err := refreshToken.SignToken(serverKey)
@@ -207,11 +205,10 @@ func newAccessTokenResponse(grant *auth.OAuth2Grant, serverKey, clientKey oauth2
 		}
 
 		idToken := &oauth2.OIDCToken{
-			// FIXME: migrate to RegisteredClaims
-			StandardClaims: jwt.StandardClaims{ //nolint
-				ExpiresAt: expirationDate.AsTime().Unix(),
+			RegisteredClaims: jwt.RegisteredClaims{
+				ExpiresAt: jwt.NewNumericDate(expirationDate.AsTime()),
 				Issuer:    setting.AppURL,
-				Audience:  app.ClientID,
+				Audience:  []string{app.ClientID},
 				Subject:   fmt.Sprint(grant.UserID),
 			},
 			Nonce: grant.Nonce,
@@ -329,8 +326,7 @@ func IntrospectOAuth(ctx *context.Context) {
 	var response struct {
 		Active bool   `json:"active"`
 		Scope  string `json:"scope,omitempty"`
-		// FIXME: Migrate to RegisteredClaims
-		jwt.StandardClaims //nolint
+		jwt.RegisteredClaims
 	}
 
 	form := web.GetForm(ctx).(*forms.IntrospectTokenForm)
@@ -344,7 +340,7 @@ func IntrospectOAuth(ctx *context.Context) {
 					response.Active = true
 					response.Scope = grant.Scope
 					response.Issuer = setting.AppURL
-					response.Audience = app.ClientID
+					response.Audience = []string{app.ClientID}
 					response.Subject = fmt.Sprint(grant.UserID)
 				}
 			}
diff --git a/services/auth/oauth2.go b/services/auth/oauth2.go
index fcff5313e3..42c91fac37 100644
--- a/services/auth/oauth2.go
+++ b/services/auth/oauth2.go
@@ -44,7 +44,7 @@ func CheckOAuthAccessToken(accessToken string) int64 {
 	if token.Type != oauth2.TypeAccessToken {
 		return 0
 	}
-	if token.ExpiresAt < time.Now().Unix() || token.IssuedAt > time.Now().Unix() {
+	if token.ExpiresAt.Before(time.Now()) || token.IssuedAt.After(time.Now()) {
 		return 0
 	}
 	return grant.UserID
diff --git a/services/auth/source/oauth2/token.go b/services/auth/source/oauth2/token.go
index 944b8da387..0c69913ff4 100644
--- a/services/auth/source/oauth2/token.go
+++ b/services/auth/source/oauth2/token.go
@@ -37,8 +37,7 @@ type Token struct {
 	GrantID int64     `json:"gnt"`
 	Type    TokenType `json:"tt"`
 	Counter int64     `json:"cnt,omitempty"`
-	// FIXME: Migrate to registered claims
-	jwt.StandardClaims
+	jwt.RegisteredClaims
 }
 
 // ParseToken parses a signed jwt string
@@ -62,7 +61,7 @@ func ParseToken(jwtToken string, signingKey JWTSigningKey) (*Token, error) {
 
 // SignToken signs the token with the JWT secret
 func (token *Token) SignToken(signingKey JWTSigningKey) (string, error) {
-	token.IssuedAt = time.Now().Unix()
+	token.IssuedAt = jwt.NewNumericDate(time.Now())
 	jwtToken := jwt.NewWithClaims(signingKey.SigningMethod(), token)
 	signingKey.PreProcessToken(jwtToken)
 	return jwtToken.SignedString(signingKey.SignKey())
@@ -70,8 +69,7 @@ func (token *Token) SignToken(signingKey JWTSigningKey) (string, error) {
 
 // OIDCToken represents an OpenID Connect id_token
 type OIDCToken struct {
-	// FIXME: Migrate to RegisteredClaims
-	jwt.StandardClaims
+	jwt.RegisteredClaims
 	Nonce string `json:"nonce,omitempty"`
 
 	// Scope profile
@@ -93,7 +91,7 @@ type OIDCToken struct {
 
 // SignToken signs an id_token with the (symmetric) client secret key
 func (token *OIDCToken) SignToken(signingKey JWTSigningKey) (string, error) {
-	token.IssuedAt = time.Now().Unix()
+	token.IssuedAt = jwt.NewNumericDate(time.Now())
 	jwtToken := jwt.NewWithClaims(signingKey.SigningMethod(), token)
 	signingKey.PreProcessToken(jwtToken)
 	return jwtToken.SignedString(signingKey.SignKey())
diff --git a/services/lfs/server.go b/services/lfs/server.go
index cdce0046b3..7c3f88e57b 100644
--- a/services/lfs/server.go
+++ b/services/lfs/server.go
@@ -45,8 +45,7 @@ type Claims struct {
 	RepoID int64
 	Op     string
 	UserID int64
-	// FIXME: Migrate to RegisteredClaims
-	jwt.StandardClaims
+	jwt.RegisteredClaims
 }
 
 // DownloadLink builds a URL to download the object.