Files

304 lines
11 KiB
Markdown
Raw Permalink Normal View History

# 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 <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.