153 lines
5.4 KiB
Markdown
153 lines
5.4 KiB
Markdown
# 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`
|
||
|