Skip to main content

Overview

The bearerauth middleware validates Bearer tokens from the Authorization header. It’s commonly used for API authentication with JWTs, OAuth tokens, or custom tokens. Use it when you need:
  • API authentication with tokens
  • JWT validation
  • OAuth 2.0 Bearer token protection
  • Custom token authentication

Installation

import "github.com/go-mizu/mizu/middlewares/bearerauth"

Quick Start

app := mizu.New()

// Simple token validation
app.Use(bearerauth.New(func(token string) bool {
    return token == "my-secret-token"
}))

Configuration

Options

OptionTypeDefaultDescription
ValidatorTokenValidator-Validates the token
ValidatorWithContextTokenValidatorWithContext-Validates and returns claims
Headerstring"Authorization"Header to read token from
AuthSchemestring"Bearer"Expected auth scheme prefix
ErrorHandlerfunc(*mizu.Ctx, error) error-Custom error handler

Validator Types

// Simple validator
type TokenValidator func(token string) bool

// Validator that returns claims
type TokenValidatorWithContext func(token string) (claims any, valid bool)

Examples

Simple Token Validation

validTokens := map[string]bool{
    "token-1": true,
    "token-2": true,
}

app.Use(bearerauth.New(func(token string) bool {
    return validTokens[token]
}))

JWT Validation with Claims

type UserClaims struct {
    UserID   string
    Username string
    Role     string
}

app.Use(bearerauth.WithOptions(bearerauth.Options{
    ValidatorWithContext: func(token string) (any, bool) {
        // Parse and validate JWT
        claims, err := parseJWT(token)
        if err != nil {
            return nil, false
        }
        return &UserClaims{
            UserID:   claims["sub"].(string),
            Username: claims["username"].(string),
            Role:     claims["role"].(string),
        }, true
    },
}))

// Access claims in handler
func protectedHandler(c *mizu.Ctx) error {
    claims, ok := bearerauth.Claims[*UserClaims](c)
    if !ok {
        return c.Text(401, "Unauthorized")
    }
    return c.JSON(200, map[string]string{
        "user": claims.Username,
        "role": claims.Role,
    })
}

Custom Header

// Use X-API-Token instead of Authorization
app.Use(bearerauth.WithHeader("X-API-Token", func(token string) bool {
    return validateToken(token)
}))

Custom Auth Scheme

// Use "Token" instead of "Bearer"
app.Use(bearerauth.WithOptions(bearerauth.Options{
    AuthScheme: "Token",
    Validator: func(token string) bool {
        return validateToken(token)
    },
}))

Custom Error Handler

app.Use(bearerauth.WithOptions(bearerauth.Options{
    Validator: validateToken,
    ErrorHandler: func(c *mizu.Ctx, err error) error {
        switch err {
        case bearerauth.ErrTokenMissing:
            return c.JSON(401, map[string]string{
                "error": "Authentication required",
            })
        case bearerauth.ErrTokenInvalid:
            return c.JSON(403, map[string]string{
                "error": "Invalid token",
            })
        default:
            return c.JSON(401, map[string]string{
                "error": err.Error(),
            })
        }
    },
}))

Database Token Lookup

app.Use(bearerauth.WithOptions(bearerauth.Options{
    ValidatorWithContext: func(token string) (any, bool) {
        // Look up token in database
        session, err := db.GetSession(token)
        if err != nil || session.IsExpired() {
            return nil, false
        }

        // Return user info as claims
        return &UserInfo{
            ID:    session.UserID,
            Email: session.UserEmail,
        }, true
    },
}))

API Reference

Functions

// New creates middleware with simple validator
func New(validator TokenValidator) mizu.Middleware

// WithHeader creates middleware reading from custom header
func WithHeader(header string, validator TokenValidator) mizu.Middleware

// WithOptions creates middleware with full configuration
func WithOptions(opts Options) mizu.Middleware

Extracting Data

// FromContext extracts token or claims
func FromContext(c *mizu.Ctx) any

// Token extracts the token string
func Token(c *mizu.Ctx) string

// Claims extracts typed claims (generic)
func Claims[T any](c *mizu.Ctx) (T, bool)

Error Types

var (
    ErrTokenMissing  // Token not found in request
    ErrTokenInvalid  // Token validation failed
    ErrInvalidScheme // Auth scheme doesn't match
)

Technical Details

Implementation Overview

The bearerauth middleware implements Bearer token authentication following RFC 6750 standards. It extracts and validates tokens from HTTP headers, storing the token or associated claims in the request context for downstream handlers.

Core Components

  1. Token Extraction: The middleware reads the configured header (default: “Authorization”) and extracts the token after the auth scheme prefix (default: “Bearer ”).
  2. Validation Flow:
    • Checks if the authorization header exists
    • Verifies the auth scheme matches the configured scheme
    • Extracts the token after removing the scheme prefix
    • Invokes either Validator or ValidatorWithContext to validate the token
    • Stores the token or claims in the request context using a private context key
  3. Context Storage: The middleware uses a private contextKey struct to store authentication data in the request context. This prevents key collisions with other middleware or application code.
  4. Error Handling: Three error types are defined:
    • ErrTokenMissing: Returned when no token is found (401 Unauthorized)
    • ErrInvalidScheme: Returned when auth scheme doesn’t match (403 Forbidden)
    • ErrTokenInvalid: Returned when validation fails (403 Forbidden)

Validator Types

  • TokenValidator: Simple boolean validation for basic token checking
  • TokenValidatorWithContext: Returns claims along with validation result, enabling stateful authentication with user data

Data Retrieval

Three helper functions extract authentication data from context:
  • FromContext(c): Returns raw token or claims (type any)
  • Token(c): Returns token string (only when using Validator)
  • Claims[T](c): Type-safe claims extraction (when using ValidatorWithContext)

Security Considerations

  1. Token Security - Use cryptographically secure tokens
  2. HTTPS Required - Always use HTTPS to protect tokens in transit
  3. Token Expiration - Implement token expiration
  4. Secure Storage - Store tokens securely on the client
  5. Revocation - Implement token revocation for logout/security

Best Practices

  • Use short-lived tokens with refresh tokens for better security
  • Validate token claims (expiration, issuer, audience)
  • Log authentication failures for security monitoring
  • Consider rate limiting failed attempts

Testing

The bearerauth middleware includes comprehensive test coverage for all authentication scenarios:
Test CaseDescriptionExpected Behavior
TestNew/allows_valid_tokenValid Bearer token in Authorization headerReturns 200 OK and allows access to protected resource
TestNew/rejects_invalid_tokenInvalid Bearer token providedReturns 403 Forbidden
TestNew/rejects_missing_tokenNo Authorization header presentReturns 401 Unauthorized
TestNew/rejects_wrong_schemeAuthorization header with wrong scheme (e.g., Basic)Returns 403 Forbidden
TestWithHeaderCustom header name (X-Api-Token) with valid tokenReturns 200 OK when token is valid
TestWithOptions_ValidatorWithContextValidatorWithContext returns user claimsClaims are stored in context and accessible via FromContext
TestWithOptions_ErrorHandlerCustom error handler for authentication failuresCustom error handler is invoked with proper error
TestWithOptions_CustomScheme/accepts_custom_schemeCustom auth scheme “Token” instead of “Bearer”Returns 200 OK for matching scheme
TestWithOptions_CustomScheme/rejects_bearer_schemeBearer scheme when Token scheme is configuredReturns 403 Forbidden for mismatched scheme
TestTokenToken extraction using Token() helperToken string is correctly extracted from context
TestWithOptions_PanicsCreating middleware without validatorPanics with appropriate message
TestClaimsType-safe claims extraction using ClaimsTClaims are properly typed and accessible
TestErrorsError message formattingError constants return correct messages
  • basicauth - Username/password authentication
  • keyauth - API key authentication
  • csrf - CSRF protection