Files
auth/authmw/authz.go
T

39 lines
1.3 KiB
Go
Raw Normal View History

package authmw
import (
"net/http"
"code.nochebuena.dev/einherjar/contracts/logging"
"code.nochebuena.dev/einherjar/contracts/security"
"code.nochebuena.dev/einherjar/core/xerrors"
"code.nochebuena.dev/einherjar/web/httputil"
)
// AuthzMiddleware gates the request against a single required permission on a named resource.
// Returns 401 if no identity is in context; 403 if the permission check fails or the
// provider returns an error (fail-closed: provider failure denies access).
func AuthzMiddleware(logger logging.Logger, provider security.PermissionProvider, resource string, required security.Permission) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
identity, ok := security.FromContext(r.Context())
if !ok {
httputil.Error(logger, w, r, xerrors.Unauthorized("missing identity"))
return
}
mask, err := provider.ResolveMask(r.Context(), identity.UID, resource)
if err != nil {
httputil.Error(logger, w, r, xerrors.PermissionDenied("permission check failed").WithError(err))
return
}
if !mask.Has(required) {
httputil.Error(logger, w, r, xerrors.PermissionDenied("insufficient permissions"))
return
}
next.ServeHTTP(w, r)
})
}
}