Skip to content

Latest commit

 

History

History
92 lines (76 loc) · 4.3 KB

File metadata and controls

92 lines (76 loc) · 4.3 KB

Authentication System

The Authentication system provides secure service-to-service communication using RS256 JWT tokens.

Security Architecture

The system employs a Dual-Token Strategy:

  1. User Tokens: Issued to clients after login. Used to authorize mutations (POST, PUT, DELETE).
  2. Service Tokens: Signed by the API to authenticate itself against external services (e.g., DemoAPI).

Components

AuthVerticle

  • Purpose: Specialized verticle for JWT management and token issuance.
  • Responsibilities:
    • Key Normalization: Reconstructs RSA PEM keys from environment variables.
    • Event Bus Listener:
      • auth.token.get: Returns cached Service Token.
      • auth.token.issue: Generates new User Token (requires username).
    • Encapsulation: Owns the Rs256TokenService.

Rs256TokenService

  • Purpose: Manages the life-cycle of JWT tokens.
  • Key Features:
    • Service Token Generation: Signs tokens for service-to-service calls (cached, auto-refresh).
    • User Token Generation: Generates short-lived (15m) tokens for users.
    • Event Loop Protection: Uses vertx.executeBlocking for RSA signing to prevent blocking the event loop during high load (v4.3 Update).
    • Signing: Uses the loaded RSA Private Key.

MainVerticle

  • Purpose: Orchestrator and Key Provider.
  • Boot Flow:
    1. Retrieves RSA_PRIVATE_KEY and RSA_PUBLIC_KEY from environment.
    2. Deploys AuthVerticle (Private Key) for signing.
    3. Deploys HttpVerticle (Public Key) for local verification.

Secure Key Management (v4.4 Update)

To support containerized environments (Docker Swarm/Kubernetes), keys are loaded with a File-First Precedence:

  1. Checks for RSA_PRIVATE_KEY_FILE. If present, reads content from the mounted secret.
  2. Falls back to RSA_PRIVATE_KEY environment variable (Legacy/Dev). This ensures keys are never exposed as plain-text environment variables in production.

Authentication Flows

1. User Login Flow (POST /login)

The user authenticates to receive a token. The request is guarded by a dedicated Circuit Breaker (auth-login) to fail fast during overloads.

Observability: Login attempts are tracked via api_auth_attempts_total and breaker status via circuit_breaker_state{name="auth-login"}.

sequenceDiagram
    participant Client
    participant AuthCtrl as AuthController
    participant Val as SchemaValidator
    participant UserV as UserVerticle
    participant AuthV as AuthVerticle

    Client->>AuthCtrl: POST /login (LoginRequestDTO)
    AuthCtrl->>Val: validateLogin(body)
    Note over Val: Fail-Fast if invalid
    AuthCtrl->>AuthCtrl: Circuit Breaker Check
    AuthCtrl->>UserV: users.authenticate (LoginRequestDTO)
    Note over UserV: BCrypt Check (Blocking)
    UserV-->>AuthCtrl: User OK
    AuthCtrl->>AuthV: auth.token.issue
    Note over AuthV: Sign (executeBlocking)
    AuthV-->>AuthCtrl: JWT Token
    AuthCtrl-->>Client: 200 OK { token }
Loading

2. Service-to-Service Flow

The Reactive API authenticates itself to the Demo service for IP verification.

graph TD
    A[Reactive API] -->|1. Sign with Private Key| B[JWT Service Token]
    B -->|2. Bearer Header| C[Demo Service]
    C -->|3. Verify with Public Key| D{Authorized?}
    D -->|Yes| E[Allow Request]
    D -->|No| F[403 Forbidden]
Loading

Security Credentials

  • Algorithm: RS256 (RSA Signature with SHA-256).
  • Public Key: Located in the Demo service (JwtAuthenticationFilter.java).
  • Private Key: Located in the Reactive API (MainVerticle.java).

Integration in Web Layer

The VerificationHandler in the auth package uses the Event Bus to fetch tokens.

  • Request: Sends a message to auth.token.get.
  • Response: Receives a String token or a failure if the AuthVerticle is not configured.
  • V1 Routes: Skip authentication.
  • V3 Routes: Require token injection via the Authorization: Bearer <token> header.