code.gitea.io/gitea@v1.22.3/services/actions/auth.go (about) 1 // Copyright 2024 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package actions 5 6 import ( 7 "fmt" 8 "net/http" 9 "strings" 10 "time" 11 12 "code.gitea.io/gitea/modules/json" 13 "code.gitea.io/gitea/modules/log" 14 "code.gitea.io/gitea/modules/setting" 15 16 "github.com/golang-jwt/jwt/v5" 17 ) 18 19 type actionsClaims struct { 20 jwt.RegisteredClaims 21 Scp string `json:"scp"` 22 TaskID int64 23 RunID int64 24 JobID int64 25 Ac string `json:"ac"` 26 } 27 28 type actionsCacheScope struct { 29 Scope string 30 Permission actionsCachePermission 31 } 32 33 type actionsCachePermission int 34 35 const ( 36 actionsCachePermissionRead = 1 << iota 37 actionsCachePermissionWrite 38 ) 39 40 func CreateAuthorizationToken(taskID, runID, jobID int64) (string, error) { 41 now := time.Now() 42 43 ac, err := json.Marshal(&[]actionsCacheScope{ 44 { 45 Scope: "", 46 Permission: actionsCachePermissionWrite, 47 }, 48 }) 49 if err != nil { 50 return "", err 51 } 52 53 claims := actionsClaims{ 54 RegisteredClaims: jwt.RegisteredClaims{ 55 ExpiresAt: jwt.NewNumericDate(now.Add(24 * time.Hour)), 56 NotBefore: jwt.NewNumericDate(now), 57 }, 58 Scp: fmt.Sprintf("Actions.Results:%d:%d", runID, jobID), 59 Ac: string(ac), 60 TaskID: taskID, 61 RunID: runID, 62 JobID: jobID, 63 } 64 token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) 65 66 tokenString, err := token.SignedString(setting.GetGeneralTokenSigningSecret()) 67 if err != nil { 68 return "", err 69 } 70 71 return tokenString, nil 72 } 73 74 func ParseAuthorizationToken(req *http.Request) (int64, error) { 75 h := req.Header.Get("Authorization") 76 if h == "" { 77 return 0, nil 78 } 79 80 parts := strings.SplitN(h, " ", 2) 81 if len(parts) != 2 { 82 log.Error("split token failed: %s", h) 83 return 0, fmt.Errorf("split token failed") 84 } 85 86 token, err := jwt.ParseWithClaims(parts[1], &actionsClaims{}, func(t *jwt.Token) (any, error) { 87 if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok { 88 return nil, fmt.Errorf("unexpected signing method: %v", t.Header["alg"]) 89 } 90 return setting.GetGeneralTokenSigningSecret(), nil 91 }) 92 if err != nil { 93 return 0, err 94 } 95 96 c, ok := token.Claims.(*actionsClaims) 97 if !token.Valid || !ok { 98 return 0, fmt.Errorf("invalid token claim") 99 } 100 101 return c.TaskID, nil 102 }