2
Authentication-and-Security
kitos edited this page 2026-05-22 12:33:03 +00:00

Authentication and Security

This page covers the full authentication model, token management, API key usage, SSO configuration, and security controls in Aegis.


Authentication Methods

Aegis supports two authentication methods, checked in order:

After a successful login, the server sets:

Set-Cookie: aegis_token=<JWT>; HttpOnly; SameSite=Strict; Path=/; [Secure in prod]

The browser automatically sends this cookie on every request. This is the recommended method for the frontend.

2. Authorization: Bearer Header (API / Machine Use)

Authorization: Bearer <JWT>

Use this for:

  • API integrations
  • Scripts and CI/CD pipelines
  • When cookies are not available (e.g. cross-origin API calls)

JWT Token

Structure

The JWT payload contains:

{
  "sub": "user-uuid",
  "role": "red_lead",
  "jti": "unique-token-id",
  "exp": 1710000000,
  "iat": 1709996400
}

Expiry

Configurable via environment variable:

ACCESS_TOKEN_EXPIRE_MINUTES=480  # 8 hours default

Token Revocation (Blacklist)

On logout, the token's jti is stored in Redis with TTL = remaining token lifetime:

Redis key: blacklist:{jti}
Value: "1"
TTL: <seconds until token expiry>

Every authenticated request checks Redis for the jti. If found → 401 Unauthorized.


Setting Development Production
HttpOnly True True
SameSite Strict Strict
Secure False True
Path / /

SECURE_COOKIES environment variable:

  • auto (default): Secure=True when AEGIS_ENV=production
  • true: Always set Secure flag
  • false: Never set Secure flag (development only)

Password Policy

  • Minimum length: 12 characters
  • Must contain: uppercase, lowercase, digit, and special character
  • Enforced at account creation and password change
  • Passwords are hashed with bcrypt (work factor 12)

must_change_password

When an admin creates a user, must_change_password is set to True. Until the user changes their password, every endpoint returns:

{"detail": "PASSWORD_CHANGE_REQUIRED"}

with status 403, except:

  • GET /api/v1/auth/me
  • POST /api/v1/auth/change-password

Change password:

POST /api/v1/auth/change-password
Content-Type: application/json

{
  "current_password": "admin-set-password",
  "new_password": "MyNewSecurePassword123!"
}

API Keys

API keys provide long-lived credentials for machine-to-machine access without session management.

Creating a Key

POST /api/v1/api-keys
Content-Type: application/json

{
  "name": "CI Pipeline Key",
  "scope": "read",
  "expires_at": "2025-12-31T00:00:00Z"
}

Response includes the key value (only shown once):

{
  "id": "uuid",
  "name": "CI Pipeline Key",
  "key": "aegis_a1b2c3d4e5f6...",
  "scope": "read"
}

Using a Key

Authorization: Bearer aegis_a1b2c3d4e5f6...

Scopes

Scope Allowed HTTP methods
read GET, HEAD, OPTIONS only
write GET, POST, PATCH, PUT, DELETE
admin All + admin-only endpoints

A read scope key that attempts POST/PATCH/DELETE receives:

{"detail": "API key scope 'read' does not permit this operation"}

with status 403.

Revoking a Key

DELETE /api/v1/api-keys/{id}

SAML 2.0 SSO

Aegis supports SAML 2.0 for enterprise single sign-on (e.g. Azure AD, Okta, Ping).

Configuration (admin only)

PUT /api/v1/sso/config
Content-Type: application/json

{
  "enabled": true,
  "idp_entity_id": "https://idp.example.com",
  "idp_sso_url": "https://idp.example.com/sso/saml",
  "idp_certificate": "-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----",
  "sp_entity_id": "https://aegis.example.com",
  "attribute_mapping": {
    "email": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
    "role": "http://schemas.microsoft.com/ws/2008/06/identity/claims/groups"
  }
}

SSO Login Flow

  1. Browser visits GET /api/v1/sso/login → redirect to IdP
  2. User authenticates with IdP
  3. IdP POSTs SAML assertion to POST /api/v1/sso/callback
  4. Aegis validates assertion, finds/creates user, issues JWT cookie
  5. Browser redirected to frontend

Service Provider Metadata

GET /api/v1/sso/metadata

Returns XML metadata to register Aegis as a SAML service provider in your IdP.


Rate Limiting

  • Login endpoint: 5 attempts per minute per IP
  • Exceeded: 429 Too Many Requests
  • Implemented via Redis counters with TTL

SSRF Protection (Webhooks)

Webhook URLs are validated before saving. The following IP ranges are blocked:

Range Description
10.0.0.0/8 Private (Class A)
172.16.0.0/12 Private (Class B)
192.168.0.0/16 Private (Class C)
169.254.0.0/16 Link-local / APIPA
127.0.0.0/8 Loopback
::1/128 IPv6 loopback
fc00::/7 IPv6 unique local
0.0.0.0/8 Reserved
100.64.0.0/10 Shared address space

Attempting to create a webhook pointing to a private IP returns:

{"detail": "Webhook URL points to a private or reserved IP address (SSRF prevention)"}

Audit Logging

Every significant action is recorded in the audit_logs table (admin read-only):

Event type Logged when
auth.login Successful login
auth.logout Logout
auth.login_failed Failed login attempt
auth.password_changed Password change
user.created New user created
user.updated User updated
user.deleted User deleted
test.created New test created
test.state_changed Test state transition
test.validated Both leads approved
campaign.completed Campaign completed
permission.denied 403 on a protected endpoint

Query audit logs:

GET /api/v1/audit-logs?user_id=<id>&event_type=auth.login&from=2024-01-01&to=2024-12-31