@@ -2,14 +2,21 @@ package api
2
2
3
3
import (
4
4
"context"
5
+ "errors"
5
6
"net/http"
6
7
8
+ "github.com/netlify/git-gateway/conf"
7
9
"github.com/sirupsen/logrus"
8
10
"github.com/okta/okta-jwt-verifier-golang"
9
11
)
10
12
11
- // requireAuthentication checks incoming requests for tokens presented using the Authorization header
12
- func (a * API ) requireAuthentication (w http.ResponseWriter , r * http.Request ) (context.Context , error ) {
13
+ type Auth struct {
14
+ config * conf.GlobalConfiguration
15
+ version string
16
+ }
17
+
18
+ // authenicate checks incoming requests for tokens presented using the Authorization header
19
+ func (a * Auth ) authenticate (w http.ResponseWriter , r * http.Request ) (context.Context , error ) {
13
20
logrus .Info ("Getting auth token" )
14
21
token , err := a .extractBearerToken (w , r )
15
22
if err != nil {
@@ -20,7 +27,48 @@ func (a *API) requireAuthentication(w http.ResponseWriter, r *http.Request) (con
20
27
return a .parseJWTClaims (token , r )
21
28
}
22
29
23
- func (a * API ) extractBearerToken (w http.ResponseWriter , r * http.Request ) (string , error ) {
30
+ // authorize checks incoming requests for roles data in tokens that is parsed and verified by prior authentication step
31
+ func (a * Auth ) authorize (w http.ResponseWriter , r * http.Request ) (context.Context , error ) {
32
+ ctx := r .Context ()
33
+ claims := getClaims (ctx )
34
+ config := getConfig (ctx )
35
+
36
+ logrus .Infof ("authenticate context: %v+" , ctx )
37
+ if claims == nil {
38
+ return nil , errors .New ("Access to endpoint not allowed: no claims found in Bearer token" )
39
+ }
40
+
41
+ if ! allowedRegexp .MatchString (r .URL .Path ) {
42
+ return nil , errors .New ("Access to endpoint not allowed: this part of GitHub's API has been restricted" )
43
+ }
44
+
45
+ if len (config .Roles ) == 0 {
46
+ return ctx , nil
47
+ }
48
+
49
+ roles , ok := claims .AppMetaData ["roles" ]
50
+ if ok {
51
+ roleStrings , _ := roles .([]interface {})
52
+ for _ , data := range roleStrings {
53
+ role , _ := data .(string )
54
+ for _ , adminRole := range config .Roles {
55
+ if role == adminRole {
56
+ return ctx , nil
57
+ }
58
+ }
59
+ }
60
+ }
61
+
62
+ return nil , errors .New ("Access to endpoint not allowed: your role doesn't allow access" )
63
+ }
64
+
65
+ func NewAuthWithVersion (ctx context.Context , globalConfig * conf.GlobalConfiguration , version string ) * Auth {
66
+ auth := & Auth {config : globalConfig , version : version }
67
+
68
+ return auth
69
+ }
70
+
71
+ func (a * Auth ) extractBearerToken (w http.ResponseWriter , r * http.Request ) (string , error ) {
24
72
authHeader := r .Header .Get ("Authorization" )
25
73
if authHeader == "" {
26
74
return "" , unauthorizedError ("This endpoint requires a Bearer token" )
@@ -34,7 +82,7 @@ func (a *API) extractBearerToken(w http.ResponseWriter, r *http.Request) (string
34
82
return matches [1 ], nil
35
83
}
36
84
37
- func (a * API ) parseJWTClaims (bearer string , r * http.Request ) (context.Context , error ) {
85
+ func (a * Auth ) parseJWTClaims (bearer string , r * http.Request ) (context.Context , error ) {
38
86
// Reimplemented to use Okta lib
39
87
// Original validation only work for HS256 algo,
40
88
// Okta supports RS256 only which requires public key downloading and caching (key rotation)
0 commit comments