diff options
author | Daniel Baumann <daniel@debian.org> | 2024-10-18 20:33:49 +0200 |
---|---|---|
committer | Daniel Baumann <daniel@debian.org> | 2024-12-12 23:57:56 +0100 |
commit | e68b9d00a6e05b3a941f63ffb696f91e554ac5ec (patch) | |
tree | 97775d6c13b0f416af55314eb6a89ef792474615 /services/auth/source/oauth2/token.go | |
parent | Initial commit. (diff) | |
download | forgejo-e68b9d00a6e05b3a941f63ffb696f91e554ac5ec.tar.xz forgejo-e68b9d00a6e05b3a941f63ffb696f91e554ac5ec.zip |
Adding upstream version 9.0.3.
Signed-off-by: Daniel Baumann <daniel@debian.org>
Diffstat (limited to 'services/auth/source/oauth2/token.go')
-rw-r--r-- | services/auth/source/oauth2/token.go | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/services/auth/source/oauth2/token.go b/services/auth/source/oauth2/token.go new file mode 100644 index 0000000..3405619 --- /dev/null +++ b/services/auth/source/oauth2/token.go @@ -0,0 +1,100 @@ +// Copyright 2021 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package oauth2 + +import ( + "fmt" + "time" + + "code.gitea.io/gitea/modules/timeutil" + + "github.com/golang-jwt/jwt/v5" +) + +// ___________ __ +// \__ ___/___ | | __ ____ ____ +// | | / _ \| |/ // __ \ / \ +// | |( <_> ) <\ ___/| | \ +// |____| \____/|__|_ \\___ >___| / +// \/ \/ \/ + +// 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) (any, 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 + } + if !parsedToken.Valid { + return nil, fmt.Errorf("invalid token") + } + 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()) +} |