Documentation
¶
Overview ¶
Package auth provides authentication and authorization utilities for HTTP handlers.
Package auth provides authentication and authorization utilities for HTTP handlers. It supports multiple authentication methods including Basic Auth, Bearer tokens, and JWT.
Index ¶
- Constants
- Variables
- func BasicHandler(h http.Handler, credentials map[string]string) http.Handler
- func BasicHandlerWithConfig(h http.Handler, config BasicAuthConfig) http.Handler
- func BearerAuth(r *http.Request) (string, bool)
- func BearerHandler(h http.Handler, secret []byte) http.Handler
- func BearerHandlerWithConfig(h http.Handler, config BearerAuthConfig) http.Handler
- func ComparePasswordHashSHA256(hashedPassword, password string) bool
- func DefaultBearerErrorHandler(w http.ResponseWriter, r *http.Request, err error)
- func HashPasswordSHA256(password string) string
- func RequireBearerHandler(h http.Handler) http.Handler
- func RequireBearerHandlerWithOptions(h http.Handler, options RequireBearerOptions) http.Handler
- type BasicAuthConfig
- type BearerAuthConfig
- type Claims
- type JWT
- type JWTConfig
- type RequireBearerOptions
Constants ¶
const Bearer = "Bearer"
Bearer is the expected authorization scheme for bearer token authentication.
Variables ¶
var ( // ClaimsContext stores JWT claims in the request context. // Set by BearerHandler after successful token verification. // Use: claims, ok := auth.ClaimsContext.Value(ctx) ClaimsContext contextkey.Key[*Claims] = "claims" // UsernameContext stores the authenticated username in the request context. // Set by BasicHandler after successful basic authentication. // Use: username, ok := auth.UsernameContext.Value(ctx) UsernameContext contextkey.Key[string] = "username" // LoggerContext stores a structured logger in the request context. // Used by authentication middleware for consistent logging. // Use: logger, ok := auth.LoggerContext.Value(ctx) LoggerContext contextkey.Key[*slog.Logger] = "logger" )
Context keys for storing authentication-related data in HTTP request contexts. These provide type-safe storage and retrieval of authentication information that can be used by downstream handlers and middleware.
var ( // ErrClaimsInvalid indicates that the JWT claims are malformed or invalid. ErrClaimsInvalid = errors.New("auth: invalid claims") // ErrTokenInvalid indicates that the JWT token is malformed, has invalid signature, or other issues. ErrTokenInvalid = errors.New("auth: invalid token") // ErrTokenExpired indicates that the JWT token has passed its expiration time. ErrTokenExpired = errors.New("auth: token expired") // ErrNoSecret indicates that no signing secret was provided for JWT operations. ErrNoSecret = errors.New("auth: no secret provided") )
JWT-related errors that can occur during token operations.
Functions ¶
func BasicHandler ¶
BasicHandler creates an HTTP Basic Authentication middleware using the provided username/password credentials. This is a convenience function that uses default configuration with realm "User Visible Realm".
The middleware performs constant-time password comparison to prevent timing attacks. Upon successful authentication, the username is stored in the request context and can be retrieved using auth.UsernameFromContext().
Example:
credentials := map[string]string{
"admin": "secret123",
"user": "password456",
}
handler := auth.BasicHandler(myHandler, credentials)
http.ListenAndServe(":8080", handler)
func BasicHandlerWithConfig ¶
func BasicHandlerWithConfig(h http.Handler, config BasicAuthConfig) http.Handler
BasicHandlerWithConfig creates an HTTP Basic Authentication middleware with customizable configuration. This allows control over the authentication realm and credential storage.
The middleware follows RFC 7617 and performs these steps:
- Extracts credentials from the Authorization header
- Validates credentials against the configured username/password map
- Uses constant-time comparison to prevent timing attacks
- Sets WWW-Authenticate header on authentication failures
- Stores authenticated username in request context on success
Example:
config := auth.BasicAuthConfig{
Credentials: map[string]string{"admin": "secret"},
Realm: "Admin Panel",
}
handler := auth.BasicHandlerWithConfig(myHandler, config)
func BearerAuth ¶
BearerAuth extracts and validates a bearer token from the Authorization header.
This function parses the Authorization header looking for a bearer token in the format "Bearer <token>". It returns the token and a boolean indicating whether a valid bearer token was found.
Parameters:
- r: The HTTP request to extract the bearer token from
Returns:
- The bearer token string (empty if not found or invalid)
- A boolean indicating whether a valid bearer token was found
Example:
// Authorization: Bearer abc123xyz
token, ok := auth.BearerAuth(r)
if ok {
// token = "abc123xyz"
// Validate token...
}
The function validates that: - The Authorization header is present - The header starts with "Bearer " - There is a non-empty token after "Bearer "
func BearerHandler ¶
BearerHandler creates a middleware that validates JWT bearer tokens using the provided secret. This is a convenience function that creates optional authentication - requests without tokens are allowed to proceed. For required authentication, use BearerHandlerWithConfig with Optional: false.
Example:
handler := auth.BearerHandler(myHandler, []byte("my-secret-key"))
http.ListenAndServe(":8080", handler)
func BearerHandlerWithConfig ¶
func BearerHandlerWithConfig(h http.Handler, config BearerAuthConfig) http.Handler
BearerHandlerWithConfig creates a bearer token authentication middleware with customizable configuration. This allows fine-grained control over authentication behavior including optional vs required authentication and custom error handling.
The middleware performs the following steps:
- Extracts the bearer token from the Authorization header
- If no token is present and authentication is optional, allows the request to proceed
- If no token is present and authentication is required, calls the error handler
- Verifies the JWT token signature and claims
- Adds verified claims to the request context for use by downstream handlers
Example:
config := auth.BearerAuthConfig{
Secret: []byte("my-secret-key"),
Optional: false, // Require authentication
OnError: myCustomErrorHandler,
}
handler := auth.BearerHandlerWithConfig(myHandler, config)
func ComparePasswordHashSHA256 ¶
ComparePasswordHashSHA256 compares a SHA-256 hashed password with its possible plaintext equivalent.
func DefaultBearerErrorHandler ¶
func DefaultBearerErrorHandler(w http.ResponseWriter, r *http.Request, err error)
DefaultBearerErrorHandler provides a standard RFC 6750 compliant error response for bearer token authentication failures. It sets the appropriate WWW-Authenticate header and logs the error if a logger is available in the request context.
func HashPasswordSHA256 ¶
HashPasswordSHA256 hashes a plain-text password using SHA-256. Use this when storing credentials in production.
func RequireBearerHandler ¶
RequireBearerHandler enforces that the request has valid JWT claims in its context. This middleware should be used after BearerHandler to ensure that only authenticated requests proceed. It checks for the presence of claims in the request context that were added by a previous authentication middleware.
This is useful for protecting routes that must have authentication, while allowing the initial bearer handler to be optional for some routes.
Example:
// Allow optional authentication
optionalAuth := auth.BearerHandler(myHandler, secret)
// Require authentication for specific routes
requiredAuth := auth.RequireBearerHandler(protectedHandler)
mux.Handle("/public", optionalAuth)
mux.Handle("/protected", chain.Handler(requiredAuth, optionalAuth))
func RequireBearerHandlerWithOptions ¶
func RequireBearerHandlerWithOptions(h http.Handler, options RequireBearerOptions) http.Handler
RequireBearerHandlerWithOptions creates a customizable middleware that enforces the presence of valid JWT claims in the request context. This provides more granular control over error handling when authentication is missing.
Example:
options := auth.RequireBearerOptions{
ErrorHandler: func(w http.ResponseWriter, r *http.Request, err error) {
// Custom JSON error response
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusUnauthorized)
json.NewEncoder(w).Encode(map[string]string{
"error": "authentication_required",
"message": "This endpoint requires valid authentication",
})
},
}
handler := auth.RequireBearerHandlerWithOptions(myHandler, options)
Types ¶
type BasicAuthConfig ¶
type BasicAuthConfig struct {
// Credentials maps usernames to their corresponding passwords.
// Passwords should be stored securely (hashed) in production environments.
Credentials map[string]string
// Realm is the authentication realm displayed to users in browser dialogs.
// This helps users understand what they're authenticating for.
// If empty, defaults to "Restricted".
Realm string
}
BasicAuthConfig holds configuration for HTTP Basic Authentication middleware. Basic authentication uses username/password credentials encoded in the Authorization header as specified in RFC 7617.
type BearerAuthConfig ¶
type BearerAuthConfig struct {
// Secret is the HMAC secret key used to sign and verify JWT tokens.
// This should be a cryptographically secure random string of at least 32 bytes.
Secret []byte
// Optional determines whether authentication is required for the protected route.
// When true, requests without tokens are allowed to proceed.
// When false, all requests must have valid bearer tokens.
Optional bool
// OnError is called when authentication fails or tokens are invalid.
// This allows for custom error responses and logging behavior.
// If nil, DefaultBearerErrorHandler will be used.
OnError func(w http.ResponseWriter, r *http.Request, err error)
}
BearerAuthConfig holds configuration for bearer token authentication middleware. This configuration allows for flexible authentication behavior including optional authentication and custom error handling.
type Claims ¶
type Claims = jwt.RegisteredClaims
Claims extends the standard JWT RegisteredClaims with commonly used fields. This type alias allows for easy extension while maintaining compatibility with the jwt-go library's standard claims.
type JWT ¶
type JWT struct {
Secret []byte
SigningMethod jwt.SigningMethod
Issuer string
ExpiryLeeway time.Duration
}
JWT manages the signing and verification of JWT tokens with configurable options. It provides a high-level interface for common JWT operations while allowing fine-grained control over token behavior.
func NewJWT ¶
NewJWT creates a new JWT manager with default settings (HS256 signing method). This is a convenience function for simple use cases where default configuration is sufficient.
Example:
jwt := auth.NewJWT([]byte("my-secret-key"))
token, err := jwt.Sign(auth.Claims{Subject: "user123"}, time.Hour)
func NewJWTWithConfig ¶
NewJWTWithConfig creates a JWT manager with custom configuration options. This allows full control over signing methods, issuers, and validation behavior.
Example:
config := auth.JWTConfig{
Secret: []byte("my-secret-key"),
SigningMethod: jwt.SigningMethodHS384,
Issuer: "my-service",
ExpiryLeeway: 30 * time.Second,
}
jwt := auth.NewJWTWithConfig(config)
func (*JWT) Sign ¶
Sign creates a signed JWT token with the provided claims and time-to-live duration. It automatically sets standard claims like issued-at, not-before, and expiration times. The subject claim is required and an error is returned if it's empty.
Example:
claims := auth.Claims{
Subject: "user123",
Issuer: "my-service", // Optional, will use JWT.Issuer if not set
}
token, err := jwt.Sign(claims, 24*time.Hour)
func (*JWT) SignWithCustomClaims ¶
SignWithCustomClaims creates a signed JWT token with custom claims structure. This allows for non-standard claims beyond the registered claims set. Note: TTL parameter is not used here as custom claims should handle expiration.
Example:
type CustomClaims struct {
jwt.RegisteredClaims
Role string `json:"role"`
Permissions []string `json:"permissions"`
}
claims := CustomClaims{
RegisteredClaims: jwt.RegisteredClaims{
Subject: "user123",
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour)),
},
Role: "admin",
Permissions: []string{"read", "write"},
}
token, err := jwt.SignWithCustomClaims(claims, time.Hour)
func (*JWT) Verify ¶
Verify validates a JWT token string and returns the parsed registered claims. It performs comprehensive validation including:
- Signature verification using the configured secret
- Signing method validation to prevent algorithm confusion attacks
- Expiration time validation with optional leeway for clock skew
- Standard claims validation (nbf, iat, etc.)
Example:
claims, err := jwt.Verify(tokenString)
if err != nil {
// Handle invalid token
return
}
userID := claims.Subject
func (*JWT) VerifyWithCustomClaims ¶
VerifyWithCustomClaims validates a JWT token with custom claims structure. Unlike Verify(), this method allows you to parse tokens with non-standard claims while still performing all security validations. The claims parameter should be a pointer to your custom claims struct.
Example:
type CustomClaims struct {
jwt.RegisteredClaims
Role string `json:"role"`
Permissions []string `json:"permissions"`
}
var claims CustomClaims
err := jwt.VerifyWithCustomClaims(tokenString, &claims)
if err != nil {
// Handle invalid token
return
}
userRole := claims.Role
type JWTConfig ¶
type JWTConfig struct {
// Secret is the HMAC secret key used to sign and verify JWT tokens.
// For HMAC algorithms (HS256, HS384, HS512), this should be a cryptographically
// secure random string of appropriate length (32+ bytes recommended).
Secret []byte
// SigningMethod specifies the algorithm used to sign tokens.
// Common values: jwt.SigningMethodHS256, jwt.SigningMethodHS384, jwt.SigningMethodHS512
// Default: HS256 if not specified.
SigningMethod jwt.SigningMethod
// Issuer is the 'iss' (issuer) claim added to generated tokens.
// This identifies the service that issued the token and can be used for validation.
Issuer string
// ExpiryLeeway is additional time added to token expiration during validation.
// This accounts for clock skew between systems. Common values: 30s-5m.
ExpiryLeeway time.Duration
}
JWTConfig holds configuration options for JWT token management. This allows customization of signing methods, issuers, and validation behavior.
type RequireBearerOptions ¶
type RequireBearerOptions struct {
// ErrorHandler is called when authentication is missing or invalid.
// If nil, DefaultBearerErrorHandler will be used.
ErrorHandler func(w http.ResponseWriter, r *http.Request, err error)
}
RequireBearerOptions configures the behavior of the require bearer handler.