Skip to content

Latest commit

 

History

History
330 lines (239 loc) · 14.7 KB

File metadata and controls

330 lines (239 loc) · 14.7 KB

Authelia Integration

Local development only. This implementation is intentionally scoped to local development environments and is not suitable for production. See Known Limitations below.

This package provides integration between the LFX v2 Auth Service and Authelia, a modern authentication and authorization server. The integration enables local development environments to use Authelia as an identity provider while maintaining user data persistence through NATS Key-Value store.

Architecture Overview

The Authelia integration consists of several key components:

  • NATS KV Storage: Persistent storage for user data using NATS Key-Value store
  • Kubernetes Orchestrator: Manages Authelia ConfigMaps, Secrets, and DaemonSet restarts
  • Sync Engine: Synchronizes user data between NATS KV and Authelia's Kubernetes resources (currently runs only at auth-service startup; future versions will watch for NATS KV changes)

Token Support

The Authelia integration takes an opaque token and validates/retrieves user data from the Authelia identity provider. The system uses the opaque token to authenticate with Authelia's OIDC UserInfo endpoint and extract user identification information.

Opaque Token Processing

Token Format: Opaque tokens issued by Authelia

Token Structure:

authelia_at_Tx****

Token Processing Flow

  1. Token Validation: Validates the opaque token with Authelia's OIDC UserInfo endpoint
  2. UserInfo Retrieval: Calls Authelia's /api/oidc/userinfo endpoint with the token
  3. Sub Extraction: Extracts the sub (subject) claim from the UserInfo response
  4. User Lookup: Uses the extracted sub value for user data retrieval
  5. User Data Retrieval: Returns user metadata from Authelia

Authelia OIDC Integration

UserInfo Endpoint:

GET /api/oidc/userinfo
Authorization: Bearer {opaque_token}

UserInfo Response:

{
  "sub": "550e8400-e29b-41d4-a716-446655440000",
  "name": "John Doe",
  "email": "john.doe@example.com"
}

Important Notes

  • Opaque Token Validation: Full token validation is performed with Authelia's OIDC UserInfo endpoint
  • Token Expiration: Opaque tokens are validated for expiration and freshness by Authelia
  • Authelia OIDC: Uses Authelia's OIDC UserInfo endpoint for user data retrieval
  • SUB Management: The sub claim is deterministically generated by Authelia and used for user identification

Components

Storage Layer (storage.go)

  • Implements NATS Key-Value store for persistent user data
  • Provides CRUD operations for Authelia user records
  • Maintains user data in JSON format within NATS KV buckets

Orchestrator Layer (orchestrator.go)

  • Manages Kubernetes resources (ConfigMaps, Secrets, DaemonSets)
  • Updates Authelia configuration when user data changes
  • Handles DaemonSet restarts to apply configuration changes

Sync Engine (sync.go)

  • Compares user data between NATS KV storage and Kubernetes ConfigMaps
  • Determines required actions (create, update, or no action needed)
  • Orchestrates updates to maintain consistency between storage and runtime configuration

User Management (user.go)

  • Provides high-level user operations (get, update, search)
  • Integrates with the sync engine to ensure data consistency
  • Implements the domain port interfaces for user management

Sync Flow

The synchronization process ensures that user data stored in NATS KV is properly reflected in Authelia's runtime configuration:

  1. Load Phase: Retrieves user data from both NATS KV storage and Kubernetes ConfigMaps
  2. Compare Phase: Identifies differences between storage and orchestrator data
  3. Sync Phase: Updates storage and/or orchestrator based on identified differences
  4. Restart Phase: Restarts Authelia DaemonSet when configuration changes are made

Sequence Diagram

The following sequence diagram illustrates the synchronization process between NATS KV storage and Authelia's Kubernetes resources:

sequenceDiagram
    participant AS as Auth Service
    participant NK as NATS KV Store
    participant CM as ConfigMap
    participant SEC as Secrets
    participant DS as DaemonSet
    participant A as Authelia Pod

    Note over AS: Service Startup / User Update
    
    AS->>NK: Load users from NATS KV
    AS->>CM: Load users from ConfigMap
    
    Note over AS: Compare Phase
    AS->>AS: Compare users between storage and orchestrator
    AS->>AS: Determine required actions
    
    alt User needs storage creation
        AS->>NK: Create/Update user in NATS KV
    end
    
    alt User needs orchestrator update
        AS->>AS: Generate new password pair (plain + bcrypt)
        AS->>NK: Update user with bcrypt hash
        AS->>CM: Update ConfigMap with user config (YAML)
        AS->>SEC: Update Secret with plain password
        AS->>DS: Restart DaemonSet (add restart annotation)
        DS->>A: Rolling restart Authelia pods
        A->>A: Load new configuration from ConfigMap
        A->>A: Access passwords from Secret
    end
    
    Note over A: Authelia ready with updated user data
