Documentation
¶
Overview ¶
Package ginmw provides Gin-compatible middleware for the api-security-sdk. It bridges the SDK's JWT, RBAC, and audit packages with the Gin web framework.
JWT authentication ¶
svc := jwt.New(jwt.WithHMAC(secret)) r.Use(ginmw.JWT(svc))
JWT with custom claims extraction and WebSocket fallback ¶
extractor := ginmw.WithClaimsExtractor(func(c *gin.Context, cl *jwt.Claims) {
c.Set("user_id", cl.Custom["user_id"])
c.Set("user_role", cl.Custom["role"])
c.Set("user_email", cl.Custom["email"])
})
r.Use(ginmw.JWT(svc, extractor, ginmw.WithWebSocketFallback()))
Verify-only (Auth0 / external IdP) ¶
src := jwks.Auth0("myapp.auth0.com")
svc := jwt.New(jwt.WithJWKS(src.KeyFunc))
r.Use(ginmw.JWT(svc))
RBAC middleware ¶
enforcer := rbac.New(store)
r.GET("/admin", ginmw.RequireRole(enforcer, "admin"), handler)
r.DELETE("/posts/:id", ginmw.RequirePermission(enforcer, "delete", "posts"), handler)
Custom claim guards ¶
r.GET("/admin", ginmw.RequireCustomClaim("user_role", "admin", "superadmin"), handler)
r.Use(ginmw.RequireCustomClaimNot("user_role", "pending"))
Async DB-backed permission check ¶
r.DELETE("/events/:id", ginmw.RequireAsyncPermission(
"user_id",
"user_role", "superadmin",
func(ctx context.Context, subject, resource, action string) bool {
return roleRepo.HasPermission(ctx, subject, resource, action)
},
"events", "delete",
), handler)
Scope checking (OAuth 2.0 / OIDC scopes) ¶
r.GET("/profile", ginmw.ScopeChecker("read:profile"), handler)
Index ¶
- func ClaimsFrom(c *gin.Context) *jwtpkg.Claims
- func JWT(svc *jwtpkg.Service, opts ...JWTOption) gin.HandlerFunc
- func RequireAsyncPermission(subjectKey string, bypassKey, bypassValue string, fn PermissionFunc, ...) gin.HandlerFunc
- func RequireCustomClaim(contextKey string, allowedValues ...string) gin.HandlerFunc
- func RequireCustomClaimNot(contextKey, blockedValue string) gin.HandlerFunc
- func RequirePermission(enforcer *rbac.Enforcer, action, resource string) gin.HandlerFunc
- func RequireRole(enforcer *rbac.Enforcer, roles ...string) gin.HandlerFunc
- func ScopeChecker(required ...string) gin.HandlerFunc
- func SubjectFrom(c *gin.Context) string
- type ClaimsExtractor
- type JWTOption
- type PermissionFunc
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ClaimsFrom ¶
ClaimsFrom retrieves the *jwt.Claims stored by the JWT middleware. Returns nil if JWT middleware has not run or the token was invalid.
func JWT ¶
func JWT(svc *jwtpkg.Service, opts ...JWTOption) gin.HandlerFunc
JWT returns a Gin middleware that:
- Extracts the Bearer token from the Authorization header.
- Falls back to the ?token= query parameter on WebSocket upgrades when WithWebSocketFallback is set.
- Validates the token via svc.Verify (supports JWKS, HMAC, RSA, ECDSA).
- Stores the *jwt.Claims in the Gin context under "ginmw:claims".
- Calls the ClaimsExtractor (if set) to populate additional context keys.
Requests without a valid token are rejected with 401. To make auth optional, apply this middleware only to protected route groups.
func RequireAsyncPermission ¶ added in v1.0.2
func RequireAsyncPermission( subjectKey string, bypassKey, bypassValue string, fn PermissionFunc, resource, action string, ) gin.HandlerFunc
RequireAsyncPermission returns a middleware that calls fn to check whether the request subject has permission to perform action on resource.
subjectKey is the Gin context key holding the subject string (e.g. "user_id").
bypassKey / bypassValue: when the context value at bypassKey equals bypassValue the permission check is skipped entirely (e.g. superadmin bypass). Pass empty strings to disable the bypass.
Must run after ginmw.JWT with a WithClaimsExtractor that populates subjectKey (and bypassKey, if used).
Example:
r.DELETE("/events/:id",
ginmw.RequireAsyncPermission(
"user_id",
"user_role", "superadmin",
func(ctx context.Context, subject, resource, action string) bool {
return roleRepo.HasPermission(ctx, subject, resource, action)
},
"events", "delete",
),
handler,
)
func RequireCustomClaim ¶ added in v1.0.2
func RequireCustomClaim(contextKey string, allowedValues ...string) gin.HandlerFunc
RequireCustomClaim returns a middleware that rejects requests (403) unless the Gin context value at contextKey matches one of the allowedValues.
The value at contextKey must be a string; a missing or non-string value is treated as denied.
Must run after ginmw.JWT with a WithClaimsExtractor that populates contextKey.
Example — require admin or superadmin role:
r.GET("/admin",
ginmw.JWT(svc, extractor),
ginmw.RequireCustomClaim("user_role", "admin", "superadmin"),
handler,
)
func RequireCustomClaimNot ¶ added in v1.0.2
func RequireCustomClaimNot(contextKey, blockedValue string) gin.HandlerFunc
RequireCustomClaimNot returns a middleware that rejects requests (403) when the Gin context value at contextKey equals blockedValue. Useful for blocking accounts in a particular state (e.g. "pending", "suspended").
If the key is absent from the context, the request is allowed through.
Must run after ginmw.JWT with a WithClaimsExtractor that populates contextKey.
Example — block pending accounts site-wide:
router.Use(ginmw.RequireCustomClaimNot("user_role", "pending"))
func RequirePermission ¶
func RequirePermission(enforcer *rbac.Enforcer, action, resource string) gin.HandlerFunc
RequirePermission returns a middleware that rejects requests (403) unless the authenticated subject has permission to perform action on resource.
Must be used after ginmw.JWT.
func RequireRole ¶
func RequireRole(enforcer *rbac.Enforcer, roles ...string) gin.HandlerFunc
RequireRole returns a middleware that rejects requests (403) unless the authenticated subject has at least one of the provided roles.
Must be used after ginmw.JWT (or another middleware that sets the subject).
func ScopeChecker ¶
func ScopeChecker(required ...string) gin.HandlerFunc
ScopeChecker returns a middleware that verifies the JWT contains all of the required OAuth 2.0 / OIDC scopes. It inspects two standard claim shapes:
- "scope" — a single space-delimited string (e.g. "read:users write:posts")
- "scopes" — a JSON array of strings (e.g. ["read:users","write:posts"])
Both conventions are widely used; Auth0 uses "scope" (string), some OIDC providers use "scopes" (array). ScopeChecker handles either.
Must be used after ginmw.JWT.
func SubjectFrom ¶
SubjectFrom retrieves the authenticated subject (sub claim) stored by the JWT middleware. Returns "" if JWT middleware has not run.
Types ¶
type ClaimsExtractor ¶ added in v1.0.2
ClaimsExtractor is called after successful token verification. Use it to unpack fields from claims.Custom into named Gin context values so that downstream handlers and middleware can access them with c.Get("key").
Example:
ginmw.WithClaimsExtractor(func(c *gin.Context, cl *jwt.Claims) {
c.Set("user_id", cl.Custom["user_id"])
c.Set("user_role", cl.Custom["role"])
c.Set("user_email", cl.Custom["email"])
})
type JWTOption ¶ added in v1.0.2
type JWTOption func(*jwtConfig)
JWTOption configures the JWT middleware.
func WithClaimsExtractor ¶ added in v1.0.2
func WithClaimsExtractor(fn ClaimsExtractor) JWTOption
WithClaimsExtractor registers a function that maps *jwt.Claims fields into named Gin context keys immediately after the token is verified.
func WithWebSocketFallback ¶ added in v1.0.2
func WithWebSocketFallback() JWTOption
WithWebSocketFallback enables token extraction from the ?token= query parameter when the Authorization header is absent on a WebSocket upgrade request (Connection: Upgrade + Upgrade: websocket). Browser WebSocket clients cannot set the Authorization header, so they pass the token as a query parameter instead.
type PermissionFunc ¶ added in v1.0.2
PermissionFunc is a caller-supplied async permission-check function. subject is the value stored in the Gin context under subjectKey (e.g. a user ID or role string). resource and action describe the operation being attempted.