# AUTH SPEC — DAARION.city Version: 1.0.0 --- ## 0. PURPOSE Цей документ описує базову систему автентифікації та авторизації для DAARION.city: - єдину модель користувача (`user_id`) для: - фронтенду (web/PWA), - Matrix/chat інтеграції, - MicroDAO governance, - Agents Service, - SecondMe. - механізм логіну/логауту (JWT access + refresh tokens), - базову RBAC (roles/permissions), - інтеграцію з існуючими сервісами (agents, microdao, city, secondme). Фокус цієї версії — **MVP-рівень**: - Password-based login (email + password) + готовність до OAuth (Google/Telegram) як наступний крок. - JWT токени (access + refresh). - Мінімальний набір ролей (`user`, `admin`, `agent-system`). - Захист основних API (governance, agents, secondme private). --- ## 1. ARCHITECTURE OVERVIEW ### 1.1. Auth Service Окремий сервіс `auth-service` (порт: **7020**): ```text [ Web / PWA / Matrix Gateway ] ↓ [ Auth Service (7020) ] ↓ [ PostgreSQL (auth tables) + Redis (sessions cache) ] ↓ [ JWT токени для інших сервісів ] ``` Auth Service: * реєструє користувачів, * зберігає хеші паролів, * видає JWT access/refresh токени, * перевіряє токени (через shared secret / public key), * надає API для інших сервісів (`/auth/introspect`). ### 1.2. Інші сервіси * `Agents Service`, `MicroDAO Service`, `SecondMe`, `City Service`: * отримують JWT у `Authorization: Bearer `, * валідують його (прямо або через Auth Service), * витягують `user_id`, `roles`, `scopes`. --- ## 2. DATA MODEL (PostgreSQL) ### 2.1. auth_users ```sql CREATE TABLE auth_users ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), email TEXT UNIQUE NOT NULL, password_hash TEXT NOT NULL, display_name TEXT, avatar_url TEXT, is_active BOOLEAN NOT NULL DEFAULT TRUE, is_admin BOOLEAN NOT NULL DEFAULT FALSE, locale TEXT DEFAULT 'uk', timezone TEXT DEFAULT 'Europe/Kyiv', meta JSONB DEFAULT '{}'::jsonb, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE INDEX ix_auth_users_email ON auth_users(email); ``` ### 2.2. auth_roles ```sql CREATE TABLE auth_roles ( id TEXT PRIMARY KEY, -- 'user' | 'admin' | 'agent-system' description TEXT ); INSERT INTO auth_roles (id, description) VALUES ('user', 'Regular user'), ('admin', 'Administrator'), ('agent-system', 'System agent'); ``` ### 2.3. auth_user_roles ```sql CREATE TABLE auth_user_roles ( user_id UUID NOT NULL REFERENCES auth_users(id) ON DELETE CASCADE, role_id TEXT NOT NULL REFERENCES auth_roles(id) ON DELETE CASCADE, PRIMARY KEY (user_id, role_id) ); ``` ### 2.4. auth_sessions ```sql CREATE TABLE auth_sessions ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES auth_users(id) ON DELETE CASCADE, user_agent TEXT, ip_address INET, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), expires_at TIMESTAMPTZ NOT NULL, revoked_at TIMESTAMPTZ, meta JSONB DEFAULT '{}'::jsonb ); CREATE INDEX ix_auth_sessions_user_id ON auth_sessions(user_id); CREATE INDEX ix_auth_sessions_expires ON auth_sessions(expires_at); ``` --- ## 3. TOKEN MODEL (JWT) ### 3.1. Access token * Формат: JWT (HS256). * Термін дії: 30 хвилин. * Payload: ```json { "sub": "user_id-uuid", "email": "user@example.com", "name": "Display Name", "roles": ["user"], "iat": 1732590000, "exp": 1732591800, "iss": "daarion-auth", "type": "access" } ``` ### 3.2. Refresh token * Формат: JWT (HS256). * Термін дії: 7 днів. * Payload: ```json { "sub": "user_id-uuid", "session_id": "session-uuid", "iat": 1732590000, "exp": 1733194800, "iss": "daarion-auth", "type": "refresh" } ``` --- ## 4. HTTP API (PUBLIC) Базовий шлях: `/api/auth/...`. ### 4.1. `POST /api/auth/register` **Request:** ```json { "email": "user@example.com", "password": "StrongPassword123", "display_name": "Alex" } ``` **Response (201):** ```json { "user_id": "uuid", "email": "user@example.com", "display_name": "Alex", "roles": ["user"] } ``` ### 4.2. `POST /api/auth/login` **Request:** ```json { "email": "user@example.com", "password": "StrongPassword123" } ``` **Response (200):** ```json { "access_token": "", "refresh_token": "", "token_type": "Bearer", "expires_in": 1800, "user": { "id": "uuid", "email": "user@example.com", "display_name": "Alex", "roles": ["user"] } } ``` ### 4.3. `POST /api/auth/refresh` **Request:** ```json { "refresh_token": "" } ``` **Response (200):** ```json { "access_token": "", "refresh_token": "", "token_type": "Bearer", "expires_in": 1800 } ``` ### 4.4. `POST /api/auth/logout` **Request:** ```json { "refresh_token": "" } ``` **Response:** ```json { "status": "ok" } ``` ### 4.5. `GET /api/auth/me` **Headers:** `Authorization: Bearer ` **Response (200):** ```json { "id": "uuid", "email": "user@example.com", "display_name": "Alex", "avatar_url": null, "roles": ["user"], "created_at": "2025-11-26T10:00:00Z" } ``` --- ## 5. HTTP API (INTERNAL) ### 5.1. `POST /api/auth/introspect` **Request:** ```json { "token": "" } ``` **Response (200, valid):** ```json { "active": true, "sub": "user_id-uuid", "email": "user@example.com", "roles": ["user"], "exp": 1732591800 } ``` **Response (200, invalid):** ```json { "active": false } ``` --- ## 6. HEALTHCHECK ### `GET /healthz` ```json { "status": "ok", "service": "auth-service", "version": "1.0.0" } ``` --- ## 7. CONFIGURATION (ENV) ```env AUTH_SERVICE_PORT=7020 AUTH_DB_DSN=postgresql://user:pass@postgres:5432/daarion AUTH_JWT_SECRET=your-very-long-secret-key-here AUTH_ACCESS_TOKEN_TTL=1800 AUTH_REFRESH_TOKEN_TTL=604800 AUTH_BCRYPT_ROUNDS=12 ``` --- ## 8. SECURITY NOTES * Паролі зберігати тільки як `bcrypt` hash. * JWT secret — довгий (мінімум 32 символи), збережений у `.env`. * Rate limiting для `/auth/login` (захист від brute force). * Логи не повинні писати паролі / токени. * HTTPS обов'язковий у production. --- ## 9. ROADMAP (POST-MVP) * OAuth2 / OIDC (Google, GitHub, Telegram). * WebAuthn / passkeys. * Device-level identity (звʼязок із Matrix devices). * On-chain identity (wallet + DID). * Email verification. * Password reset flow.