auth-yes/Custom IAM Architecture Analysis v2.md

456 lines
22 KiB
Markdown

# Custom IAM Architecture Analysis v2.md
# Architectural Blueprint & Enterprise Implementation Roadmap: Decoupled Zero-Trust Identity Fabric
## 1. Executive Summary & Paradigm Evolution
The **Auth-Yes** Identity Fabric represents an ultra-low-friction, zero-trust
Identity and Access Management (IAM) system tailored for a high-velocity
microservice ecosystem. By rejecting the protocol bloat, redirect friction, and
configuration overhead of traditional OIDC/OAuth2 monoliths (e.g., Keycloak,
Authentik, Okta), Auth-Yes delivers microsecond-level stateful session
verification, phishing-proof WebAuthn passkey authentication, and cryptographic
workload identity.
### Key Refinements in v2 Architecture:
1. **Parent-Domain WebAuthn Scoping (`RP_ID=atyg.org`):**
- Eliminates the runtime complexity of Related Origin Requests (ROR) for the
primary domain ecosystem. All subdomains across `*.atyg.org` natively share
passkeys and session verification.
2. **Three-Tier Defense-in-Depth Model:**
- **Tier 1 (Global Edge Default):** Universal Traefik ForwardAuth perimeter
fallback protecting untagged/pre-release services.
- **Tier 2 (Edge Proxy Override):** ForwardAuth cookie validation for
legacy/third-party applications (Portainer, Grafana, admin consoles).
- **Tier 3 (Application Zero-Trust):** In-app Deno App SDK communicating over
high-throughput ConnectRPC / gRPC with SPIFFE/SPIRE mTLS identity and
granular application RBAC.
3. **Structured Token Provisioning Taxonomy:**
- Formalized 3-tier invite token architecture (Global Admin, Site-Scoped, and
Open/Pending) alongside Out-of-Band Account Recovery.
4. **Complete Administrative Console Roadmap:**
- Finalized UI specifications for Application Registration (`/admin/apps`),
Multi-Type Invite Provisioning (`/admin/invites`), and Granular User RBAC
Grant Management (`/admin/users/:id`).
---
## 2. Core Security Architecture & Defense-in-Depth Layering
Auth-Yes implements a strict multi-layered defense model ensuring that neither
network locality nor perimeter isolation is treated as an implicit proxy for
trust.
```
[ Public Internet / Client Browser ]
═══════════════════════════════════════════════════
TIER 1 & 2: Traefik Reverse Proxy & ForwardAuth Edge
═══════════════════════════════════════════════════
│ │
(Legacy/3rd-Party Apps) (Native Microservices)
[ Portainer / Web UIs ] [ ed-droid Web Edge ]
│ │
▼ ▼
ForwardAuth Interception Traefik TLS Ingress
GET /api/forward-auth PassTLSClientCert
(Valkey Cache Lookup) │
│ ▼
└──────────────────────────────► ═══════════════════════════
TIER 3: Zero-Trust App Mesh
ConnectRPC + SPIFFE / mTLS
═══════════════════════════
[ Auth-Yes Core Gateway ]
- Valkey Cache (L1/L2)
- PostgreSQL Store
- Default-Deny RBAC
```
### 2.1. Tier 1 — Global Edge Perimeter (Traefik ForwardAuth Default Fallback)
- **Objective:** Ensure zero accidental exposure of internal or pre-release
services.
- **Mechanism:** Traefik entrypoints (e.g., `websecure`) are configured with a
default ForwardAuth middleware. Any newly created container or untagged
service deployed on the internal network is protected by default.
- **Behavior:** Unauthenticated HTTP requests without a valid session cookie are
automatically redirected to `https://auth.atyg.org/login`.
### 2.2. Tier 2 — Edge Proxy Override (Third-Party & Legacy Applications)
- **Objective:** Secure off-the-shelf and legacy software (e.g., Portainer,
Grafana, PgAdmin) without requiring code modifications or custom SDK
integration.
- **Mechanism:** Traefik routers for these services explicitly route
authentication checks to `https://auth.atyg.org/api/forward-auth`.
- **Validation Flow:**
1. Client sends request with `session_id` cookie scoped to `.atyg.org`.
2. Traefik queries `auth-api:8000/api/forward-auth`.
3. Auth API checks Valkey in microseconds. If valid and account is active,
returns HTTP `200 OK` and injects upstream identity headers:
- `X-Forwarded-User: <username>`
- `X-Forwarded-User-Id: <uuid>`
4. If invalid or missing, returns HTTP `401 Unauthorized` or redirects to
login.
### 2.3. Tier 3 — Application-Level Zero-Trust (Deno App SDK + ConnectRPC + SPIFFE/mTLS)
- **Objective:** Provide high-throughput, microsecond-latency identity
validation with granular Role-Based Access Control (RBAC) for native
microservices.
- **Mechanism:**
- Subsidiary services import the logic-pure `@ed-droid/auth-yes/sdk`
middleware.
- The SDK intercepts requests, extracts the session token, and validates it
against the Auth Hub using **ConnectRPC / gRPC** over HTTP/2 multiplexed
connections.
- **Workload Cryptographic Attestation:** Workload identity is authenticated
via **SPIFFE/SPIRE x509 SVID certificates**. The Auth Hub validates the
calling application's SPIFFE ID (e.g.,
`spiffe://system.local/ed-droid-backend`) against the `apps` table.
- **Default-Deny Authorization:** Authentication (who the user is) is
decoupled from authorization (what app they can access). The Auth Hub
verifies that an explicit active record exists in the `grants` table
matching `(user_id, app_id)`.
---
## 3. WebAuthn Scope Mechanics: Parent Domain vs. Related Origin Requests (ROR)
### 3.1. Parent Domain Scoping (`RP_ID=atyg.org`)
In the W3C WebAuthn specification, a credential is bound to a Relying Party
Identifier (`RP_ID`).
- Under WebAuthn origin validation rules, an `RP_ID` can be set to any
**registrable domain suffix (eTLD+1)** of the origin.
- By setting:
```env
RP_ID=atyg.org
ORIGIN=https://auth.atyg.org
```
- **Result:** Any passkey created under `RP_ID=atyg.org` is cryptographically
valid and authenticatable across **all** subdomains under `*.atyg.org` (e.g.,
`auth.atyg.org`, `ed-droid.atyg.org`, `nas.atyg.org`).
- **Browser Compliance:** Supported natively across 100% of modern WebAuthn
implementations (Apple Safari/iOS, Google Chrome/Android, Windows Hello,
1Password, YubiKeys).
### 3.2. Session Cookie Cross-Subdomain Sharing
To support edge proxy interception (ForwardAuth Tier 1 & 2), the Auth Hub sets
the session cookie with domain wildcard scoping:
```ts
setCookie(c, "session_id", sessionId, {
domain: ".atyg.org",
httpOnly: true,
secure: true,
sameSite: "Lax",
expires: expiresAt,
});
```
This ensures the browser transmits the session cookie seamlessly to all
subdomains under `*.atyg.org`.
### 3.3. Future Scope: Related Origin Requests (ROR)
Dynamic Related Origin Requests via `https://auth.atyg.org/.well-known/webauthn`
are officially archived for **Phase 3 (Cross-TLD Expansion)**. ROR will only be
required when federating authentication across completely distinct root domains
(e.g., bridging `atyg.org` with `ed-droid.io` or `independent-domain.com`).
---
## 4. Identity Lifecycle & Token Provisioning Taxonomy
Auth-Yes implements a strict 3-tier invite provisioning architecture ensuring
mathematical control over user onboarding and access grants.
```
┌────────────────────────────────────────┐
│ Admin Onboarding Generator │
└───────────────────┬────────────────────┘
┌───────────────────────────────┼──────────────────────────────┐
▼ ▼ ▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Type 1: Global │ │ Type 2: Site │ │ Type 3: General │
│ Admin Invite │ │ Scoped Invite │ │ Open / Pending │
├──────────────────┤ ├──────────────────┤ ├──────────────────┤
│ app_id: NULL │ │ app_id: UUID │ │ app_id: NULL │
│ role: 'admin' │ │ role: 'user/adm' │ │ role: 'user' │
│ status: 'active' │ │ status: 'active' │ │ status: 'pending'│
└──────────────────┘ └──────────────────┘ └──────────────────┘
```
### 4.1. Type 1: Global Admin Onboarding Token
- **Purpose:** Initial system bootstrapping and administrative team onboarding.
- **Characteristics:** `app_id` is unbound (`NULL` or Management Console),
`role = 'admin'`.
- **Lifecycle:** User registers passkey $\rightarrow$ Account is set to `active`
$\rightarrow$ User is granted global administrative privileges across Auth-Yes
and all internal systems.
### 4.2. Type 2: Site-Scoped Onboarding Token
- **Purpose:** Controlled user onboarding for a specific subsidiary application
(e.g., `ed-droid`).
- **Characteristics:** `app_id` is locked to a specific application UUID,
`role = 'user'` (or application admin).
- **Lifecycle:** User registers passkey $\rightarrow$ Account is set to `active`
$\rightarrow$ System automatically inserts a grant record into
`grants (user_id, app_id, role)`. User can access the designated application
immediately, but is denied access to all other apps.
### 4.3. Type 3: General Open / Pending Registration Token
- **Purpose:** Broad community or team registration requiring manual
verification.
- **Characteristics:** `app_id: NULL`, `role = 'user'`, initial
`account_status = 'pending'`.
- **Lifecycle:** User registers passkey $\rightarrow$ Account is created in
`pending` state $\rightarrow$ User cannot log in until a Global Admin accesses
`/admin/users` and activates the account, optionally assigning specific
application grants.
### 4.4. Out-of-Band Single-Use Account Recovery Token
- **Purpose:** Lockout recovery when a user loses all registered hardware
passkeys.
- **Characteristics:** 24-hour time-limited cryptographic token linked to
existing `user_id`.
- **Lifecycle:** Admin generates recovery link in `/admin/users/:id`
$\rightarrow$ Transmitted out-of-band $\rightarrow$ User accesses
`/recovery?code=...` $\rightarrow$ User binds new hardware passkey
$\rightarrow$ Previous passkeys invalidated, existing UUID and application
grants preserved.
### 4.5. The RBAC Grant Lifecycle: Default-Deny, Assignment Matrix & RPC Payload
The identity fabric enforces strict decoupled authorization governed by three
continuous states:
1. **The Baseline (Default-Deny Zero-Trust):**
- When a user registers a passkey or when an admin provisions an account, the
user possesses **zero application access by default**.
- If an unassigned user attempts to authenticate to `ed-droid.atyg.org`, the
calling application SDK queries the central `AuthService.validateSession`
endpoint over ConnectRPC.
- The Auth Hub queries
`SELECT role FROM grants WHERE user_id = $1 AND app_id = $2`. Finding no
matching grant record, the server returns
`{ valid: false, uuid: "", scopes: [], error: "Validation failed" }`,
resulting in an instant `403 Forbidden: No explicitly granted roles`.
2. **The Assignment Matrix (Admin Console):**
- In `https://auth.atyg.org/admin`:
- Under **Applications** (`/admin/apps`), apps are registered (e.g.
`ed-droid`, SPIFFE ID `spiffe://system.local/ed-droid-backend`).
- Under **User Profile** (`/admin/users/:id`), the administrator views the
user's active permissions matrix.
- To grant access to a user (e.g., your nephew), the administrator selects
`ed-droid` from the app selector, selects a role (`viewer`, `operator`,
`editor`, `admin`), and clicks **Grant Access** (or checks the matrix
toggle).
- An atomic row is written to `grants (user_id, app_id, role)`.
3. **The Payload & Runtime Authorization:**
- The next time the user makes a request to `ed-droid`, the Deno App SDK
intercepts the session token and validates it via ConnectRPC over internal
mTLS.
- The Auth Hub validates the session in Valkey, retrieves the active grant
for `ed-droid`, and returns the cryptographic payload:
```json
{
"valid": true,
"uuid": "edfa8a54-66c5-4444-9e38-becfc5aa6463",
"scopes": ["viewer"]
}
```
- The Deno App SDK middleware injects
`c.set("user", { uuid, scopes: ["viewer"] })` into the application context,
allowing `ed-droid` to render the exact UI views and API actions permitted
for a `viewer`.
---
## 5. PostgreSQL Central Identity Schema Reference
```sql
-- Central Users Table
CREATE TABLE IF NOT EXISTS users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
username TEXT UNIQUE NOT NULL,
display_name TEXT,
account_status TEXT DEFAULT 'pending' CHECK (account_status IN ('active', 'pending', 'suspended')),
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- Registered Applications / Sites Table
CREATE TABLE IF NOT EXISTS apps (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
spiffe_id TEXT UNIQUE NOT NULL,
description TEXT,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Granular Application RBAC Grants Table
CREATE TABLE IF NOT EXISTS grants (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
app_id UUID NOT NULL REFERENCES apps(id) ON DELETE CASCADE,
role TEXT NOT NULL DEFAULT 'user',
created_at TIMESTAMPTZ DEFAULT NOW(),
UNIQUE(user_id, app_id)
);
-- Onboarding & Invitation Tokens Table
CREATE TABLE IF NOT EXISTS invites (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
code TEXT UNIQUE NOT NULL,
app_id UUID REFERENCES apps(id) ON DELETE CASCADE,
role TEXT NOT NULL DEFAULT 'user',
used_by UUID REFERENCES users(id) ON DELETE SET NULL,
expires_at TIMESTAMPTZ NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW(),
used_at TIMESTAMPTZ
);
-- Hardware Passkeys Table
CREATE TABLE IF NOT EXISTS passkeys (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
credential_id TEXT UNIQUE NOT NULL,
public_key TEXT NOT NULL,
counter BIGINT NOT NULL DEFAULT 0,
aaguid TEXT,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Active User Sessions Table
CREATE TABLE IF NOT EXISTS sessions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
created_at TIMESTAMPTZ DEFAULT NOW(),
expires_at TIMESTAMPTZ NOT NULL
);
-- Security Audit Records Table
CREATE TABLE IF NOT EXISTS audit_records (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id) ON DELETE SET NULL,
action TEXT NOT NULL,
resource TEXT,
details JSONB,
ip_address TEXT,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Enterprise Hardware AAGUID Allowlist Table
CREATE TABLE IF NOT EXISTS aaguid_allowlist (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
aaguid TEXT UNIQUE NOT NULL,
description TEXT NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW()
);
```
---
## 6. Administrative UI Implementation Specifications
The Auth-Yes Admin Console is built using server-rendered Deno Hono JSX
components executing direct database queries with zero intermediate loopback
latency.
### 6.1. Navigation Architecture (`AuthenticatedLayout.tsx` & `AdminLayout.tsx`)
```
[ Identity Provider Navbar ]
├── User Dashboard (/dashboard)
├── Active Sessions (/dashboard/sessions)
├── Registered Passkeys (/dashboard/passkeys)
└── [ ADMIN CONSOLE ] (Rendered if isAdmin = true)
├── User Directory (/admin/users)
├── Application Registry (/admin/apps)
├── Invite Tokens (/admin/invites)
├── AAGUID Allow-List (/admin/aaguid)
└── Security Audit Logs (/admin/audit-logs)
```
### 6.2. Page Specifications & Actions
#### 1. User Directory (`/admin/users`)
- **Features:**
- Tabular list of all registered users (`username`, `display_name`,
`account_status`, `created_at`, `grant_count`).
- Status mutation buttons: _Activate_, _Suspend_, _Re-Activate_.
- Link to detailed User Management profile (`/admin/users/:id`).
#### 2. User Profile & RBAC Grant Manager (`/admin/users/:id`)
- **Features:**
- **Account Recovery:** Single-click _Generate 24h Out-of-Band Recovery Link_.
- **Active Sessions:** List active sessions with individual and _Revoke All_
actions.
- **Registered Hardware Tokens:** List registered passkeys (`credential_id`,
`counter`, `created_at`) with _Delete Device_ action.
- **Application Access Grants (New in v2):**
- Matrix of currently assigned application access (`App Name`, `Role`,
`Granted At`).
- _Grant Access_ dropdown selector (`App`, `Role: user | admin`) to attach
new app permissions.
- _Revoke Access_ button to remove application-specific access.
#### 3. Application Registry (`/admin/apps`)
- **Features:**
- Table of all registered internal applications (`name`, `spiffe_id`,
`description`, `active_users_count`).
- _Register New Application_ form:
- `App Name` (e.g., "Elite Dangerous Streaming Hub")
- `SPIFFE ID` (e.g., `spiffe://system.local/ed-droid-backend`)
- `Description`
- _Delete Application_ action (with confirmation modal preventing accidental
lockout).
#### 4. Invite & Onboarding Token Manager (`/admin/invites`)
- **Features:**
- **Token Generation Modal/Form:**
- **Token Type Selector:**
1. _Global Admin Token_ (Pre-configures `role: 'admin'`, `app: NULL`)
2. _Site-Scoped Token_ (Displays App dropdown selector + Role selector)
3. _Open/Pending User Token_ (Pre-configures `role: 'user'`, `app: NULL`,
creates pending user)
- **Expiration Bounds:** 1 to 30 days (default: 7 days).
- **Custom Invite Code (Optional):** Auto-generates cryptographically random
code if left blank.
- **Live Invites Ledger:**
- Table displaying `Code`, `Type / Scope`, `Target App`, `Role`,
`Expires At`, `Status (Active / Used / Expired)`.
- Single-click _Copy Registration URL_ button
(`https://auth.atyg.org/register?code=...`).
- _Revoke Invite_ action.
---
## 7. Implementation Roadmap & Execution Checklist
| Phase | Milestone | Scope / Deliverables | Status |
| :---------- | :----------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :------------------ |
| **Phase 1** | **Core Identity & Passkey Engine** | - WebAuthn challenge & verification engine<br>- PostgreSQL schema auto-initialization<br>- Valkey session cache & instant revocation<br>- Direct SSR database rendering (zero-loopback)<br>- Hybrid hardware/software passkey support | **COMPLETED** |
| **Phase 2** | **Zero-Trust App Mesh (Backend)** | - ConnectRPC / gRPC transport<br>- SPIFFE/SPIRE mTLS client certificate validation<br>- Default-deny RBAC grant verification<br>- ForwardAuth `/api/forward-auth` endpoint | **COMPLETED** |
| **Phase 3** | **Admin Console UI Views (Current)** | - `/admin/apps` Application Registry UI<br>- `/admin/invites` Multi-Type Token Provisioning UI<br>- `/admin/users/:id` App RBAC Grant Manager UI<br>- Domain wildcard cookie (`.atyg.org`) deployment | **READY FOR BUILD** |
| **Phase 4** | **Edge Hardening & Future Scoping** | - Traefik Tier 1 global ForwardAuth fallback configuration<br>- Traefik Tier 2 ForwardAuth container routing<br>- Related Origin Requests (`/.well-known/webauthn`) for external TLDs | **FUTURE** |