@@ -10,6 +10,36 @@ import (
1010 "github.com/github/github-mcp-server/pkg/utils"
1111)
1212
13+ << << << < HEAD
14+ == == == =
15+ type authType int
16+
17+ const (
18+ authTypeUnknown authType = iota
19+ authTypeIDE
20+ authTypeGhToken
21+ )
22+
23+ var (
24+ errMissingAuthorizationHeader = fmt .Errorf ("%w: missing required Authorization header" , mark .ErrBadRequest )
25+ errBadAuthorizationHeader = fmt .Errorf ("%w: Authorization header is badly formatted" , mark .ErrBadRequest )
26+ errUnsupportedAuthorizationHeader = fmt .Errorf ("%w: unsupported Authorization header" , mark .ErrBadRequest )
27+ )
28+
29+ var supportedGitHubPrefixes = []string {
30+ "ghp_" , // Personal access token (classic)
31+ "github_pat_" , // Fine-grained personal access token
32+ "gho_" , // OAuth access token
33+ "ghu_" , // User access token for a GitHub App
34+ "ghs_" , // Installation access token for a GitHub App (a.k.a. server-to-server token)
35+ }
36+
37+ // oldPatternRegexp is the regular expression for the old pattern of the token.
38+ // Until 2021, GitHub API tokens did not have an identifiable prefix. They
39+ // were 40 characters long and only contained the characters a-f and 0-9.
40+ var oldPatternRegexp = regexp .MustCompile (`\A[a-f0-9]{40}\z` )
41+
42+ >> >> >> > http - stack - 2
1343func ExtractUserToken (oauthCfg * oauth.Config ) func (next http.Handler ) http.Handler {
1444 return func (next http.Handler ) http.Handler {
1545 return http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
@@ -45,3 +75,45 @@ func sendAuthChallenge(w http.ResponseWriter, r *http.Request, oauthCfg *oauth.C
4575 w .Header ().Set ("WWW-Authenticate" , fmt .Sprintf (`Bearer resource_metadata=%q` , resourceMetadataURL ))
4676 http .Error (w , "Unauthorized" , http .StatusUnauthorized )
4777}
78+ << << << < HEAD
79+ == == == =
80+
81+ func parseAuthorizationHeader (req * http.Request ) (authType authType , token string , _ error ) {
82+ authHeader := req .Header .Get (httpheaders .AuthorizationHeader )
83+ if authHeader == "" {
84+ return 0 , "" , errMissingAuthorizationHeader
85+ }
86+
87+ switch {
88+ // decrypt dotcom token and set it as token
89+ case strings .HasPrefix (authHeader , "GitHub-Bearer " ):
90+ return 0 , "" , errUnsupportedAuthorizationHeader
91+ default :
92+ // support both "Bearer" and "bearer" to conform to api.github.com
93+ if len (authHeader ) > 7 && strings .EqualFold (authHeader [:7 ], "Bearer " ) {
94+ token = authHeader [7 :]
95+ } else {
96+ token = authHeader
97+ }
98+ }
99+
100+ // Do a naïve check for a colon in the token - currently, only the IDE token has a colon in it.
101+ // ex: tid=1;exp=25145314523;chat=1:<hmac>
102+ if strings .Contains (token , ":" ) {
103+ return authTypeIDE , token , nil
104+ }
105+
106+ for _ , prefix := range supportedGitHubPrefixes {
107+ if strings .HasPrefix (token , prefix ) {
108+ return authTypeGhToken , token , nil
109+ }
110+ }
111+
112+ matchesOldTokenPattern := oldPatternRegexp .MatchString (token )
113+ if matchesOldTokenPattern {
114+ return authTypeGhToken , token , nil
115+ }
116+
117+ return 0 , "" , errBadAuthorizationHeader
118+ }
119+ >> >> >> > http - stack - 2
0 commit comments