Passenger Auth
Регистрация и авторизация пассажирских аккаунтов (consumer mobile / website).
Пассажирские аккаунты изолированы от staff-аккаунтов авиакомпании:
у них отдельное хранилище и собственный scope JWT (scope="passenger").
Это значит, что passenger-токен никогда не даёт доступа к
staff-API — даже при компрометации он бесполезен для операций
авиакомпании.
Base URL: https://api.nurcore.kg/api/v1/auth/passenger
Когда использовать
| Use case | Метод |
|---|---|
| Mobile/website регистрирует постоянного клиента | POST /register |
| Возвращающийся клиент входит по email/паролю | POST /login |
| Обновление access-токена | POST /refresh |
| Получение/редактирование профиля | GET /me, PATCH /me |
| Выход | POST /logout |
Гость (без аккаунта) бронирует через Booking API без регистрации — используется magic-link на email после оплаты.
POST /register
Создаёт новый passenger-аккаунт и сразу возвращает токены.
curl -X POST \
-H "X-API-Key: $PUBLISHABLE_KEY" \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "StrongPass123!",
"first_name": "John",
"last_name": "Doe",
"phone": "+996555000000"
}' \
"https://api.nurcore.kg/api/v1/auth/passenger/register"Request body:
| Поле | Тип | Required | Constraints |
|---|---|---|---|
email | string | ✓ | RFC 5322 email |
password | string | ✓ | 8-128 символов, требования validity ниже |
first_name | string | — | ≤100 символов |
last_name | string | — | ≤100 символов |
phone | string | — | ≤20 символов |
Требования к паролю:
- Минимум 8 символов
- Минимум одна заглавная и одна строчная буква
- Минимум одна цифра
- Минимум один спец-символ
Response 201:
{
"access_token": "eyJhbGciOi...",
"refresh_token": "eyJhbGciOi...",
"token_type": "bearer",
"expires_in": 900,
"passenger": {
"id": "uuid",
"email": "user@example.com",
"first_name": "John",
"last_name": "Doe",
"phone": "+996555000000",
"ffp_number": null,
"is_active": true,
"verified_at": null,
"created_at": "2026-05-11T10:00:00Z"
}
}Errors:
| Code | Причина |
|---|---|
| 400 | {detail: {password_errors: [...]}} — пароль не прошёл валидацию |
| 409 | Аккаунт с таким email уже существует |
POST /login
Вход существующего пассажира.
curl -X POST \
-H "X-API-Key: $PUBLISHABLE_KEY" \
-H "Content-Type: application/json" \
-d '{"email": "user@example.com", "password": "StrongPass123!"}' \
"https://api.nurcore.kg/api/v1/auth/passenger/login"Response 200: идентичен /register — пара токенов + профиль.
Brute-force protection:
- 5 неудачных попыток подряд → аккаунт заблокирован на 15 минут
- При успешном входе счётчик сбрасывается
- При попытке логина в заблокированный аккаунт →
423 Lockedсlocked_untilв ISO 8601
Errors:
| Code | Причина |
|---|---|
| 401 | Неверный email или пароль (не различаем — защита от user-enumeration) |
| 403 | Аккаунт деактивирован администратором |
| 423 | Заблокирован после 5 неудачных попыток (до locked_until) |
POST /refresh
Обновляет пару токенов через refresh-токен. Реализована ротация — старый refresh-токен немедленно отзывается.
curl -X POST \
-H "X-API-Key: $PUBLISHABLE_KEY" \
-H "Content-Type: application/json" \
-d '{"refresh_token": "eyJhbGciOi..."}' \
"https://api.nurcore.kg/api/v1/auth/passenger/refresh"Response 200: новые access_token + refresh_token.
Errors:
| Code | Причина |
|---|---|
| 401 | Недействительный, истёкший или уже отозванный refresh-токен |
Best practice (mobile): храните refresh_token в Keychain (iOS) /
EncryptedSharedPreferences (Android), а access_token — в памяти процесса.
GET /me
Возвращает профиль текущего пассажира.
curl -H "Authorization: Bearer $ACCESS_TOKEN" \
-H "X-API-Key: $PUBLISHABLE_KEY" \
"https://api.nurcore.kg/api/v1/auth/passenger/me"Response 200:
{
"id": "uuid",
"email": "user@example.com",
"first_name": "John",
"last_name": "Doe",
"phone": "+996555000000",
"ffp_number": "ASM12345",
"is_active": true,
"verified_at": "2026-04-15T08:30:00Z",
"created_at": "2026-01-10T12:00:00Z"
}PATCH /me
Обновляет профиль. Все поля опциональные — отправляйте только то, что меняется.
curl -X PATCH \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "X-API-Key: $PUBLISHABLE_KEY" \
-H "Content-Type: application/json" \
-d '{
"first_name": "Jonathan",
"preferences": {
"seat": "window",
"meal": "vegetarian",
"language": "ky",
"notifications": {"email": true, "push": true}
},
"documents": [{
"type": "passport",
"number": "AN1234567",
"expiry": "2030-05-01",
"country": "KGZ"
}]
}' \
"https://api.nurcore.kg/api/v1/auth/passenger/me"Request body (все поля optional):
| Поле | Тип | Назначение |
|---|---|---|
first_name | string | ≤100 |
last_name | string | ≤100 |
phone | string | ≤20 |
ffp_number | string | ≤20, уникален среди passengers |
documents | array | Документы (pre-fill при создании броней) |
preferences | object | seat / meal / language / notifications |
POST /logout
Отзывает указанный refresh-токен (удаляет session-запись).
curl -X POST \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "X-API-Key: $PUBLISHABLE_KEY" \
-H "Content-Type: application/json" \
-d '{"refresh_token": "eyJhbGciOi..."}' \
"https://api.nurcore.kg/api/v1/auth/passenger/logout"Response 204 (no content).
После logout локально очистите оба токена. Access-токен теоретически
ещё валиден до expires_in, но без refresh пользователь не сможет
получить новый.
JWT scope изоляция
Все 6 endpoints выдают/требуют JWT с scope="passenger". Этот scope
ограничен consumer-flow и не имеет доступа к staff-API
авиакомпании (внутренние операции check-in, обработка багажа,
weight & balance, партнёрские кошельки и т. д.).
Контроль на уровне ACL API Gateway — passenger-токен получит 403 на
любом staff-маршруте.
Связанные endpoints
- Device tokens —
/passenger/devices/*для регистрации FCM-токенов - Bookings — поиск своих броней через
customer_account_id - Magic-link flow — для гостевых броней