Documentation
¶
Overview ¶
Package api provides authorization middleware for fine-grained access control. This file implements scope-based authorization and user context management.
Package api provides HTTP authentication middleware for the EVE service. This file implements HTTP Basic Authentication with bcrypt password verification.
Package api provides HTTP handlers and routing for the EVE evaluation service. It includes authentication, message publishing, and process management endpoints.
Package api provides HTTP middleware and server utilities for API key authentication. It includes middleware for validating API keys and a convenience function for starting a server with API key protection.
Index ¶
- func APIKeyAuth(validKey string) echo.MiddlewareFunc
- func BasicAuthMiddleware(config BasicAuthConfig) echo.MiddlewareFunc
- func GetBasicAuthUsername(c echo.Context) string
- func GetClaims(c echo.Context) (map[string]interface{}, bool)
- func GetScopes(c echo.Context) ([]string, bool)
- func RequireAllScopes(requiredScopes ...string) echo.MiddlewareFunc
- func RequireScope(requiredScopes ...string) echo.MiddlewareFunc
- func SetClaims(c echo.Context, claims map[string]interface{})
- func SetScopes(c echo.Context, scopes []string)
- func SetUser(c echo.Context, user *AuthUser)
- func SetupRoutes(e *echo.Echo, h *Handlers, c *eve.FlowConfig)
- func StartWithApiKey(address, apiKey string)
- type AuthUser
- type BasicAuthConfig
- type Handlers
- type TokenRequest
- type TokenResponse
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func APIKeyAuth ¶
func APIKeyAuth(validKey string) echo.MiddlewareFunc
APIKeyAuth creates an Echo middleware function that validates API keys from request headers. The middleware checks for the presence and validity of an API key in the "X-API-Key" header. If the key is missing or doesn't match the provided valid key, it returns an HTTP 401 Unauthorized error.
This middleware should be applied to routes that require API key authentication. It follows the Echo middleware pattern and can be used with e.Use() or on specific route groups.
Parameters:
- validKey: The expected API key that clients must provide for authentication
Returns:
- echo.MiddlewareFunc: Middleware function that can be used with Echo router
Usage:
e := echo.New()
e.Use(APIKeyAuth("your-secret-api-key"))
HTTP Headers:
- X-API-Key: Required header containing the API key for authentication
Error Responses:
- 401 Unauthorized: Returned when API key is missing or invalid Response body: {"message": "invalid or missing API key"}
func BasicAuthMiddleware ¶ added in v0.0.12
func BasicAuthMiddleware(config BasicAuthConfig) echo.MiddlewareFunc
BasicAuthMiddleware returns an Echo middleware that enforces HTTP Basic Authentication. It validates credentials using bcrypt password hashing for security.
The middleware:
- Checks if the request should be skipped (via Skipper function)
- Extracts credentials from the Authorization header
- Validates username and password against configured values
- Returns 401 Unauthorized with WWW-Authenticate header if authentication fails
Configuration options:
- Username: Required - the expected username
- Password: Plaintext password (less secure, use PasswordHash instead)
- PasswordHash: Bcrypt hash of password (recommended for production)
- Realm: Authentication realm (default: "Restricted")
- Skipper: Function to skip auth for specific requests (optional)
- Validator: Custom validation function (optional)
Parameters:
- config: Basic authentication configuration
Returns:
- echo.MiddlewareFunc: Configured middleware function
Example:
// Using plaintext password (development only)
e := echo.New()
e.Use(BasicAuthMiddleware(BasicAuthConfig{
Username: "admin",
Password: "secret123",
Realm: "Admin Area",
}))
// Using bcrypt hash (recommended for production)
passwordHash, _ := security.HashPassword("secret123")
e.Use(BasicAuthMiddleware(BasicAuthConfig{
Username: "admin",
PasswordHash: passwordHash,
Realm: "Admin Area",
}))
// Skip authentication for health checks
e.Use(BasicAuthMiddleware(BasicAuthConfig{
Username: "admin",
PasswordHash: passwordHash,
Skipper: func(c echo.Context) bool {
return c.Path() == "/health"
},
}))
// Custom validator
e.Use(BasicAuthMiddleware(BasicAuthConfig{
Validator: func(username, password string, c echo.Context) bool {
// Check against database or external service
return validateAgainstDB(username, password)
},
}))
func GetBasicAuthUsername ¶ added in v0.0.12
GetBasicAuthUsername retrieves the authenticated username from the Echo context. Returns empty string if not authenticated via Basic Auth.
Parameters:
- c: Echo context
Returns:
- string: The authenticated username, or empty string if not available
Example:
func handler(c echo.Context) error {
username := GetBasicAuthUsername(c)
if username != "" {
return c.String(200, "Hello, "+username)
}
return c.String(200, "Hello, guest")
}
func GetClaims ¶ added in v0.0.12
GetClaims retrieves JWT/OIDC claims from the Echo context.
Parameters:
- c: Echo context
Returns:
- map[string]interface{}: The claims map, or nil if not available
- bool: true if claims were found in context, false otherwise
Example:
func handler(c echo.Context) error {
claims, ok := GetClaims(c)
if !ok {
return c.String(401, "No claims available")
}
role, _ := claims["role"].(string)
return c.JSON(200, map[string]interface{}{
"role": role,
"claims": claims,
})
}
func GetScopes ¶ added in v0.0.12
GetScopes retrieves authorization scopes from the Echo context.
Parameters:
- c: Echo context
Returns:
- []string: List of scopes, or nil if not available
- bool: true if scopes were found in context, false otherwise
func RequireAllScopes ¶ added in v0.0.12
func RequireAllScopes(requiredScopes ...string) echo.MiddlewareFunc
RequireAllScopes returns Echo middleware that enforces scope-based authorization. Unlike RequireScope, this requires the user to have ALL specified scopes.
Parameters:
- requiredScopes: Scopes that the user must have (all of them)
Returns:
- echo.MiddlewareFunc: Configured middleware function
Example:
// User must have both "read" AND "write" scopes
api.POST("/data", handler, RequireAllScopes("read", "write"))
func RequireScope ¶ added in v0.0.12
func RequireScope(requiredScopes ...string) echo.MiddlewareFunc
RequireScope returns Echo middleware that enforces scope-based authorization. It checks if the authenticated user has at least one of the required scopes.
The middleware expects scopes to be stored in the context (by authentication middleware) either in the User object or directly via SetScopes.
If the user doesn't have any of the required scopes, it returns 403 Forbidden. If no scopes are stored in context, it returns 401 Unauthorized.
Parameters:
- requiredScopes: One or more scopes, where the user must have at least one
Returns:
- echo.MiddlewareFunc: Configured middleware function
Example:
e := echo.New()
// Require "read" scope for GET endpoints
api := e.Group("/api")
api.Use(jwtMiddleware) // Must set scopes in context
api.GET("/data", handler, RequireScope("read"))
// Require either "admin" or "write" scope
api.POST("/data", handler, RequireScope("admin", "write"))
// Chain multiple scope requirements
api.DELETE("/data/:id", handler,
RequireScope("write"), // Must have write
RequireScope("admin"), // AND must have admin
)
func SetClaims ¶ added in v0.0.12
SetClaims stores JWT/OIDC claims in the Echo context. This is typically called by authentication middleware after token validation.
Parameters:
- c: Echo context
- claims: The claims to store
Example:
func jwtMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
// After validating JWT token...
claims := map[string]interface{}{
"sub": "user123",
"email": "john@example.com",
"role": "admin",
}
SetClaims(c, claims)
return next(c)
}
}
func SetScopes ¶ added in v0.0.12
SetScopes stores authorization scopes in the Echo context. This is typically called by authentication middleware.
Parameters:
- c: Echo context
- scopes: List of scope strings
func SetUser ¶ added in v0.0.12
SetUser stores the authenticated user in the Echo context. This is typically called by authentication middleware after successful authentication.
Parameters:
- c: Echo context
- user: The authenticated user to store
Example:
func authMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
// After validating credentials...
user := &AuthUser{
ID: "user123",
Username: "john.doe",
Email: "john@example.com",
Scopes: []string{"read", "write"},
}
SetUser(c, user)
return next(c)
}
}
func SetupRoutes ¶
func SetupRoutes(e *echo.Echo, h *Handlers, c *eve.FlowConfig)
SetupRoutes configures all API routes for the EVE service. It sets up both public and protected endpoints under the /v1/api base path.
Public routes:
- POST /auth/token - Generate authentication token
Protected routes (require JWT authentication):
- POST /v1/api/publish - Publish flow process messages
- GET /v1/api/processes/:id - Get specific process by ID
- GET /v1/api/processes - Get processes, optionally filtered by state
Parameters:
- e: Echo instance to register routes with
- h: Handlers struct containing service dependencies
- c: FlowConfig containing API configuration including signing key
func StartWithApiKey ¶
func StartWithApiKey(address, apiKey string)
StartWithApiKey creates and starts an Echo HTTP server with API key authentication middleware. This is a convenience function that sets up a basic server with a health check endpoint, protected by API key authentication. The server will terminate the program if it fails to start.
The function automatically applies the API key authentication middleware to all routes, meaning every request must include a valid "X-API-Key" header.
Default routes:
- GET /: Health check endpoint that returns "OK!" when API key is valid
Parameters:
- address: The network address and port to bind the server to (e.g., ":8080", "localhost:3000")
- apiKey: The API key that clients must provide in the "X-API-Key" header
Behavior:
- Creates a new Echo instance
- Applies API key authentication middleware globally
- Registers a simple health check endpoint at "/"
- Starts the server and terminates the program on failure
Usage:
StartWithApiKey(":8080", "your-secret-api-key")
Example request:
curl -H "X-API-Key: your-secret-api-key" http://localhost:8080/
Note: This function calls e.Logger.Fatal() which will terminate the program if the server fails to start. For production use, consider handling errors more gracefully.
Types ¶
type AuthUser ¶ added in v0.0.12
type AuthUser struct {
// JSON-LD semantic fields
Context string `json:"@context,omitempty"` // https://schema.org
Type string `json:"@type,omitempty"` // Person
// Schema.org Person properties
Identifier string `json:"identifier"` // Unique user identifier (from "sub" claim)
Name string `json:"name,omitempty"` // Display name
Email string `json:"email,omitempty"` // Email address
GivenName string `json:"givenName,omitempty"` // First name (optional)
FamilyName string `json:"familyName,omitempty"` // Last name (optional)
// Authentication & Authorization properties
Username string `json:"username,omitempty"` // Login name
Scopes []string `json:"scopes,omitempty"` // Authorization scopes
Claims map[string]interface{} `json:"claims,omitempty"` // JWT/OIDC claims
// Legacy fields (for backward compatibility - use Identifier instead)
ID string `json:"id,omitempty"` // Deprecated: use identifier
}
AuthUser represents an authenticated user with associated claims and permissions. Semantic Schema.org Person type for user identity and authentication
func GetUser ¶ added in v0.0.12
GetUser retrieves the authenticated user from the Echo context. Returns nil if no user is authenticated or if authentication middleware hasn't run.
Parameters:
- c: Echo context
Returns:
- *AuthUser: The authenticated user, or nil if not available
- bool: true if user was found in context, false otherwise
Example:
func handler(c echo.Context) error {
user, ok := GetUser(c)
if !ok {
return c.String(401, "Not authenticated")
}
return c.JSON(200, map[string]string{
"message": "Hello, " + user.Username,
"user_id": user.ID,
})
}
type BasicAuthConfig ¶ added in v0.0.12
type BasicAuthConfig struct {
// Username is the expected username for authentication
Username string
// Password is the plaintext password (will be compared with PasswordHash via bcrypt)
// Either Password or PasswordHash must be set (PasswordHash is preferred for security)
Password string
// PasswordHash is the bcrypt hash of the password
// If set, this takes precedence over Password field
PasswordHash string
// Realm is the authentication realm shown in the browser's login prompt
// Default: "Restricted"
Realm string
// Skipper defines a function to skip middleware for specific requests
// Default: nil (all requests require authentication)
Skipper func(c echo.Context) bool
// Validator is a custom validation function for username/password
// If set, this overrides the default bcrypt validation
// Return true if credentials are valid, false otherwise
Validator func(username, password string, c echo.Context) bool
}
BasicAuthConfig contains configuration for Basic Authentication middleware.
type Handlers ¶
type Handlers struct {
RabbitMQ queue.MessagePublisher // Message publisher for flow process messages
CouchDB db.DocumentStore // Document store for process data
JWT *security.JWTService // JWT service for token generation and validation
}
Handlers contains the service dependencies required for API operations. It provides access to message publishing, document storage, and JWT authentication. Uses interfaces to enable easy testing and mocking.
func (*Handlers) GenerateToken ¶
GenerateToken handles JWT token generation for user authentication. It validates the user ID and generates a token with 24-hour expiration.
Endpoint: POST /auth/token
Request body:
{
"user_id": "string" // Required: User identifier
}
Response:
Success (200): {"token": "jwt_token_string"}
Bad Request (400): {"error": "error_message"}
Internal Error (500): {"error": "error_message"}
func (*Handlers) GetProcess ¶
GetProcess retrieves a specific process document by its ID from CouchDB. Returns the complete process document if found.
Endpoint: GET /v1/api/processes/:id Authentication: Required (JWT Bearer token)
Path Parameters:
- id: Process identifier
Response:
Success (200): Process document JSON
Bad Request (400): {"error": "Process ID is required"}
Not Found (404): {"error": "Process not found"}
Internal Error (500): {"error": "Failed to retrieve process"}
func (*Handlers) GetProcessesByState ¶
GetProcessesByState retrieves processes from CouchDB, optionally filtered by state. If no state parameter is provided, returns all processes. Validates state parameter against allowed values if provided.
Endpoint: GET /v1/api/processes Authentication: Required (JWT Bearer token)
Query Parameters:
- state (optional): Filter processes by state Valid values: "started", "running", "successful", "failed"
Response:
Success (200): {
"processes": [...], // Array of process documents
"count": number // Total count of returned processes
}
Bad Request (400): {"error": "Invalid state value"}
Internal Error (500): {"error": "Failed to retrieve processes"}
func (*Handlers) PublishMessage ¶
PublishMessage handles publishing of flow process messages to RabbitMQ. It validates the message format and required fields before publishing. If no timestamp is provided, it sets the current time.
Endpoint: POST /v1/api/publish Authentication: Required (JWT Bearer token)
Request body:
{
"process_id": "string", // Required: Process identifier
"state": "string", // Required: Process state
"timestamp": "datetime", // Optional: Message timestamp (auto-set if empty)
// ... other FlowProcessMessage fields
}
Response:
Success (200): {"status": "Message published successfully"}
Bad Request (400): {"error": "error_message"}
Internal Error (500): {"error": "error_message"}
type TokenRequest ¶
type TokenRequest struct {
UserID string `json:"user_id" validate:"required"` // User identifier for token association
}
TokenRequest represents the request payload for token generation. It requires a user ID to associate with the generated JWT token.
type TokenResponse ¶
type TokenResponse struct {
Token string `json:"token"` // JWT token for API authentication
}
TokenResponse represents the response payload containing the generated JWT token.