Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/AndresGT/GoKit/llms.txt

Use this file to discover all available pages before exploring further.

The Auth middleware protects your Gin routes by validating JWT tokens on every incoming request. It extracts the token from the Authorization: Bearer header or a token cookie, validates it using GoKit’s JWT package, and injects the user’s ID, role, and full claims into the Gin context. Unauthorized requests are aborted with a structured JSON error before they ever reach your handlers.

Import

import "github.com/AndresGT/GoKit/middleware"

Overview

When a request arrives, the middleware runs through the following steps:
1

Skip check

If the request path matches any entry in SkipPaths, the middleware calls c.Next() immediately — no token required.
2

Token extraction

The configured TokenExtractor reads the token string from the request. By default it checks the Authorization: Bearer <token> header first, then falls back to the token cookie.
3

JWT validation

The token is validated via jwt.Validate(). An invalid or expired token is logged at Security level and results in a 401 response.
4

Claims validation

The middleware checks that the claims contain a non-nil UserID and a non-empty Role. Missing claims return a 403 response.
5

Context injection

On success, UserID, Role, and Claims are stored in the Gin context for downstream handlers to read.

Usage

router.Use(middleware.Auth(middleware.AuthConfig{}))
Passing an empty AuthConfig{} applies all defaults: DefaultTokenExtractor, the global logger, and no skip paths.

Configuration

SkipPaths
[]string
Paths that bypass authentication entirely. Supports exact matches and wildcard prefixes — any entry ending with * skips all paths that start with the prefix before the asterisk.
SkipPaths: []string{
    "/api/auth/login",
    "/api/auth/register",
    "/api/public/*",  // skips /api/public/anything
}
TokenExtractor
func(*gin.Context) string
A function that receives the Gin context and returns the raw JWT string. Defaults to DefaultTokenExtractor. Set this to HeaderOnlyExtractor or CookieOnlyExtractor for stricter extraction, or provide your own function for custom schemes.
ErrorHandler
func(c *gin.Context, err error)
Called when authentication fails. If nil, the default handler returns a JSON body with {"error": "unauthorized"} (401) or {"error": "invalid claims"} (403) and aborts the request.
Logger
*logger.Logger
The logger instance used for security and debug events. Falls back to the GoKit global logger when nil.

Built-in Token Extractors

GoKit ships three ready-to-use extractors:

DefaultTokenExtractor

Checks Authorization: Bearer <token> first, then falls back to the token cookie. Best for APIs that serve both browser and programmatic clients.

HeaderOnlyExtractor

Reads only from the Authorization header. Use this when cookies are never expected (e.g., pure REST APIs consumed by mobile apps).

CookieOnlyExtractor

Reads only from the token cookie. Useful for traditional web apps where tokens are set server-side and cookies are the sole transport.
// Use header-only extraction
router.Use(middleware.Auth(middleware.AuthConfig{
    TokenExtractor: middleware.HeaderOnlyExtractor,
}))

Error Types

The middleware uses three sentinel errors. Your custom ErrorHandler can use errors.Is to distinguish them:
var (
    ErrNoToken       = errors.New("auth: token not provided")       // → 401
    ErrInvalidToken  = errors.New("auth: invalid or expired token") // → 401
    ErrInvalidClaims = errors.New("auth: invalid claims")           // → 403
)
ErrorDefault StatusCause
ErrNoToken401No token found in header or cookie
ErrInvalidToken401Token signature invalid or expired
ErrInvalidClaims403UserID is nil or Role is empty

Accessing Token Data in Handlers

After the middleware runs, use these typed helpers to read values from the Gin context:
func ProfileHandler(c *gin.Context) {
    userID, ok := middleware.GetUserID(c)   // uuid.UUID
    role, ok   := middleware.GetUserRole(c) // string
    claims, ok := middleware.GetClaims(c)   // *jwt.Claims
    _ = ok

    c.JSON(200, gin.H{
        "user_id": userID,
        "role":    role,
        "expires": claims.ExpiresAt,
    })
}
GetUserID(c *gin.Context)
(uuid.UUID, bool)
Returns the authenticated user’s UUID and true, or a zero-value UUID and false if the middleware did not run or was skipped.
GetUserRole(c *gin.Context)
(string, bool)
Returns the user’s role string from the JWT claims.
GetClaims(c *gin.Context)
(*jwt.Claims, bool)
Returns the full *jwt.Claims struct, giving access to UserID, Role, Extra, ExpiresAt, and any other fields defined in GoKit’s JWT package.

Context Keys

GoKit stores auth data under typed contextKey string constants. The helper functions (GetUserID, GetUserRole, GetClaims) are the recommended way to read these values in production code because they perform a safe type assertion. In tests you may need to seed the context directly using the raw string values:
ConstantRaw string valueHolds
ctxUserIDKey"gokit:user_id"uuid.UUID
ctxRoleKey"gokit:user_role"string
ctxClaimsKey"gokit:claims"*jwt.Claims
// Seeding context in tests (using raw string keys)
c.Set("gokit:user_id", someUUID)
c.Set("gokit:user_role", "admin")
c.Set("gokit:claims", &jwt.Claims{UserID: someUUID, Role: "admin"})

// Reading back via helpers works as normal
userID, ok := middleware.GetUserID(c)
The constants ctxUserIDKey, ctxRoleKey, and ctxClaimsKey are unexported. Use the string literals shown above when seeding a *gin.Context in unit tests.

Role-Based Access Control

RequireRole is a secondary middleware that must be placed after Auth. It reads the role that Auth injected into the context and aborts with 403 if the role is not in the allowed list. Denied attempts are logged at SecurityLevel.
func RequireRole(roles ...string) gin.HandlerFunc
// Only admins
admin := router.Group("/admin")
admin.Use(middleware.Auth(middleware.AuthConfig{}))
admin.Use(middleware.RequireRole("admin"))

// Admins or moderators
mod := router.Group("/mod")
mod.Use(middleware.Auth(middleware.AuthConfig{}))
mod.Use(middleware.RequireRole("admin", "moderator"))
If GetUserRole returns false (Auth was not run or was skipped), RequireRole responds with 401 rather than 403. Always chain it after Auth.

Examples

router := gin.New()

router.Use(middleware.Auth(middleware.AuthConfig{}))

router.GET("/profile", ProfileHandler)
router.GET("/settings", SettingsHandler)

Build docs developers (and LLMs) love