* 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>
		
			
				
	
	
		
			99 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			99 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2021 The Gitea Authors. All rights reserved.
 | 
						|
// Use of this source code is governed by a MIT-style
 | 
						|
// license that can be found in the LICENSE file.
 | 
						|
 | 
						|
package oauth2
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"code.gitea.io/gitea/modules/timeutil"
 | 
						|
 | 
						|
	"github.com/golang-jwt/jwt/v4"
 | 
						|
)
 | 
						|
 | 
						|
// ___________     __
 | 
						|
// \__    ___/___ |  | __ ____   ____
 | 
						|
//   |    | /  _ \|  |/ // __ \ /    \
 | 
						|
//   |    |(  <_> )    <\  ___/|   |  \
 | 
						|
//   |____| \____/|__|_ \\___  >___|  /
 | 
						|
//                     \/    \/     \/
 | 
						|
 | 
						|
// Token represents an Oauth grant
 | 
						|
 | 
						|
// TokenType represents the type of token for an oauth application
 | 
						|
type TokenType int
 | 
						|
 | 
						|
const (
 | 
						|
	// TypeAccessToken is a token with short lifetime to access the api
 | 
						|
	TypeAccessToken TokenType = 0
 | 
						|
	// TypeRefreshToken is token with long lifetime to refresh access tokens obtained by the client
 | 
						|
	TypeRefreshToken = iota
 | 
						|
)
 | 
						|
 | 
						|
// Token represents a JWT token used to authenticate a client
 | 
						|
type Token struct {
 | 
						|
	GrantID int64     `json:"gnt"`
 | 
						|
	Type    TokenType `json:"tt"`
 | 
						|
	Counter int64     `json:"cnt,omitempty"`
 | 
						|
	jwt.RegisteredClaims
 | 
						|
}
 | 
						|
 | 
						|
// ParseToken parses a signed jwt string
 | 
						|
func ParseToken(jwtToken string, signingKey JWTSigningKey) (*Token, error) {
 | 
						|
	parsedToken, err := jwt.ParseWithClaims(jwtToken, &Token{}, func(token *jwt.Token) (interface{}, error) {
 | 
						|
		if token.Method == nil || token.Method.Alg() != signingKey.SigningMethod().Alg() {
 | 
						|
			return nil, fmt.Errorf("unexpected signing algo: %v", token.Header["alg"])
 | 
						|
		}
 | 
						|
		return signingKey.VerifyKey(), nil
 | 
						|
	})
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	var token *Token
 | 
						|
	var ok bool
 | 
						|
	if token, ok = parsedToken.Claims.(*Token); !ok || !parsedToken.Valid {
 | 
						|
		return nil, fmt.Errorf("invalid token")
 | 
						|
	}
 | 
						|
	return token, nil
 | 
						|
}
 | 
						|
 | 
						|
// SignToken signs the token with the JWT secret
 | 
						|
func (token *Token) SignToken(signingKey JWTSigningKey) (string, error) {
 | 
						|
	token.IssuedAt = jwt.NewNumericDate(time.Now())
 | 
						|
	jwtToken := jwt.NewWithClaims(signingKey.SigningMethod(), token)
 | 
						|
	signingKey.PreProcessToken(jwtToken)
 | 
						|
	return jwtToken.SignedString(signingKey.SignKey())
 | 
						|
}
 | 
						|
 | 
						|
// OIDCToken represents an OpenID Connect id_token
 | 
						|
type OIDCToken struct {
 | 
						|
	jwt.RegisteredClaims
 | 
						|
	Nonce string `json:"nonce,omitempty"`
 | 
						|
 | 
						|
	// Scope profile
 | 
						|
	Name              string             `json:"name,omitempty"`
 | 
						|
	PreferredUsername string             `json:"preferred_username,omitempty"`
 | 
						|
	Profile           string             `json:"profile,omitempty"`
 | 
						|
	Picture           string             `json:"picture,omitempty"`
 | 
						|
	Website           string             `json:"website,omitempty"`
 | 
						|
	Locale            string             `json:"locale,omitempty"`
 | 
						|
	UpdatedAt         timeutil.TimeStamp `json:"updated_at,omitempty"`
 | 
						|
 | 
						|
	// Scope email
 | 
						|
	Email         string `json:"email,omitempty"`
 | 
						|
	EmailVerified bool   `json:"email_verified,omitempty"`
 | 
						|
 | 
						|
	// Groups are generated by organization and team names
 | 
						|
	Groups []string `json:"groups,omitempty"`
 | 
						|
}
 | 
						|
 | 
						|
// SignToken signs an id_token with the (symmetric) client secret key
 | 
						|
func (token *OIDCToken) SignToken(signingKey JWTSigningKey) (string, error) {
 | 
						|
	token.IssuedAt = jwt.NewNumericDate(time.Now())
 | 
						|
	jwtToken := jwt.NewWithClaims(signingKey.SigningMethod(), token)
 | 
						|
	signingKey.PreProcessToken(jwtToken)
 | 
						|
	return jwtToken.SignedString(signingKey.SignKey())
 | 
						|
}
 |