Пример #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 (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)
		})
	}
}
Пример #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 (h *Handler) Create(ctx context.Context, rw http.ResponseWriter, req *http.Request) {
	var p DefaultPolicy
	decoder := json.NewDecoder(req.Body)
	if err := decoder.Decode(&p); err != nil {
		pkg.HttpError(rw, err, http.StatusBadRequest)
		return
	}

	p.ID = uuid.New()
	if err := h.s.Create(&p); err != nil {
		pkg.HttpError(rw, err, http.StatusInternalServerError)
		return
	}

	pkg.WriteCreatedJSON(rw, "/policies/"+p.ID, p)
}
Пример #5
0
func (h *Handler) Delete(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), "delete", nil)(hctx.ContextHandlerFunc(
		func(ctx context.Context, rw http.ResponseWriter, req *http.Request) {
			if err := h.s.Delete(id); err != nil {
				pkg.HttpError(rw, errors.Errorf("Could not retrieve client: %s", id), http.StatusInternalServerError)
				return
			}
			rw.WriteHeader(http.StatusAccepted)
		},
	)).ServeHTTPContext(ctx, rw, req)
}
Пример #6
0
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)
	})
}
Пример #7
0
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)
}
Пример #8
0
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})
}
Пример #9
0
func (h *Handler) RevokeHandler(w http.ResponseWriter, r *http.Request) {
	auth, err := osin.CheckBasicAuth(r)
	if 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
	}

	r.ParseForm()
	tokenToRevoke := r.Form.Get("token")
	if tokenToRevoke == "" {
		log.WithField("revokation", "fail").Warn("No token given.")
		pkg.HttpError(w, errors.New("No token given"), http.StatusServiceUnavailable)
		return
	}

	getClaims := func(ud interface{}) (jwt.ClaimsCarrier, error) {
		data, ok := ud.(string)
		var claims jwt.ClaimsCarrier
		if !ok {
			return nil, errors.New("Could not assert UserData to string")
		}
		if err := json.Unmarshal([]byte(data), &claims); err != nil {
			return nil, errors.New("Could not unmarshal UserData")
		}
		return claims, nil
	}

	var ud interface{}
	var revokeToken *osin.AccessData
	if revokeToken, err = h.OAuthStore.LoadAccess(tokenToRevoke); err == pkg.ErrNotFound {
		revokeToken, err = h.OAuthStore.LoadRefresh(tokenToRevoke)
		if err != nil {
			log.WithField("revokation", "fail").WithField("error", err).Warn("Could not fetch refresh token.")
			pkg.HttpError(w, errors.New("Could not find token"), http.StatusServiceUnavailable)
			return
		}
	} else if err != nil {
		log.WithField("revokation", "fail").WithField("error", err).Warn("Could not fetch acccess token.")
		pkg.HttpError(w, errors.New("Could not find token"), http.StatusServiceUnavailable)
		return
	}

	ud = revokeToken.UserData
	claims, err := getClaims(ud)
	if err != nil {
		log.WithField("error", err).Warn("Could not retrieve claims.")
		pkg.HttpError(w, err, http.StatusServiceUnavailable)
		return
	}

	if claims.GetAudience() != client.GetId() {
		log.WithFields(log.Fields{
			"claimAudience":  claims.GetAudience(),
			"clientAudience": client.GetId(),
		}).Warn("Suspicious activity detected. Audience mismatch.")
		pkg.HttpError(w, errors.New("Forbidden"), http.StatusServiceUnavailable)
		return
	}

	if err := h.OAuthStore.RemoveAccess(revokeToken.AccessToken); err != nil {
		log.WithField("error", err).Warn("Could not revoke access token.")
		pkg.HttpError(w, err, http.StatusServiceUnavailable)
		return
	}

	w.WriteHeader(http.StatusOK)
}