api

package
v0.0.57 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 15, 2025 License: Apache-2.0 Imports: 10 Imported by: 0

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

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:

  1. Checks if the request should be skipped (via Skipper function)
  2. Extracts credentials from the Authorization header
  3. Validates username and password against configured values
  4. 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

func GetBasicAuthUsername(c echo.Context) string

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

func GetClaims(c echo.Context) (map[string]interface{}, bool)

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

func GetScopes(c echo.Context) ([]string, bool)

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

func SetClaims(c echo.Context, claims map[string]interface{})

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

func SetScopes(c echo.Context, scopes []string)

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

func SetUser(c echo.Context, user *AuthUser)

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

func GetUser(c echo.Context) (*AuthUser, bool)

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

func (h *Handlers) GenerateToken(c echo.Context) error

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

func (h *Handlers) GetProcess(c echo.Context) error

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

func (h *Handlers) GetProcessesByState(c echo.Context) error

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

func (h *Handlers) PublishMessage(c echo.Context) error

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL