# Million Miles Authentik POC POC с кастомными формами `login/register`, где `Authentik` используется только как backend IdP. ## Что реализовано - `/login` — кастомная форма `Email / Password / Войти` - `/register` — кастомная форма `Full name / Email / Password / Confirm password` - `Authentik` используется как backend для пользователей, паролей и OIDC - наше приложение не хранит пароль и не хранит password hash - регистрация создаёт пользователя через `Authentik API` - login выполняется backend-to-backend через `Authentik flow/executor API` - после login backend получает `id_token` и `access_token` от `Authentik` - токены не хранятся в `localStorage` или `sessionStorage` - токены хранятся только в `HttpOnly` cookie с `SameSite=Lax` - `/me` возвращает claims из JWT после валидации токена на backend - `/dashboard` показывает claims из `/me`, без вывода raw JWT ## Что вне scope - sessions UI - consent UI - MFA devices UI - connected services - app passwords ## Порты Порты проброшены только на localhost: - frontend: `http://localhost:3000` - Authentik admin: `http://localhost:9000` ## Быстрый старт 1. Скопируй `.env.example` в `.env` 2. Для локального теста можно использовать такие значения: ```env AUTHENTIK_IMAGE=docker.io/authentik/server AUTHENTIK_TAG=2026.2.2 PG_DB=authentik PG_USER=authentik PG_PASS=authentik AUTHENTIK_SECRET_KEY=change-me-local-secret AUTHENTIK_BOOTSTRAP_EMAIL=admin@millionmiles.local AUTHENTIK_BOOTSTRAP_PASSWORD=admin123456 AUTHENTIK_BOOTSTRAP_TOKEN=local-bootstrap-token-change-me APP_URL=http://localhost:3000 AUTHENTIK_PUBLIC_URL=http://localhost:9000 AUTHENTIK_INTERNAL_URL=http://host.docker.internal:9000 AUTHENTIK_API_TOKEN=local-bootstrap-token-change-me AUTHENTIK_LOGIN_FLOW=mm-custom-authentication-flow OIDC_CLIENT_ID=mm-custom-frontend OIDC_CLIENT_SECRET=mm-custom-secret OIDC_ISSUER=http://localhost:9000/application/o/mm-custom-frontend/ OIDC_REDIRECT_URI=http://localhost:3000/auth/callback COOKIE_SECURE=false AUTH_DEBUG=false ``` 3. Запусти проект: ```bash docker compose up --build ``` Если нужен полностью чистый запуск: ```bash docker compose down -v docker compose up --build ``` ## Как зайти в админку Authentik Открой: ```txt http://localhost:9000 ``` Для локального теста из примера выше: ```txt email: admin@millionmiles.local password: admin123456 ``` ## Как это работает 1. Регистрация пользователя идёт через `Authentik API` 2. Пароль хранится в `Authentik`, не в нашем приложении 3. Login идёт через кастомную форму на нашем frontend 4. Backend проверяет логин/пароль через `Authentik flow/executor API` 5. После успешного login backend получает `id_token` и `access_token` от `Authentik` 6. Токены кладутся в `HttpOnly` cookie 7. `/me` читает токен из cookie, валидирует JWT и возвращает claims JSON 8. `/dashboard` показывает именно эти claims ## Что создаёт blueprint ```txt Flow: Million Miles Custom Authentication Slug: mm-custom-authentication-flow OAuth2/OIDC Provider: Million Miles Custom Frontend Application slug: mm-custom-frontend Client ID: mm-custom-frontend Client Secret: mm-custom-secret Redirect URI: http://localhost:3000/auth/callback ``` ## Ручная проверка 1. Открой `http://localhost:3000/register` 2. Зарегистрируй нового пользователя 3. Проверь, что форма требует: `Полное имя`, `Email`, `Пароль`, `Подтвердите пароль` 4. Проверь валидацию пароля: минимум 8 символов, одна заглавная, одна строчная, одна цифра 5. После регистрации перейди на `http://localhost:3000/login` 6. Войди через кастомную форму `email/password` 7. После входа открой `http://localhost:3000/me` 8. Убедись, что `/me` возвращает JSON с claims: `sub`, `email`, `name`, `preferred_username`, `username`, `iss`, `aud`, `iat`, `exp` 9. Открой `http://localhost:3000/dashboard` 10. Убедись, что dashboard показывает claims без raw JWT 11. Нажми `Выйти` и проверь, что `POST /logout` очищает cookie и возвращает на `/login` ## Что проверить в админке В Authentik admin можно проверить: ```txt Applications -> Applications -> Million Miles Applications -> Providers -> Million Miles Custom Frontend Flows and Stages -> Flows -> Million Miles Custom Authentication Directory -> Users ``` ## Важно - `COOKIE_SECURE=false` подходит только для локальной разработки по `http` - в production нужно использовать `COOKIE_SECURE=true`