Files
boc/AAMOS_AUTH_AUDIT_REPORT.md
Bernt (LandveX AI) 6bb355ce17 LINUS ROUND 3: Unified AAMOS auth system for BOC
- auth/auth.go: AAMOS-standard JWT claims (sub, org_id, roles, scopes)
- auth/auth_test.go: 18 tests (login, validation, middleware, roles)
- Compatible with ouroboros-identity RS256 tokens
- Middleware: Bearer validation + RequireRole
- AAMOS_AUTH_AUDIT_REPORT.md: Full auth audit across all systems
2026-07-14 16:33:54 +00:00

11 KiB

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 SSOaamos_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

{
  "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

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

┌─────────────────────────────────────────────────────────────┐
│                     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)

  1. BOC RS256 support — use same keypair as AAMOS
  2. Unified user DB — sync boc_users with prexo_users
  3. Google OAuth in quiXzoom — reuse AAMOS Google integration
  4. Token introspection endpoint — /api/auth/validate for all services

P2 — Medium (Next Sprint)

  1. MFA support — TOTP or SMS for admin accounts
  2. Password policies — min length, complexity, rotation
  3. Session management — view active sessions, revoke
  4. Audit logging — all auth events to SOC2 evidence

P3 — Low (Backlog)

  1. SCIM provisioning — auto-sync with Google Workspace
  2. SAML support — enterprise SSO
  3. 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)

# 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 <token>"
# → {"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.