[FEATURE] Route metadata
deborggraever opened this issue · comments
Is there an existing feature request for this?
- I have searched the existing feature requests
Is your feature request related to a problem? Please describe.
Currently it is difficult to do authorization on routes based on claim requirements, unless we do the check inside the http handler.
Coming from a C# .NET world, there it is easy because it support attributes like an [Authorize] attribute.
As workaround i added a unique name to each route, and created a authorization mapping between the route name and the authorization policy.
Middleware
var routePolicies map[string]string
var authPolicies map[string]authorization.Policy
func authMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
route := mux.CurrentRoute(r)
policyName, ok := routePolicies[route.GetName()]
if !ok {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
policy, ok := authPolicies[policyName]
if !ok || !policy.MeetsRequirements(r.Context()) {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
next.ServeHTTP(w, r)
})
}
Setup
// Register the route
r.HandleFunc("/v1/product", api.GetProductsHandlerV1).Methods(http.MethodGet).Name("product_api:GetProductsHandlerV1")
r.HandleFunc("/v1/product/{id}", api.GetProductByIdHandlerV1).Methods(http.MethodGet).Name("product_api:GetProductByIdHandlerV1")
// Set the route policies
routePolicies["product_api:GetProductsHandlerV1"] = "product.read"
routePolicies["product_api:GetProductByIdHandlerV1"] = "product.read"
// Create the policies
authPolicies["product.read"] = authorization.NewPolicy(
"product.read",
NewUserRequirement(),
NewScopeRequirement("product.read"),
)
Describe the solution that you would like.
To make it easy to create an authorization middleware with limited code, it would be nice to have metadata on a route.
Example:
r.HandleFunc("/v1/product", api.GetProductsHandlerV1).Methods(http.MethodGet).Metadata("authPolicy", "product.read")
r.HandleFunc("/v1/product/{id}", api.GetProductByIdHandlerV1).Methods(http.MethodGet).Metadata("authPolicy", "product.read")
func authMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
route := mux.CurrentRoute(r)
policy, ok := authPolicies[route.GetMetadata()["authPolicy"]]
if !ok || !policy.MeetsRequirements(r.Context()) {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
next.ServeHTTP(w, r)
})
}
Route metadata could be used for many other solutions, where u want to set some properties on a route to use inside the handler or middlewares
Describe alternatives you have considered.
No response
Anything else?
No response