AuthN vs AuthZ — Identity vs Permission
AuthN = who are you? AuthZ = what can you do? Conflating them is a security design smell.
When to use
- Every system with users or service-to-service calls
- When designing access control that survives role changes without re-login
Tradeoffs
- RBAC (role-based) is simple but coarse; ABAC (attribute-based) is flexible but complex
- Checking permissions in business logic couples domain to security policy
- Go
- Python
func AuthNMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("Authorization")
claims, err := validateJWT(token)
if err != nil {
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
}
ctx := context.WithValue(r.Context(), claimsKey, claims)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
func RequirePermission(perm string, next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
claims := r.Context().Value(claimsKey).(*Claims)
if !claims.HasPermission(perm) {
http.Error(w, "forbidden", http.StatusForbidden)
return
}
next.ServeHTTP(w, r)
})
}
from functools import wraps
from flask import request, g, abort
def authn_middleware(f):
@wraps(f)
def wrapper(*args, **kwargs):
token = request.headers.get("Authorization", "")
claims = validate_jwt(token)
if not claims:
abort(401)
g.claims = claims
return f(*args, **kwargs)
return wrapper
def require_permission(perm: str):
def decorator(f):
@wraps(f)
def wrapper(*args, **kwargs):
if not g.claims.has_permission(perm):
abort(403)
return f(*args, **kwargs)
return wrapper
return decorator
Gotcha: Checking
if user.is_admin()in business logic is AuthZ leaking into your domain. Extract it to a policy/middleware layer.