Loading

Sync Actions

  • Storage Creation: User exists in orchestrator but not in storage - user is added to NATS KV
  • Orchestrator Creation: User exists in storage but not in orchestrator - ConfigMap and Secrets are updated
  • Orchestrator Update: User exists in both but has different password or email - ConfigMap and Secrets are updated
  • No Action: User data is consistent between storage and orchestrator

Configuration

The Authelia integration requires the following configuration parameters:

Kubernetes Configuration

  • namespace: Kubernetes namespace where Authelia resources are deployed
  • configmap-name: Name of the ConfigMap containing Authelia user configuration
  • daemon-set-name: Name of the Authelia DaemonSet to restart when needed
  • secret-name: Name of the Secret containing user passwords

NATS Configuration

  • NATS server connection details (inherited from main service configuration)
  • Key-Value bucket configuration for user data storage

Subject Identifier (SUB) Management

SUB Generation and Persistence

The Subject Identifier (SUB) in Authelia is a deterministic UUID that uniquely identifies each user within the system. Key characteristics:

  • Deterministic Generation: The SUB is a UUID that is deterministically generated from the username by Authelia
  • No Provider Prefix: Unlike Auth0 (which uses formats like auth0|123456789), Authelia SUBs are pure UUIDs without any provider prefix (e.g., 550e8400-e29b-41d4-a716-446655440000)
  • Username-Based: The SUB is consistently derived from the username, ensuring the same username always produces the same SUB
  • Token-Based Persistence: To ensure consistent data retrieval from Authelia, the SUB is only persisted when a user is updated using a valid authentication token
  • OIDC UserInfo Endpoint: The SUB can be retrieved from Authelia's OIDC UserInfo endpoint at /api/oidc/userinfo using a valid token

Token-Based User Updates

When updating user metadata through the auth service, the SUB is populated by accessing Authelia's UserInfo endpoint with the provided token:

# Example: Update user metadata with token (this populates the SUB)
nats req --server nats://lfx-platform-nats.lfx.svc.cluster.local:4222 "lfx.auth-service.user_metadata.update" '{
  "token": "authelia_at_Tx****",
  "user_metadata": {
    "city": "Metropolis"
  }
}'

This process ensures that:

  • The SUB is retrieved from Authelia's authoritative source
  • User data consistency is maintained across the system
  • The canonical user identifier is properly established for future lookups

Alternate Email Linking with OTP Verification

The Authelia integration supports linking alternate email addresses to user accounts through a secure OTP (One-Time Password) verification flow. This feature enables users to add and verify additional email addresses without requiring a full authentication flow.

OTP Flow Architecture

The OTP verification system uses a dedicated NATS Key-Value bucket with TTL (Time-To-Live) for secure and temporary storage of verification codes. This ensures that:

  • OTP codes are automatically expired after a configured time period (default: 5 minutes)
  • No manual cleanup is required - NATS handles expiration automatically
  • Storage is isolated from user data in a separate KV bucket
  • Verification codes are ephemeral and cannot be reused after expiration

OTP Verification Flow

sequenceDiagram
    participant User
    participant AuthService
    participant SMTP
    participant NATSKV as NATS KV<br/>(authelia-email-otp)
    participant Storage as NATS KV<br/>(authelia-users)

    Note over User,Storage: Step 1: Send Verification Code
    
    User->>AuthService: Send verification (alternate email)
    AuthService->>AuthService: Check email not already linked
    AuthService->>AuthService: Generate 6-digit OTP
    AuthService->>SMTP: Send OTP email
    SMTP-->>User: Email with OTP code
    
    AuthService->>NATSKV: Store OTP with TTL<br/>Key: email<br/>Value: OTP code<br/>TTL: 5 minutes
    NATSKV-->>AuthService: Success
    AuthService-->>User: Verification sent

    Note over User,Storage: Step 2: Verify OTP Code
    
    User->>AuthService: Verify OTP (email + code)
    AuthService->>AuthService: Check email not already linked
    AuthService->>NATSKV: Get OTP by email key
    
    alt OTP Found and Valid
        NATSKV-->>AuthService: OTP code
        AuthService->>AuthService: Compare submitted vs stored OTP
        alt OTP Matches
            AuthService->>AuthService: Generate identity tokens<br/>(ID token + Access token)
            AuthService-->>User: Success + tokens
        else OTP Mismatch
            AuthService-->>User: Error: Invalid code
        end
    else OTP Not Found or Expired
        NATSKV-->>AuthService: KeyNotFound error
        AuthService-->>User: Error: Code expired
    end

    Note over User,Storage: Step 3: Link Identity to User
    
    User->>AuthService: Link identity (user token + identity token)
    AuthService->>AuthService: Parse identity token<br/>Extract email from claims
    AuthService->>Storage: Get user with revision
    Storage-->>AuthService: User data + revision
    AuthService->>AuthService: Add email to AlternateEmails
    AuthService->>Storage: Update user with revision<br/>(optimistic locking)
    Storage-->>AuthService: Success
    AuthService-->>User: Identity linked
