docs/guide/extractors.md
The extractors package provides shared value extraction utilities for Fiber middleware packages. It helps reduce code duplication across middleware packages while ensuring consistent behavior and security practices.
The github.com/gofiber/fiber/v3/extractors module provides standardized value extraction utilities integrated into Fiber's middleware ecosystem. This approach:
Extractors are utilities that middleware uses to get values from different parts of HTTP requests:
FromAuthHeader(authScheme string): Extract from Authorization header with optional schemeFromCookie(key string): Extract from HTTP cookiesFromParam(param string): Extract from URL path parametersFromForm(param string): Extract from form dataFromHeader(header string): Extract from custom HTTP headersFromQuery(param string): Extract from URL query parametersFromCustom(key string, fn func(fiber.Ctx) (string, error)): Define custom extraction logic with metadataChain(extractors ...Extractor): Chain multiple extractors with fallback logicEach Extractor contains:
type Extractor struct {
Extract func(fiber.Ctx) (string, error) // Extraction function
Key string // Parameter/header name
Source Source // Source type for inspection
AuthScheme string // Auth scheme (FromAuthHeader)
Chain []Extractor // Chained extractors
}
Authorization, X-API-Key, custom headers?token=abc123/users/:idThe Chain function creates extractors that try multiple sources in order:
ErrNotFoundnil Extract functionsChain fieldMiddleware needs to extract values from requests for authentication, authorization, and other purposes. Extractors provide:
// KeyAuth middleware extracts key from header
app.Use(keyauth.New(keyauth.Config{
Extractor: extractors.FromHeader("Middleware-Key"),
}))
// Try multiple sources in order
tokenExtractor := extractors.Chain(
extractors.FromHeader("Middleware-Key"), // Try header first
extractors.FromCookie("middleware_key"), // Then cookie
extractors.FromQuery("middleware_key"), // Finally query param
)
app.Use(keyauth.New(keyauth.Config{
Extractor: tokenExtractor,
}))
// KeyAuth middleware (default: FromAuthHeader)
app.Use(keyauth.New(keyauth.Config{
// Default extracts from Authorization header
// Extractor: extractors.FromAuthHeader("Bearer"),
}))
// Custom header extraction
app.Use(keyauth.New(keyauth.Config{
Extractor: extractors.FromHeader("X-API-Key"),
}))
// Multiple sources with secure fallback
app.Use(keyauth.New(keyauth.Config{
Extractor: extractors.Chain(
extractors.FromAuthHeader("Bearer"), // Secure first
extractors.FromHeader("X-API-Key"), // Then custom header
extractors.FromQuery("api_key"), // Least secure last
),
}))
// Session middleware (default: FromCookie)
app.Use(session.New(session.Config{
// Default extracts from session_id cookie
// Extractor: extractors.FromCookie("session_id"),
}))
// Custom cookie name
app.Use(session.New(session.Config{
Extractor: extractors.FromCookie("my_session"),
}))
// CSRF middleware (default: FromHeader)
app.Use(csrf.New(csrf.Config{
// Default extracts from X-CSRF-Token header
// Extractor: extractors.FromHeader("X-CSRF-Token"),
}))
// Form-based CSRF (less secure, use only if needed)
app.Use(csrf.New(csrf.Config{
Extractor: extractors.Chain(
extractors.FromHeader("X-CSRF-Token"), // Secure first
extractors.FromForm("_csrf"), // Form fallback
),
}))
Different extraction sources have different security properties and use cases:
Secure, HttpOnly, and SameSite flagsWhen using multiple sources, order them by your security preferences:
// Example: Prefer headers, fall back to cookies, then query
extractors.Chain(
extractors.FromAuthHeader("Bearer"), // Standard auth
extractors.FromCookie("auth_token"), // Secure storage
extractors.FromQuery("token"), // Public fallback
)
The "best" source depends on your specific use case, security requirements, and application architecture.
// β DON'T: API keys in URLs (visible in logs, history, bookmarks)
app.Use(keyauth.New(keyauth.Config{
Extractor: extractors.FromQuery("api_key"), // PROBLEMATIC
}))
// β
DO: API keys in headers (not visible in URLs)
app.Use(keyauth.New(keyauth.Config{
Extractor: extractors.FromHeader("X-API-Key"), // BETTER
}))
// β DON'T: Session tokens in URLs (can be bookmarked, leaked)
app.Use(session.New(session.Config{
Extractor: extractors.FromQuery("session"), // PROBLEMATIC
}))
// β
DO: Session tokens in cookies (designed for this purpose)
app.Use(session.New(session.Config{
Extractor: extractors.FromCookie("session_id"), // BETTER
}))
While the default extractor uses headers, some implementations use form fields, which is fine if you don't have AJAX or API clients:
// β DON'T: CSRF tokens only in forms (breaks AJAX, API calls)
app.Use(csrf.New(csrf.Config{
Extractor: extractors.FromForm("_csrf"), // LIMITED
}))
// β
DO: Header-first with form fallback (works everywhere)
app.Use(csrf.New(csrf.Config{
Extractor: extractors.Chain(
extractors.FromHeader("X-CSRF-Token"), // PREFERRED
extractors.FromForm("_csrf"), // FALLBACK
),
}))
No extractor is universally "secure" - security depends on:
Choose extractors based on your specific use case and security needs, not blanket "secure" vs "insecure" labels.
The FromAuthHeader extractor provides comprehensive RFC compliance with strict security validation:
credentials = auth-scheme 1*SP token68 structureBearer, bearer, BEARER all work correctlyThe extractor implements strict token68 character validation per RFC 7235:
A-Z, a-z, 0-9, -, ., _, ~, +, /, == characters only allowed at the end of tokens= or having non-padding characters after =ErrNotFound for all invalid cases// Standard usage - strict validation
extractor := extractors.FromAuthHeader("Bearer")
// β
Valid cases:
// "Bearer abc123" -> "abc123"
// "bearer ABC123" -> "ABC123" (case-insensitive scheme)
// "Bearer token123=" -> "token123=" (valid padding)
// "Bearer token==" -> "token==" (valid multiple padding)
// β Invalid cases (all return ErrNotFound):
// "Bearer abc def" -> rejected (space in token)
// "Bearer abc\tdef" -> rejected (tab in token)
// "Bearer =abc" -> rejected (padding at start)
// "Bearer ab=cd" -> rejected (padding in middle)
// "Bearer token" -> rejected (multiple spaces after scheme)
// "Bearer\ttoken" -> rejected (tab after scheme)
// "Bearertoken" -> rejected (no space after scheme)
// Raw header extraction (no validation)
rawExtractor := extractors.FromAuthHeader("")
// "CustomAuth anything goes here" -> "CustomAuth anything goes here"
Problem: Middleware returns "value not found" or authentication fails
Solutions:
Debug Example:
// Add simple debug logging (avoid logging secrets in production)
app.Use(func(c fiber.Ctx) error {
hdr := c.Get("X-API-Key")
cookie := c.Cookies("session_id")
if hdr != "" || cookie != "" {
log.Printf("debug: X-API-Key present=%t, session_id present=%t", hdr != "", cookie != "")
}
return c.Next()
})
Problem: Values extracted from unexpected sources
Solutions:
Problem: Getting security warnings in logs
Solutions:
Extractors support custom extractors for complex scenarios:
// Extract from custom logic (rarely needed)
customExtractor := extractors.FromCustom("my-source", func(c fiber.Ctx) (string, error) {
// Complex extraction logic
if value := c.Locals("computed_token"); value != nil {
return value.(string), nil
}
return "", extractors.ErrNotFound
})
:::warning
Custom extractors break source awareness. When you use FromCustom, middleware cannot determine where the value came from, which means:
Only use FromCustom when:
Note: If you pass nil as the function parameter, FromCustom will return an extractor that always fails with ErrNotFound.
:::
When using multiple middleware that extract values, ensure they don't conflict:
// Good: Different sources for different purposes
app.Use(keyauth.New(keyauth.Config{
Extractor: extractors.FromHeader("X-API-Key"),
}))
app.Use(session.New(session.Config{
Extractor: extractors.FromCookie("session_id"),
}))
// Avoid: Same source for different middleware
app.Use(keyauth.New(keyauth.Config{
Extractor: extractors.FromCookie("token"), // API auth
}))
app.Use(session.New(session.Config{
Extractor: extractors.FromCookie("token"), // Session - CONFLICT!
}))