feat: rbac_check (pure), jwt_middleware, rbac_middleware
Fase 5 del issue 0010 — RBAC y middlewares de auth.
- rbac_check es pura: solo recorre la matriz roles/permisos
- jwt_middleware extrae token del header Authorization: Bearer, valida e
inyecta claims en el context con una key privada (jwtCtxKey struct{})
- rbac_middleware requiere jwt_middleware antes; lee role de claims.Custom
- Helper JWTClaimsFromContext para acceder a las claims desde handlers
- 401 claro si RBAC se usa sin JWT antes (code: no_claims)
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
package infra
|
||||
|
||||
import "net/http"
|
||||
|
||||
// RBACMiddleware retorna un Middleware que verifica que el usuario autenticado
|
||||
// tenga un permiso concreto. Requiere que JWTMiddleware se ejecute antes en la
|
||||
// chain (lee las claims del context). El rol se extrae de claims.Custom["role"].
|
||||
// Responde 403 si el rol no tiene el permiso; 401 si no hay claims en el context.
|
||||
func RBACMiddleware(roles []Role, required Permission) Middleware {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
claims, ok := JWTClaimsFromContext(r.Context())
|
||||
if !ok {
|
||||
HTTPErrorResponse(w, HTTPError{
|
||||
Status: http.StatusUnauthorized, Code: "no_claims",
|
||||
Message: "rbac_middleware requiere jwt_middleware antes en la chain",
|
||||
})
|
||||
return
|
||||
}
|
||||
roleName, _ := claims.Custom["role"].(string)
|
||||
if roleName == "" || !RBACCheck(roles, roleName, required) {
|
||||
HTTPErrorResponse(w, HTTPError{
|
||||
Status: http.StatusForbidden, Code: "forbidden",
|
||||
Message: "no tienes permiso para esta accion",
|
||||
})
|
||||
return
|
||||
}
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user