func TestNewHttpRouterAdapter(t *testing.T) { called := 0 params := httprouter.Params{{"foo", "bar"}} NewHttpRouterAdapter( context.Background(), func(next handler.ContextHandler) handler.ContextHandler { return handler.ContextHandlerFunc(func(ctx context.Context, rw http.ResponseWriter, req *http.Request) { if called == 0 { called = 1 } next.ServeHTTPContext(ctx, rw, req) }) }, func(next handler.ContextHandler) handler.ContextHandler { return handler.ContextHandlerFunc(func(ctx context.Context, rw http.ResponseWriter, req *http.Request) { if called == 1 { called = 2 } next.ServeHTTPContext(ctx, rw, req) }) }, ).ThenFunc(func(ctx context.Context, r http.ResponseWriter, w *http.Request) { if called == 2 { called = 3 } vars, err := cc.FetchRouterParamsFromContext(ctx, "foo") assert.Nil(t, err) assert.Equal(t, "bar", vars["foo"]) })(nil, nil, params) assert.Equal(t, 3, called) }
func TestMiddleware(t *testing.T) { m := &Middleware{} for k, c := range cases { h := chd.NewContextAdapter( context.Background(), mockContext(c), m.IsAuthenticated, ).ThenFunc(chd.ContextHandlerFunc(handler(m, c))) ts := httptest.NewServer(h) defer ts.Close() res, err := http.Get(ts.URL) require.Nil(t, err) res.Body.Close() if !c.expectAuthN { assert.Equal(t, http.StatusUnauthorized, res.StatusCode, "Authentication failed case %d", k) } else if !c.expectAuthZ { assert.Equal(t, http.StatusForbidden, res.StatusCode, "Authorization failed case %d", k) } else { assert.Equal(t, http.StatusOK, res.StatusCode, "Case %d should be authorized but wasn't.", k) } } }
func (h *Handler) updateUsername(ctx context.Context, rw http.ResponseWriter, req *http.Request) { id, ok := mux.Vars(req)["id"] if !ok { HttpError(rw, errors.Errorf("No id given."), http.StatusBadRequest) return } h.m.IsAuthorized(permission(id), "put:data", middleware.NewEnv(req).Owner(id))(chd.ContextHandlerFunc( func(ctx context.Context, rw http.ResponseWriter, req *http.Request) { var p UpdateUsernameRequest if err := json.NewDecoder(req.Body).Decode(&p); err != nil { HttpError(rw, err, http.StatusBadRequest) return } user, err := h.s.UpdateUsername(id, p) if err != nil { WriteError(rw, err) return } WriteJSON(rw, user) }), ).ServeHTTPContext(ctx, rw, req) }
func (m *Middleware) IsAuthenticated(next chd.ContextHandler) chd.ContextHandler { return chd.ContextHandlerFunc(func(ctx context.Context, rw http.ResponseWriter, req *http.Request) { bearer := osin.CheckBearerAuth(req) if bearer == nil { log.WithFields(log.Fields{ "authentication": "invalid", "error": errors.New("No bearer token given"), "valid": false, }).Warn(`Authentication invalid.`) rw.WriteHeader(http.StatusUnauthorized) return } if authenticated, err := m.Client.IsAuthenticated(bearer.Code); err != nil { log.WithFields(log.Fields{ "authentication": "invalid", "error": err, "valid": authenticated, }).Warn(`Authentication invalid.`) rw.WriteHeader(http.StatusUnauthorized) return } else if !authenticated { log.WithFields(log.Fields{ "authentication": "invalid", "error": nil, "valid": authenticated, }).Warn(`Authentication invalid.`) rw.WriteHeader(http.StatusUnauthorized) return } log.WithFields(log.Fields{"authentication": "success"}).Info(`Authenticated.`) next.ServeHTTPContext(ctx, rw, req) }) }
func handler(m *Middleware, c test) func(context.Context, http.ResponseWriter, *http.Request) { return func(ctx context.Context, rw http.ResponseWriter, req *http.Request) { m.IsAuthorized(c.resource, c.permission, mwroot.NewEnv(req).Owner(c.owner))(chd.ContextHandlerFunc( func(ctx context.Context, rw http.ResponseWriter, req *http.Request) { fmt.Fprintln(rw, "ok") }, )).ServeHTTPContext(ctx, rw, req) } }
func mockAuthorization(c test) func(h chd.ContextHandler) chd.ContextHandler { return func(h chd.ContextHandler) chd.ContextHandler { return chd.ContextHandlerFunc(func(ctx context.Context, rw http.ResponseWriter, req *http.Request) { claims := hjwt.NewClaimsCarrier(uuid.New(), "hydra", c.subject, "tests", time.Now().Add(time.Hour), time.Now(), time.Now()) ctx = authcon.NewContextFromAuthValues(ctx, claims, &c.token, c.policies) h.ServeHTTPContext(ctx, rw, req) }) } }
func (m *Middleware) IsAuthorized(resource, permission string, environment *middleware.Env) func(chd.ContextHandler) chd.ContextHandler { return func(next chd.ContextHandler) chd.ContextHandler { return chd.ContextHandlerFunc(func(ctx context.Context, rw http.ResponseWriter, req *http.Request) { if environment == nil { environment = middleware.NewEnv(req) } policies, err := authcon.PoliciesFromContext(ctx) if err != nil { log.WithFields(log.Fields{ "authorization": "forbidden", "error": err, }).Warnf(`Policy extraction failed.`) pkg.HttpError(rw, errors.New("Forbidden"), http.StatusForbidden) return } subject, err := authcon.SubjectFromContext(ctx) if err != nil { log.WithFields(log.Fields{ "authorization": "forbidden", "error": err, }).Warnf(`Subject extraction failed.`) pkg.HttpError(rw, errors.New("Forbidden"), http.StatusForbidden) return } ok, err := guard.IsGranted(resource, permission, subject, policies, environment.Ctx()) if err != nil || !ok { log.WithFields(log.Fields{ "authorization": "forbidden", "error": err, "valid": ok, "subject": subject, "permission": permission, "resource": resource, }).Warnf(`Subject is not allowed perform this action on this resource.`) pkg.HttpError(rw, errors.New("Forbidden"), http.StatusForbidden) return } log.WithFields(log.Fields{ "authorization": "success", "subject": subject, "permission": permission, "resource": resource, }).Infof(`Access granted.`) next.ServeHTTPContext(ctx, rw, req) }) } }
func (h *Handler) Delete(ctx context.Context, rw http.ResponseWriter, req *http.Request) { id, ok := mux.Vars(req)["id"] if !ok { HttpError(rw, errors.New("No id given."), http.StatusBadRequest) return } h.m.IsAuthorized(permission(id), "delete", nil)(chd.ContextHandlerFunc( func(ctx context.Context, rw http.ResponseWriter, req *http.Request) { if err := h.s.RemoveClient(id); err != nil { HttpError(rw, errors.Errorf("Could not retrieve client: %s", id), http.StatusInternalServerError) return } rw.WriteHeader(http.StatusAccepted) }, )).ServeHTTPContext(ctx, rw, req) }
func (h *Handler) Get(ctx context.Context, rw http.ResponseWriter, req *http.Request) { id, ok := mux.Vars(req)["id"] if !ok { HttpError(rw, errors.New("No id given."), http.StatusBadRequest) return } h.m.IsAuthorized(permission(id), "get", nil)(chd.ContextHandlerFunc( func(ctx context.Context, rw http.ResponseWriter, req *http.Request) { client, err := h.s.GetClient(id) if err != nil { WriteError(rw, err) return } WriteJSON(rw, client) }, )).ServeHTTPContext(ctx, rw, req) }
func (h *Handler) delete(ctx context.Context, rw http.ResponseWriter, req *http.Request) { id, ok := mux.Vars(req)["id"] if !ok { HttpError(rw, errors.Errorf("No id given."), http.StatusBadRequest) return } h.m.IsAuthorized(permission(id), "delete", middleware.NewEnv(req).Owner(id))(chd.ContextHandlerFunc( func(ctx context.Context, rw http.ResponseWriter, req *http.Request) { if err := h.s.Delete(id); err != nil { HttpError(rw, err, http.StatusInternalServerError) return } rw.WriteHeader(http.StatusAccepted) }), ).ServeHTTPContext(ctx, rw, req) }
func (h *Handler) get(ctx context.Context, rw http.ResponseWriter, req *http.Request) { id, ok := mux.Vars(req)["id"] if !ok { HttpError(rw, errors.Errorf("No id given."), http.StatusBadRequest) return } h.m.IsAuthorized(permission(id), "get", middleware.NewEnv(req).Owner(id))(chd.ContextHandlerFunc( func(ctx context.Context, rw http.ResponseWriter, req *http.Request) { user, err := h.s.Get(id) if err != nil { WriteError(rw, err) return } WriteJSON(rw, user) }), ).ServeHTTPContext(ctx, rw, req) }
func TestHelpers(t *testing.T) { ctrl := gomock.NewController(t) mockMW := NewMockMiddleware(ctrl) defer ctrl.Finish() w := new(writer) last := handler.ContextHandlerFunc(func(_ context.Context, rw http.ResponseWriter, _ *http.Request) { rw.WriteHeader(http.StatusOK) require.NotNil(t, errors.New("Should have been called")) }) mockMW.EXPECT().IsAuthenticated(gomock.Any()).Return(MockFailAuthenticationHandler) mockMW.IsAuthenticated(last).ServeHTTPContext(nil, w, nil) require.Equal(t, http.StatusUnauthorized, w.status) mockMW.EXPECT().IsAuthenticated(gomock.Any()).Return(MockPassAuthenticationHandler(last)) mockMW.IsAuthenticated(last).ServeHTTPContext(nil, w, nil) require.Equal(t, http.StatusOK, w.status) }
func (m *Middleware) IsAuthorized(resource, permission string, environment *middleware.Env) func(chd.ContextHandler) chd.ContextHandler { return func(next chd.ContextHandler) chd.ContextHandler { return chd.ContextHandlerFunc(func(ctx context.Context, rw http.ResponseWriter, req *http.Request) { if environment == nil { environment = middleware.NewEnv(req) } bearer := osin.CheckBearerAuth(req) if allowed, err := m.Client.IsAllowed(&AuthorizeRequest{ Resource: resource, Permission: permission, Context: environment.Ctx(), Token: bearer.Code, }); err != nil { log.WithFields(log.Fields{ "authorization": "forbidden", "error": err, "valid": allowed, "permission": permission, "resource": resource, }).Warnf(`Subject is not allowed perform this action on this resource.`) rw.WriteHeader(http.StatusForbidden) return } else if !allowed { log.WithFields(log.Fields{ "authorization": "forbidden", "error": nil, "valid": allowed, "permission": permission, "resource": resource, }).Warnf(`Subject is not allowed perform this action on this resource.`) rw.WriteHeader(http.StatusForbidden) return } log.WithFields(log.Fields{"authorization": "success"}).Info(`Allowed!`) next.ServeHTTPContext(ctx, rw, req) }) } }
func (m *Middleware) IsAuthenticated(next chd.ContextHandler) chd.ContextHandler { return chd.ContextHandlerFunc(func(ctx context.Context, rw http.ResponseWriter, req *http.Request) { if !authcon.IsAuthenticatedFromContext(ctx) { log.WithFields(log.Fields{"authentication": "fail"}).Warn(`Not able to get authorization from context.`) pkg.HttpError(rw, errors.New("Unauthorized"), http.StatusUnauthorized) return } subject, err := authcon.SubjectFromContext(ctx) if err != nil { log.WithFields(log.Fields{"authentication": "fail"}).Warnf("Subject extraction failed: %s", err) pkg.HttpError(rw, errors.New("Unauthorized"), http.StatusUnauthorized) return } else if subject == "" { log.WithFields(log.Fields{"authentication": "fail"}).Warnf("No subject given.") pkg.HttpError(rw, errors.New("Unauthorized"), http.StatusUnauthorized) return } log.WithFields(log.Fields{"authentication": "success"}).Infof(`Authenticated subject "%s".`, subject) next.ServeHTTPContext(ctx, rw, req) }) }
func (h *Handler) Get(ctx context.Context, rw http.ResponseWriter, req *http.Request) { id, ok := mux.Vars(req)["id"] if !ok { HttpError(rw, errors.New("No id given."), http.StatusBadRequest) return } conn, err := h.s.Get(id) if err != nil { WriteError(rw, err) return } h.m.IsAuthorized(permission(id), "get", middleware.NewEnv(req).Owner(conn.GetLocalSubject()))(hydcon.ContextHandlerFunc( func(ctx context.Context, rw http.ResponseWriter, req *http.Request) { WriteJSON(rw, conn) }, )).ServeHTTPContext(ctx, rw, req) }
func (h *Handler) Find(ctx context.Context, rw http.ResponseWriter, req *http.Request) { subject, ok := mux.Vars(req)["subject"] if !ok { HttpError(rw, errors.New("No id given."), http.StatusBadRequest) return } h.m.IsAuthorized(connectionsPermission, "get", middleware.NewEnv(req).Owner(subject))(hydcon.ContextHandlerFunc( func(ctx context.Context, rw http.ResponseWriter, req *http.Request) { conns, err := h.s.FindAllByLocalSubject(subject) if err != nil { HttpError(rw, err, http.StatusNotFound) return } WriteJSON(rw, conns) }, )).ServeHTTPContext(ctx, rw, req) }
func (m *Middleware) ExtractAuthentication(next chd.ContextHandler) chd.ContextHandler { return chd.ContextHandlerFunc(func(ctx context.Context, rw http.ResponseWriter, req *http.Request) { ctx = authcon.NewContextFromAuthorization(ctx, req, m.jwtService, m.policyStore) next.ServeHTTPContext(ctx, rw, req) }) }
package mock import ( chd "github.com/ory-am/common/handler" "golang.org/x/net/context" "net/http" ) var MockFailAuthenticationHandler = chd.ContextHandlerFunc(func(ctx context.Context, rw http.ResponseWriter, req *http.Request) { rw.WriteHeader(http.StatusUnauthorized) }) var MockPassAuthenticationHandler = func(next chd.ContextHandler) chd.ContextHandlerFunc { return func(ctx context.Context, rw http.ResponseWriter, req *http.Request) { next.ServeHTTPContext(ctx, rw, req) } }
func (h *Handler) Delete(ctx context.Context, rw http.ResponseWriter, req *http.Request) { id, ok := mux.Vars(req)["id"] if !ok { http.Error(rw, "No id given.", http.StatusBadRequest) return } conn, err := h.s.Get(id) if err != nil { HttpError(rw, err, http.StatusNotFound) return } h.m.IsAuthorized(permission(id), "delete", middleware.NewEnv(req).Owner(conn.GetLocalSubject()))(hydcon.ContextHandlerFunc( func(ctx context.Context, rw http.ResponseWriter, req *http.Request) { if err := h.s.Delete(conn.GetID()); err != nil { HttpError(rw, err, http.StatusInternalServerError) return } rw.WriteHeader(http.StatusAccepted) }, )).ServeHTTPContext(ctx, rw, req) }