func (h *Handler) IntrospectHandler(w http.ResponseWriter, r *http.Request) { auth, err := osin.CheckBasicAuth(r) if _, err := h.OAuthStore.GetClient(auth.Username); err != nil { pkg.HttpError(w, errors.New("Unauthorized"), http.StatusUnauthorized) return } else if auth == nil { pkg.HttpError(w, errors.New("Unauthorized"), http.StatusUnauthorized) return } client, err := h.OAuthStore.GetClient(auth.Username) if err != nil { pkg.HttpError(w, errors.New("Unauthorized"), http.StatusUnauthorized) return } else if client.GetSecret() != auth.Password { pkg.HttpError(w, errors.New("Unauthorized"), http.StatusUnauthorized) return } result := make(map[string]interface{}) result["active"] = false r.ParseForm() if r.Form.Get("token") == "" { log.WithField("introspect", "fail").Warn("No token given.") result["error"] = "No token given." pkg.WriteJSON(w, result) return } token, err := h.JWT.VerifyToken([]byte(r.Form.Get("token"))) if err != nil { log.WithField("introspect", "fail").Warn("Token is invalid.") pkg.WriteJSON(w, result) return } claims := jwt.ClaimsCarrier(token.Claims) if claims.GetAudience() != auth.Username { log.WithFields(log.Fields{ "introspect": "fail", "actualAudience": auth.Username, "expectedAudience": claims.GetAudience(), }).Warn(`Token audience mismatch.`) pkg.WriteJSON(w, result) return } if claims.GetSubject() == "" { log.WithFields(log.Fields{ "introspect": "fail", }).Warn(`Token claims no subject.`) pkg.WriteJSON(w, result) return } result = token.Claims result["active"] = token.Valid pkg.WriteJSON(w, result) }
func TestIsAuthenticated(t *testing.T) { router := mux.NewRouter() called := false router.HandleFunc("/oauth2/token", tokenHandler).Methods("POST") router.HandleFunc("/oauth2/introspect", func(rw http.ResponseWriter, req *http.Request) { if req.Header.Get("Authorization") != "Basic YXBwOmtleQ==" { http.Error(rw, req.Header.Get("Authorization"), http.StatusUnauthorized) return } req.ParseForm() assert.NotEmpty(t, req.Form.Get("token")) pkg.WriteJSON(rw, struct { Active bool `json:"active"` }{Active: true}) called = true }).Methods("POST") ts := httptest.NewServer(router) defer ts.Close() c := New(ts.URL, "app", "key") active, err := c.IsAuthenticated("some.token") assert.Nil(t, err, "%s", err) assert.True(t, active) assert.True(t, called) }
func TestIsAllowed(t *testing.T) { router := mux.NewRouter() router.HandleFunc("/oauth2/token", tokenHandler).Methods("POST") router.HandleFunc("/guard/allowed", func(rw http.ResponseWriter, req *http.Request) { if req.Header.Get("Authorization") != "Basic YXBwOmtleQ==" { http.Error(rw, req.Header.Get("Authorization"), http.StatusUnauthorized) return } var p handler.GrantedPayload decoder := json.NewDecoder(req.Body) if err := decoder.Decode(&p); err != nil { t.Logf("Could not decode body %s", err) pkg.HttpError(rw, errors.New(err), http.StatusBadRequest) return } assert.Equal(t, "foo", p.Permission) assert.Equal(t, "bar", p.Token) assert.Equal(t, "res", p.Resource) assert.Equal(t, "foo", p.Context.Owner) pkg.WriteJSON(rw, struct { Allowed bool `json:"allowed"` }{Allowed: true}) }).Methods("POST") ts := httptest.NewServer(router) defer ts.Close() c := New(ts.URL, "app", "key") allowed, err := c.IsAllowed(&AuthorizeRequest{Permission: "foo", Token: "bar", Resource: "res", Context: &operator.Context{Owner: "foo"}}) assert.Nil(t, err, "%s", err) assert.True(t, allowed) }
func tokenHandler(rw http.ResponseWriter, req *http.Request) { pkg.WriteJSON(rw, struct { AccessToken string `json:"access_token"` TokenType string `json:"token_type"` RefreshToken string `json:"refresh_token"` ExpiresIn int `json:"expires_in"` }{ AccessToken: "fetch-token-ok", TokenType: "Bearer", ExpiresIn: 9600, }) }
func (h *Handler) Get(ctx context.Context, rw http.ResponseWriter, req *http.Request) { id, ok := mux.Vars(req)["id"] if !ok { pkg.HttpError(rw, errors.New("No id given."), http.StatusBadRequest) return } h.m.IsAuthorized(permission(id), "get", nil)(hctx.ContextHandlerFunc( func(ctx context.Context, rw http.ResponseWriter, req *http.Request) { policy, err := h.s.Get(id) if err != nil { pkg.WriteError(rw, err) return } pkg.WriteJSON(rw, policy) }, )).ServeHTTPContext(ctx, rw, req) }
func TestIsRequestAllowed(t *testing.T) { router := mux.NewRouter() router.HandleFunc("/guard/allowed", func(rw http.ResponseWriter, req *http.Request) { if req.Header.Get("Authorization") != "Basic YXBwOmtleQ==" { http.Error(rw, req.Header.Get("Authorization"), http.StatusUnauthorized) return } pkg.WriteJSON(rw, struct { Allowed bool `json:"allowed"` }{Allowed: true}) }).Methods("POST") router.HandleFunc("/oauth2/token", tokenHandler).Methods("POST") ts := httptest.NewServer(router) defer ts.Close() c := New(ts.URL, "app", "key") c.SetClientToken(&oauth2.Token{TokenType: "bearer", AccessToken: "foobar"}) allowed, err := c.IsRequestAllowed(&http.Request{Header: http.Header{"Authorization": []string{"Bearer token"}}}, "", "", "") assert.Nil(t, err) assert.True(t, allowed) }
func (h *Handler) Granted(ctx context.Context, rw http.ResponseWriter, req *http.Request) { auth, err := osin.CheckBasicAuth(req) if err != nil { pkg.HttpError(rw, errors.New("Unauthorized"), http.StatusUnauthorized) return } else if auth == nil { pkg.HttpError(rw, errors.New("Unauthorized"), http.StatusUnauthorized) return } client, err := h.o.GetClient(auth.Username) if err != nil { pkg.HttpError(rw, errors.New("Unauthorized"), http.StatusUnauthorized) return } else if client.GetSecret() != auth.Password { pkg.HttpError(rw, errors.New("Unauthorized"), http.StatusUnauthorized) return } var p GrantedPayload decoder := json.NewDecoder(req.Body) if err := decoder.Decode(&p); err != nil { pkg.HttpError(rw, errors.New(err), http.StatusBadRequest) return } token, err := h.j.VerifyToken([]byte(p.Token)) if err != nil { log.WithFields(log.Fields{ "error": err.Error(), "resource": p.Resource, "permission": p.Permission, "subject": "", "context": fmt.Sprintf("%s", p.Context), }).Warn("Token not valid.") pkg.WriteJSON(rw, struct { Allowed bool `json:"allowed"` Error string `json:"error"` }{Allowed: false, Error: err.Error()}) return } subject, ok := token.Claims["sub"].(string) if !ok { err := errors.New("Bearer token is not valid.") log.WithFields(log.Fields{ "error": err.Error(), "resource": p.Resource, "permission": p.Permission, "subject": "", "context": fmt.Sprintf("%s", p.Context), }).Warn("Token does not claim a subject.") pkg.WriteJSON(rw, struct { Allowed bool `json:"allowed"` Error string `json:"error"` }{Allowed: false, Error: err.Error()}) return } policies, err := h.s.FindPoliciesForSubject(subject) if err != nil { log.WithFields(log.Fields{ "error": err.Error(), "resource": p.Resource, "permission": p.Permission, "subject": subject, "context": fmt.Sprintf("%s", p.Context), }).Warn("Could not fetch policies from store.") pkg.WriteJSON(rw, struct { Allowed bool `json:"allowed"` Error string `json:"error"` }{Allowed: false, Error: err.Error()}) return } allowed, err := h.g.IsGranted(p.Resource, p.Permission, subject, policies, p.Context) if err != nil { log.WithFields(log.Fields{ "error": err.Error(), "resource": p.Resource, "permission": p.Permission, "subject": subject, "policies": fmt.Sprintf("%s", policies), "context": fmt.Sprintf("%s", p.Context), }).Warn("Granted check failed.") pkg.WriteJSON(rw, struct { Allowed bool `json:"allowed"` Error string `json:"error"` }{Allowed: false, Error: err.Error()}) return } log.WithFields(log.Fields{ "resource": p.Resource, "permission": p.Permission, "subject": subject, "allowed": allowed, "policies": fmt.Sprintf("%s", policies), "context": fmt.Sprintf("%s", p.Context), }).Info("Got guard decision.") pkg.WriteJSON(rw, struct { Allowed bool `json:"allowed"` }{Allowed: allowed}) }
func (c *Core) Start(ctx *cli.Context) error { c.Ctx.Start() private, err := jwt.LoadCertificate(jwtPrivateKeyPath) if err != nil { return fmt.Errorf("Could not load private key: %s", err) } public, err := jwt.LoadCertificate(jwtPublicKeyPath) if err != nil { return fmt.Errorf("Could not load public key: %s", err) } j := jwt.New(private, public) m := middleware.New(c.Ctx.Policies, j) c.guard = new(guard.Guard) c.accountHandler = accounts.NewHandler(c.Ctx.Accounts, m) c.clientHandler = clients.NewHandler(c.Ctx.Osins, m) c.connectionHandler = connections.NewHandler(c.Ctx.Connections, m) c.providers = provider.NewRegistry(providers) c.policyHandler = policies.NewHandler(c.Ctx.Policies, m, c.guard, j, c.Ctx.Osins) c.oauthHandler = &oauth.Handler{ Accounts: c.Ctx.Accounts, Policies: c.Ctx.Policies, Guard: c.guard, Connections: c.Ctx.Connections, Providers: c.providers, Issuer: c.issuer, Audience: c.audience, JWT: j, OAuthConfig: oauth.DefaultConfig(), OAuthStore: c.Ctx.Osins, States: c.Ctx.States, SignUpLocation: locations["signUp"], SignInLocation: locations["signIn"], Middleware: host.New(c.Ctx.Policies, j), } extractor := m.ExtractAuthentication router := mux.NewRouter() c.accountHandler.SetRoutes(router, extractor) c.connectionHandler.SetRoutes(router, extractor) c.clientHandler.SetRoutes(router, extractor) c.oauthHandler.SetRoutes(router, extractor) c.policyHandler.SetRoutes(router, extractor) // TODO un-hack this, add database check, add error response router.HandleFunc("/alive", func(w http.ResponseWriter, r *http.Request) { pkg.WriteJSON(w, &struct { Status string `json:"status"` }{ Status: "alive", }) }) if forceHTTP == "force" { http.Handle("/", router) log.Warn("You're using HTTP without TLS encryption. This is dangerously unsafe and you should not do this.") if err := http.ListenAndServe(listenOn, nil); err != nil { return fmt.Errorf("Could not serve HTTP server because %s", err) } return nil } http.Handle("/", router) srv := &http.Server{Addr: listenOn} http2.ConfigureServer(srv, &http2.Server{}) if err := srv.ListenAndServeTLS(tlsCertPath, tlsKeyPath); err != nil { return fmt.Errorf("Could not serve HTTP/2 server because %s", err) } return nil }
func (c *Fosite) WriteAccessResponse(rw http.ResponseWriter, requester AccessRequester, responder AccessResponder) { rw.Header().Set("Content-Type", "application/json;charset=UTF-8") rw.Header().Set("Cache-Control", "no-store") rw.Header().Set("Pragma", "no-cache") pkg.WriteJSON(rw, responder.ToMap()) }