예제 #1
0
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)
}
예제 #2
0
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)
}
예제 #3
0
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)
}
예제 #4
0
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,
	})
}
예제 #5
0
파일: handler.go 프로젝트: lmineiro/hydra
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)
}
예제 #6
0
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)
}
예제 #7
0
파일: handler.go 프로젝트: lmineiro/hydra
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})
}
예제 #8
0
파일: core.go 프로젝트: emmanuel/hydra
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
}
예제 #9
0
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())
}