code.gitea.io/gitea@v1.21.7/services/auth/source/oauth2/token.go (about) 1 // Copyright 2021 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package oauth2 5 6 import ( 7 "fmt" 8 "time" 9 10 "code.gitea.io/gitea/modules/timeutil" 11 12 "github.com/golang-jwt/jwt/v5" 13 ) 14 15 // ___________ __ 16 // \__ ___/___ | | __ ____ ____ 17 // | | / _ \| |/ // __ \ / \ 18 // | |( <_> ) <\ ___/| | \ 19 // |____| \____/|__|_ \\___ >___| / 20 // \/ \/ \/ 21 22 // Token represents an Oauth grant 23 24 // TokenType represents the type of token for an oauth application 25 type TokenType int 26 27 const ( 28 // TypeAccessToken is a token with short lifetime to access the api 29 TypeAccessToken TokenType = 0 30 // TypeRefreshToken is token with long lifetime to refresh access tokens obtained by the client 31 TypeRefreshToken = iota 32 ) 33 34 // Token represents a JWT token used to authenticate a client 35 type Token struct { 36 GrantID int64 `json:"gnt"` 37 Type TokenType `json:"tt"` 38 Counter int64 `json:"cnt,omitempty"` 39 jwt.RegisteredClaims 40 } 41 42 // ParseToken parses a signed jwt string 43 func ParseToken(jwtToken string, signingKey JWTSigningKey) (*Token, error) { 44 parsedToken, err := jwt.ParseWithClaims(jwtToken, &Token{}, func(token *jwt.Token) (any, error) { 45 if token.Method == nil || token.Method.Alg() != signingKey.SigningMethod().Alg() { 46 return nil, fmt.Errorf("unexpected signing algo: %v", token.Header["alg"]) 47 } 48 return signingKey.VerifyKey(), nil 49 }) 50 if err != nil { 51 return nil, err 52 } 53 if !parsedToken.Valid { 54 return nil, fmt.Errorf("invalid token") 55 } 56 var token *Token 57 var ok bool 58 if token, ok = parsedToken.Claims.(*Token); !ok || !parsedToken.Valid { 59 return nil, fmt.Errorf("invalid token") 60 } 61 return token, nil 62 } 63 64 // SignToken signs the token with the JWT secret 65 func (token *Token) SignToken(signingKey JWTSigningKey) (string, error) { 66 token.IssuedAt = jwt.NewNumericDate(time.Now()) 67 jwtToken := jwt.NewWithClaims(signingKey.SigningMethod(), token) 68 signingKey.PreProcessToken(jwtToken) 69 return jwtToken.SignedString(signingKey.SignKey()) 70 } 71 72 // OIDCToken represents an OpenID Connect id_token 73 type OIDCToken struct { 74 jwt.RegisteredClaims 75 Nonce string `json:"nonce,omitempty"` 76 77 // Scope profile 78 Name string `json:"name,omitempty"` 79 PreferredUsername string `json:"preferred_username,omitempty"` 80 Profile string `json:"profile,omitempty"` 81 Picture string `json:"picture,omitempty"` 82 Website string `json:"website,omitempty"` 83 Locale string `json:"locale,omitempty"` 84 UpdatedAt timeutil.TimeStamp `json:"updated_at,omitempty"` 85 86 // Scope email 87 Email string `json:"email,omitempty"` 88 EmailVerified bool `json:"email_verified,omitempty"` 89 90 // Groups are generated by organization and team names 91 Groups []string `json:"groups,omitempty"` 92 } 93 94 // SignToken signs an id_token with the (symmetric) client secret key 95 func (token *OIDCToken) SignToken(signingKey JWTSigningKey) (string, error) { 96 token.IssuedAt = jwt.NewNumericDate(time.Now()) 97 jwtToken := jwt.NewWithClaims(signingKey.SigningMethod(), token) 98 signingKey.PreProcessToken(jwtToken) 99 return jwtToken.SignedString(signingKey.SignKey()) 100 }