Skip to content

Auth Service

The Auth Service (auth_service) handles authentication, token management, and cryptographic operations for the FluxiQ SPB platform. It issues JWT tokens, manages refresh token rotation, and integrates with HSM for BACEN message signing.

Port: 4001

Responsibilities

  • Authenticate users via username/password credentials
  • Issue and validate JWT access tokens and refresh tokens
  • Manage token revocation and blacklisting
  • Provide mTLS certificate validation for inter-service communication
  • Integrate with HSM (Hardware Security Module) for BACEN digital signatures
  • Support multi-factor authentication (MFA) for privileged operations

Authentication Flow

Client                API Gateway            Auth Service          Database
  |                       |                       |                    |
  |  POST /auth/login     |                       |                    |
  |---------------------->|                       |                    |
  |                       |  Forward credentials  |                    |
  |                       |---------------------->|                    |
  |                       |                       |  Verify password   |
  |                       |                       |------------------>|
  |                       |                       |<------------------|
  |                       |                       |                    |
  |                       |                       |  Generate JWT +    |
  |                       |                       |  Refresh Token     |
  |                       |<----------------------|                    |
  |  { token, refresh }   |                       |                    |
  |<----------------------|                       |                    |

JWT Token Structure

Access tokens contain the following claims:

json
{
  "sub": "user-uuid",
  "iss": "fluxiq-spb",
  "aud": "fluxiq-spb-api",
  "exp": 1706000000,
  "iat": 1705996400,
  "tenant_id": "institution-uuid",
  "ispb": "12345678",
  "roles": ["operator", "treasury"],
  "permissions": [
    "transactions:read",
    "transactions:create",
    "str:balance:read",
    "settlements:read"
  ]
}

Token lifetimes:

Token TypeDefault TTLConfigurable
Access Token1 hourJWT_TTL env var
Refresh Token7 daysREFRESH_TTL env var
MFA Token5 minutesMFA_TTL env var

Configuration

elixir
# config/runtime.exs
config :auth_service, AuthService.Token,
  secret_key: System.fetch_env!("JWT_SECRET"),
  issuer: "fluxiq-spb",
  ttl: {System.get_env("JWT_TTL", "3600") |> String.to_integer(), :seconds},
  refresh_ttl: {System.get_env("REFRESH_TTL", "604800") |> String.to_integer(), :seconds}

config :auth_service, AuthService.HSM,
  provider: System.get_env("HSM_PROVIDER", "softHSM"),
  slot: System.get_env("HSM_SLOT", "0"),
  pin: System.get_env("HSM_PIN"),
  key_label: System.get_env("HSM_KEY_LABEL", "bacen-signing-key")

config :auth_service, AuthService.MFA,
  enabled: System.get_env("MFA_ENABLED", "true") == "true",
  issuer: "FluxiQ SPB",
  totp_period: 30

API Endpoints

Login

bash
POST /api/v1/auth/login
Content-Type: application/json

{
  "username": "operator@institution.com.br",
  "password": "secure-password"
}

# Response 200
{
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIs...",
    "refresh_token": "dGhpcyBpcyBhIHJlZn...",
    "expires_in": 3600,
    "token_type": "Bearer"
  }
}

Refresh Token

bash
POST /api/v1/auth/refresh
Content-Type: application/json

{
  "refresh_token": "dGhpcyBpcyBhIHJlZn..."
}

# Response 200
{
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIs...",
    "refresh_token": "bmV3IHJlZnJlc2ggdG9r...",
    "expires_in": 3600,
    "token_type": "Bearer"
  }
}

Refresh tokens follow a rotation policy: each use issues a new refresh token and invalidates the previous one. If a previously-used refresh token is presented, all tokens for that user session are revoked (replay detection).

Token Revocation

bash
POST /api/v1/auth/revoke
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Content-Type: application/json

{
  "token": "eyJhbGciOiJIUzI1NiIs..."
}

# Response 200
{
  "data": {"revoked": true}
}

MFA Setup

bash
POST /api/v1/auth/mfa/setup
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

# Response 200
{
  "data": {
    "secret": "JBSWY3DPEHPK3PXP",
    "qr_code_uri": "otpauth://totp/FluxiQ%20SPB:user@institution.com.br?secret=JBSWY3DPEHPK3PXP&issuer=FluxiQ%20SPB",
    "backup_codes": ["12345678", "23456789", "34567890", "45678901", "56789012"]
  }
}

MFA Verification

bash
POST /api/v1/auth/mfa/verify
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Content-Type: application/json

{
  "code": "123456"
}

# Response 200
{
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIs...",
    "mfa_verified": true
  }
}

Password Policy

Passwords must meet BACEN security requirements:

  • Minimum 12 characters
  • At least one uppercase letter, one lowercase letter, one digit, and one special character
  • Cannot match the last 12 passwords
  • Expires after 90 days
  • Account locks after 5 failed attempts (unlocks after 30 minutes)

HSM Integration

The auth_service manages HSM operations for BACEN message signing:

elixir
defmodule AuthService.HSM do
  @doc "Signs a BACEN XML message using the institution's private key"
  def sign_message(xml_content) do
    with {:ok, session} <- open_session(),
         {:ok, key} <- find_key(session, @key_label),
         {:ok, signature} <- sign(session, key, xml_content) do
      {:ok, Base.encode64(signature)}
    end
  end

  @doc "Verifies a BACEN response signature using BACEN's public certificate"
  def verify_signature(xml_content, signature, certificate) do
    :public_key.verify(xml_content, :sha256, signature, certificate)
  end
end

Health Check

bash
curl http://localhost:4001/health
# {"status": "ok", "hsm": "connected", "database": "connected"}

Plataforma de Integracao BACEN/SPB