# AAMOS Auth Audit Report **Date:** 2026-07-14 **Auditor:** Bernt (AI Agent) **Scope:** All AAMOS authentication systems --- ## Executive Summary | System | Status | Auth Method | JWT Type | SSO | Production Ready | |--------|--------|-------------|----------|-----|------------------| | **AAMOS Admin v2** | ✅ Running | Cookie + Bearer | RS256 | Google One Tap | ⚠️ Partial | | **quiXzoom API** | ✅ Running | Bearer | RS256 | ❌ No | ⚠️ Partial | | **aamos-ledger** | ✅ Running | Bearer | RS256 | ❌ No | ⚠️ Partial | | **ouroboros-identity** | ❌ STOPPED | — | RS256 | ❌ No | ❌ No | | **BOC** | 🚧 Dev | Bearer | HS256 | ❌ No | ❌ No | **Critical Finding:** ouroboros-identity (the designated identity service) is **STOPPED**. All auth currently flows through `aamos-admin-v2` API gateway. --- ## 1. AAMOS Admin v2 (api/auth-routes.js) — PRIMARY AUTH SYSTEM **Port:** 443 (via API Gateway) **File:** `/opt/amos/api/auth-routes.js` ### What Works - ✅ **Local admin login** — hardcoded users (erik@aamos.systems, dev@hypbit.com) - ✅ **DB user login** — scrypt password verification against prexo_users / ouroboros_users - ✅ **Google One Tap OAuth** — credential verification via Google tokeninfo - ✅ **RS256 JWT signing** — uses `/opt/amos/data/keys/jwt-private.pem` - ✅ **Refresh tokens** — 7-day refresh with denylist - ✅ **Password reset** — SMS (46elks) + email (Resend) with 6-digit codes - ✅ **Cookie-based SSO** — `aamos_token` + `aamos_refresh` cookies - ✅ **Role-based access** — group-ceo, group-cto, group-cfo, group-admin, admin, super_admin ### Auth Flow ``` User → POST /api/auth/login ├── Local admin bypass (hardcoded passwords) ├── DB check (scrypt hash in PostgreSQL) └── Google One Tap (credential from frontend) ↓ RS256 JWT signed with jwt-private.pem ↓ Cookie: aamos_token (24h) + aamos_refresh (7d) ↓ All subsequent requests: Bearer token OR cookie ``` ### JWT Claims Structure ```json { "sub": "user-uuid", "email": "user@example.com", "name": "User Name", "org": "org-uuid", "roles": ["admin", "group-admin"], "iss": "amos.aamos.systems", "exp": 1721030400, "iat": 1720944000 } ``` ### What's Broken / Risky - ❌ **Identity service STOPPED** — ouroboros-identity (port 3207) is inactive - ❌ **Hardcoded admin passwords** — LOCAL_ADMINS in plaintext - ❌ **No MFA** — SMS/email reset is single-factor - ❌ **No rate limiting** — brute force possible on /login - ❌ **HS256 fallback** — if RS256 keys missing, falls back to HS256 with fallback secret - ❌ **No token introspection** — /me just decodes, doesn't check revocation --- ## 2. quiXzoom Auth (/api/qz/auth) **Port:** 443 (via quixzoom-api.service) **File:** `/opt/amos/data/quixzoom-api/routes/auth.mjs` ### What Works - ✅ **Registration** — email + password + role (zoomer/orderer) - ✅ **Login** — bcrypt password verification - ✅ **Email verification** — SES welcome email with verify link - ✅ **RS256 JWT** — same keypair as AAMOS - ✅ **Token refresh** — /refresh endpoint ### Auth Flow ``` Zoomer → POST /api/qz/auth/register └── bcrypt hash → PostgreSQL quixzoom.users ↓ POST /api/qz/auth/login ↓ RS256 JWT (issuer: identity.quixzoom.com) ``` ### What's Broken / Risky - ❌ **Separate user DB** — quixzoom.users ≠ prexo_users ≠ ouroboros_users - ❌ **No SSO with AAMOS** — can't use AAMOS login for quiXzoom - ❌ **No Google OAuth** — only email/password - ❌ **No password reset** — missing /reset-request endpoint --- ## 3. aamos-ledger Auth **Port:** 3250 **File:** `/opt/amos/services/aamos-ledger/auth.mjs` ### What Works - ✅ **RS256 verification** — reads jwt-public.pem - ✅ **Role checking** — admin, accountant, viewer - ✅ **AAMOS token compatible** — accepts tokens from auth-routes.js ### What's Broken / Risky - ❌ **No own login** — relies on external auth service - ❌ **No user DB** — doesn't store users, just validates tokens --- ## 4. ouroboros-identity (STOPPED) **Port:** 3207 (INACTIVE) **File:** `/home/bernt/rust/ouroboros-identity/src/main.rs` ### What It Was Supposed To Do - RS256 JWT signing/verification - User management (prexo_users table) - Org/tenant isolation - Role-based access ### Why It's Stopped ```bash sudo systemctl status ouroboros-identity.service # Active: inactive (dead) ``` **Likely cause:** Rust binary crash or deployment issue. Needs investigation. --- ## 5. BOC Auth (In Development) **Port:** 9092 (planned) **Files:** `boc/backend/auth/auth.go`, `boc/backend/handlers/auth.go` ### Current State - ✅ **AAMOS-standard JWT claims** — sub, email, org_id, roles, scopes - ✅ **HS256 signing** — (should be RS256 for production) - ✅ **Middleware** — Bearer token validation - ✅ **Role middleware** — RequireRole("admin", "viewer") - ✅ **18 tests passing** — login, validation, middleware, roles ### What's Missing - ❌ **RS256 support** — only HS256, no keypair - ❌ **No Google OAuth** — no SSO integration - ❌ **No password reset** — missing /reset-request - ❌ **No refresh tokens** — single 24h token - ❌ **No cookie support** — only Bearer header - ❌ **Separate user DB** — boc_users table, not synced with AAMOS --- ## 6. Google OAuth Integration **Status:** ✅ Working in AAMOS Admin v2 ### Flow ``` Frontend (Google One Tap) └── credential (Google ID token) ↓ POST /api/auth/google ↓ Verify with https://oauth2.googleapis.com/tokeninfo ↓ Issue AAMOS RS256 JWT ``` ### Client ID ``` 168062155822-c6qvngkn5193ckipssoubgrvb0v4tn9r.apps.googleusercontent.com ``` ### What's Missing - ❌ **Not in quiXzoom** — Zoomers can't use Google login - ❌ **Not in BOC** — no Google OAuth integration - ❌ **No domain restriction** — any Google account can login --- ## Unified Auth Architecture (Recommended) ``` ┌─────────────────────────────────────────────────────────────┐ │ AAMOS IDENTITY HUB │ │ (ouroboros-identity) │ │ Port 3207 │ ├─────────────────────────────────────────────────────────────┤ │ • RS256 JWT signing/verification │ │ • User directory (unified across all services) │ │ • Google OAuth integration │ │ • Password reset (SMS + email) │ │ • Refresh token rotation │ │ • Role/scope management │ │ • Audit logging │ └─────────────────────────────────────────────────────────────┘ │ ┌───────────────────┼───────────────────┐ ▼ ▼ ▼ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ AAMOS Admin │ │ quiXzoom │ │ BOC │ │ (v2) │ │ (API) │ │ (9092) │ └─────────────┘ └─────────────┘ └─────────────┘ All services verify JWT via /api/auth/validate or local RS256 public key verification ``` --- ## Action Items (Priority Order) ### P0 — Critical (Do Today) 1. **Restart ouroboros-identity** — investigate why it's stopped 2. **Remove hardcoded passwords** — move to env vars or DB 3. **Enable rate limiting** — on /login, /reset-request ### P1 — High (This Week) 4. **BOC RS256 support** — use same keypair as AAMOS 5. **Unified user DB** — sync boc_users with prexo_users 6. **Google OAuth in quiXzoom** — reuse AAMOS Google integration 7. **Token introspection endpoint** — /api/auth/validate for all services ### P2 — Medium (Next Sprint) 8. **MFA support** — TOTP or SMS for admin accounts 9. **Password policies** — min length, complexity, rotation 10. **Session management** — view active sessions, revoke 11. **Audit logging** — all auth events to SOC2 evidence ### P3 — Low (Backlog) 12. **SCIM provisioning** — auto-sync with Google Workspace 13. **SAML support** — enterprise SSO 14. **Federated login** — BankID (Sweden), Vipps (Norway) --- ## Test Results ### BOC Auth Tests (18/18 passing) ``` ✅ TestNewService ✅ TestService_Login_Success ✅ TestService_Login_InvalidPassword ✅ TestService_Login_UserNotFound ✅ TestService_ValidateToken_Success ✅ TestService_ValidateToken_Expired ✅ TestService_ValidateToken_InvalidSignature ✅ TestService_ValidateToken_MissingSub ✅ TestMiddleware_ValidToken ✅ TestMiddleware_MissingHeader ✅ TestMiddleware_InvalidFormat ✅ TestMiddleware_InvalidToken ✅ TestRequireRole_Success ✅ TestRequireRole_Forbidden ✅ TestRequireRole_Unauthorized ✅ TestClaims_Valid ✅ TestFromContext_Missing ✅ TestWithClaims_RoundTrip ``` ### AAMOS Auth Endpoints (Manual Check) ```bash # Health check curl https://amos.aamos.systems/health # → {"ok":true} # Login (local admin) curl -X POST https://amos.aamos.systems/api/auth/login \ -H "Content-Type: application/json" \ -d '{"email":"erik@aamos.systems","password":"Erik1987"}' # → {"token":"eyJ...","refresh_token":"eyJ..."} # Me (with token) curl https://amos.aamos.systems/api/auth/me \ -H "Authorization: Bearer " # → {"user":{"sub":"...","email":"...","roles":["admin"]}} ``` --- ## Conclusion **Current State:** AAMOS has a working auth system in `aamos-admin-v2` with RS256 JWT, Google OAuth, and password reset. However, it's a monolithic auth implementation rather than a unified identity service. **Risk:** ouroboros-identity (the designated identity hub) is stopped. If aamos-admin-v2 fails, all auth stops. **Recommendation:** 1. Fix and restart ouroboros-identity 2. Migrate all services to use it as the single auth source 3. BOC should use RS256 + connect to the identity hub, not HS256 with local users **Auth Maturity: 5/10** — Functional but fragile, not unified.