Loading

OTP Storage Implementation

NATS KV Bucket Configuration:

  • Bucket Name: authelia-email-otp (constants.KVBucketNameAutheliaEmailOTP)
  • TTL: 5 minutes (configurable at bucket creation)
  • Key Format: Email address (used as alternate email index key)
  • Value Format: 6-digit numeric OTP code (stored as plain string)
  • Auto-Expiration: NATS automatically removes expired entries after TTL

Token Generation After Verification

Upon successful OTP verification, the system generates two tokens:

ID Token:

  • Contains verified email as subject claim (sub: "email|{email}")
  • Used for identity linking operation
  • Validity: 60 minutes
  • Format: JWT with custom claims

Access Token:

  • Standard OAuth2 access token
  • Same validity period as ID token
  • Used for authenticated operations

Integration with Identity Linking

The OTP verification flow integrates with the identity linking system:

  1. Verification Phase: User verifies email ownership via OTP → receives identity token
  2. Linking Phase: User links identity token to account → email added to AlternateEmails array
  3. Storage Update: User record updated with optimistic locking to prevent race conditions

For complete flow details, see the Email Verification Documentation.

NATS Subjects

The OTP verification flow exposes the following NATS subjects:

  • lfx.auth-service.email_linking.send_verification - Initiates OTP verification flow
  • lfx.auth-service.email_linking.verify - Validates OTP and returns identity token
  • lfx.auth-service.user_identity.link - Links verified identity to user account

Known Limitations

This implementation is designed for local development convenience and carries trade-offs that make it unsuitable for production:

  • Sync runs only at startup. The sync engine compares NATS KV against Kubernetes ConfigMaps once when the auth-service starts. There is no continuous watch — changes made to user data between restarts are not automatically propagated to Authelia until the next service startup.

  • Every credential change restarts Authelia. User creation or password updates trigger a Kubernetes DaemonSet rolling restart. This introduces a brief authentication downtime window on each change and does not scale to environments with many concurrent user updates.

  • No distributed retry for optimistic concurrency conflicts. Identity link/unlink operations use NATS KV revision-based optimistic concurrency. A conflict error is returned to the caller with no automatic retry — acceptable for single-developer local use, not for concurrent multi-user traffic.

  • Identity tokens use a test signing key. The OTP verification flow generates internal ID tokens via jwt.GenerateSimpleTestIdentityTokenWithSubject, which uses an ephemeral in-process RSA key regenerated on each service restart. These tokens cannot be verified across service instances or restarts.

  • Single-instance assumption. The design assumes one auth-service instance managing one Authelia deployment. Running multiple auth-service replicas against the same NATS KV store would cause split-brain sync behaviour.

Security Considerations

  • User passwords are automatically generated and stored as bcrypt hashes in ConfigMaps
  • Plain text passwords are stored separately in Kubernetes Secrets for Authelia access
  • All password generation uses cryptographically secure random generation
  • Kubernetes RBAC controls access to ConfigMaps and Secrets

Development Usage

When running in local development mode with Authelia:

  1. Ensure Kubernetes cluster is available (local or remote)
  2. Deploy Authelia using the LFX v2 platform Helm charts: lfx-v2-helm/charts/lfx-platform/templates/authelia
  3. Configure the auth-service with proper Kubernetes credentials and resource names
  4. The service will automatically sync user data and restart Authelia when needed

Error Handling

The integration includes comprehensive error handling for:

  • Kubernetes API failures
  • NATS KV storage issues
  • Configuration validation errors
  • Sync operation failures

All errors are logged with appropriate context and returned as structured error types for proper handling by the calling application.