diff options
| author | mo khan <mo@mokhan.ca> | 2022-05-17 22:37:57 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2022-05-17 22:37:57 -0600 |
| commit | 8a38385ec7d1ad38fd7c21c5c68065eba999d1b3 (patch) | |
| tree | c967352c752ef8242c9ec1bada6205997b387583 | |
| parent | 06d5a14da989ce326a7c1e1d39457bc2be0fa882 (diff) | |
allow public access to wildcard routes
| -rw-r--r-- | cmd/api/main.go | 82 | ||||
| -rw-r--r-- | pkg/api/model.conf | 11 | ||||
| -rw-r--r-- | pkg/api/policy.conf | 11 | ||||
| -rw-r--r-- | pkg/api/policy.csv | 5 |
4 files changed, 38 insertions, 71 deletions
diff --git a/cmd/api/main.go b/cmd/api/main.go index 1ca5e28..0359dc9 100644 --- a/cmd/api/main.go +++ b/cmd/api/main.go @@ -31,34 +31,38 @@ func ValidAudience(audiences []string) bool { return false } +func Enforce(e *casbin.Enforcer, subject, resource, action string) bool { + ok := x.Must(e.Enforce(subject, resource, action)) + fmt.Printf("%v: %v %v %v\n", ok, subject, resource, action) + return ok +} + func Authorizer(e *casbin.Enforcer, keySet jwk.Set) func(next http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var subject string raw := jwtauth.TokenFromHeader(r) if raw == "" { - w.WriteHeader(http.StatusUnauthorized) - w.Write([]byte(fmt.Sprintf(`{"message":"%v"}`, "missing token"))) - return - } - - token, err := jwt.ParseString(raw, jwt.WithKeySet(keySet)) - if err != nil { - w.WriteHeader(http.StatusUnauthorized) - w.Write([]byte(fmt.Sprintf(`{"message":"%v"}`, err))) - return - } - - if !ValidAudience(token.Audience()) { - w.WriteHeader(http.StatusUnauthorized) - w.Write([]byte(fmt.Sprintf(`{"message":"%v"}`, "invalid audience"))) - return + subject = "" + } else { + token, err := jwt.ParseString(raw, jwt.WithKeySet(keySet)) + if err != nil { + w.WriteHeader(http.StatusUnauthorized) + w.Write([]byte(fmt.Sprintf(`{"message":"%v"}`, err))) + return + } + + if !ValidAudience(token.Audience()) { + w.WriteHeader(http.StatusUnauthorized) + w.Write([]byte(fmt.Sprintf(`{"message":"%v"}`, "invalid audience"))) + return + } + subject = token.Subject() } - if ok, _ := e.Enforce(token.Subject(), r.URL.Path, r.Method); ok { - fmt.Printf("pass: %v %v %v\n", token.Subject(), r.URL.Path, r.Method) + if Enforce(e, subject, r.URL.Path, r.Method) { next.ServeHTTP(w, r) } else { - fmt.Printf("fail: %v %v %v\n", token.Subject(), r.URL.Path, r.Method) w.WriteHeader(http.StatusUnauthorized) w.Write([]byte(fmt.Sprintf(`{"message":"%v"}`, http.StatusText(http.StatusUnauthorized)))) } @@ -66,44 +70,6 @@ func Authorizer(e *casbin.Enforcer, keySet jwk.Set) func(next http.Handler) http } } -// func BuildJwtMiddleware(issuerURL *url.URL) *jwtmiddleware.JWTMiddleware { -// provider := jwks.NewCachingProvider(issuerURL, 5*time.Minute) -// jwtValidator := x.Must( -// validator.New( -// provider.KeyFunc, -// validator.RS256, -// issuerURL.String(), -// []string{os.Getenv("AUTH0_AUDIENCE")}, -// validator.WithAllowedClockSkew(time.Minute), -// validator.WithCustomClaims(func() validator.CustomClaims { -// return &x.CustomClaims{} -// }), -// ), -// ) - -// errHandler := func(w http.ResponseWriter, r *http.Request, err error) { -// w.Header().Set("Content-Type", "application/json") -// w.WriteHeader(http.StatusUnauthorized) -// w.Write([]byte(fmt.Sprintf(`{"message":"%v"}`, err))) -// } -// return jwtmiddleware.New( -// jwtValidator.ValidateToken, -// jwtmiddleware.WithCredentialsOptional(true), -// jwtmiddleware.WithErrorHandler(errHandler), -// jwtmiddleware.WithValidateOnOptions(false), -// ) -// } - -// func Authorize(middleware *jwtmiddleware.JWTMiddleware, requiredPermissions ...x.Permission) func(http.Handler) http.Handler { -// return func(next http.Handler) http.Handler { -// return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -// middleware. -// CheckJWT(next). -// ServeHTTP(w, r.WithContext(context.WithValue(r.Context(), "required_permissions", requiredPermissions))) -// }) -// } -// } - func readFixture(path string) []byte { finalPath := filepath.Join(x.Must(os.Getwd()), "pkg/api/fixtures", path) return x.Must(ioutil.ReadFile(finalPath)) @@ -128,7 +94,7 @@ func main() { router.Use(middleware.AllowContentType("application/json")) router.Use(middleware.Heartbeat("/health")) router.Use(cors.AllowAll().Handler) - router.Use(Authorizer(x.Must(casbin.NewEnforcer("pkg/api/model.conf", "pkg/api/policy.csv")), keySet)) + router.Use(Authorizer(x.Must(casbin.NewEnforcer("pkg/api/policy.conf", "pkg/api/policy.csv")), keySet)) // issuer := x.Must(url.Parse("https://" + os.Getenv("AUTH0_DOMAIN") + "/")) // token := BuildJwtMiddleware(issuer) diff --git a/pkg/api/model.conf b/pkg/api/model.conf deleted file mode 100644 index cee2566..0000000 --- a/pkg/api/model.conf +++ /dev/null @@ -1,11 +0,0 @@ -[request_definition] -r = sub, obj, act - -[policy_definition] -p = sub, obj, act - -[policy_effect] -e = some(where (p.eft == allow)) - -[matchers] -m = r.sub == p.sub && r.obj == p.obj && r.act == p.act diff --git a/pkg/api/policy.conf b/pkg/api/policy.conf new file mode 100644 index 0000000..ee06c27 --- /dev/null +++ b/pkg/api/policy.conf @@ -0,0 +1,11 @@ +[request_definition] +r = subject, resource, action + +[policy_definition] +p = subject, resource, action + +[policy_effect] +e = some(where (p.eft == allow)) + +[matchers] +m = (p.subject == "*" || r.subject == p.subject) && r.resource == p.resource && r.action == p.action diff --git a/pkg/api/policy.csv b/pkg/api/policy.csv index 888c8cb..fa2451a 100644 --- a/pkg/api/policy.csv +++ b/pkg/api/policy.csv @@ -1,3 +1,4 @@ -p, alice, data1, read -p, bob, data2, write +p, *, /api/public, GET +p, auth0|alice, /api/atlas/QwfsJDutXwPD, read p, auth0|627b10e1019dd10068e03db4, /api/users, GET +p, auth0|bob, /api/atlas/QwfsJDutXwPD/investigations/FJ9mVozy2TjT, POST |
