Use admin-specific Telegram copy and define the missing credential API. Replace predictable bootstrap passwords with random one-time secrets.
103 lines
3.2 KiB
Markdown
103 lines
3.2 KiB
Markdown
# Admin credential authentication handoff
|
|
|
|
## Current production state
|
|
|
|
`admin.gorbushka.market` can authenticate through the existing Telegram
|
|
session flow. Login/password authentication is not implemented by the live
|
|
backend, so the frontend must not validate or embed administrator credentials.
|
|
|
|
The existing `/admin-login` Ed25519 page is also not production-ready because
|
|
the backend challenge/verify endpoints do not exist.
|
|
|
|
## Required backend API
|
|
|
|
Tenant identity comes only from nginx's trusted `X-Storefront-Host` header.
|
|
Never accept a tenant or marketplace identifier from the login request body.
|
|
|
|
### Create session
|
|
|
|
```http
|
|
POST /api/identity/v1/session
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"login": "gorbushka",
|
|
"password": "<secret>"
|
|
}
|
|
```
|
|
|
|
Success:
|
|
|
|
```json
|
|
{
|
|
"accessToken": "<short-lived JWT>",
|
|
"refreshToken": "<rotating opaque token>",
|
|
"expiresAt": "2026-08-21T04:00:00Z",
|
|
"mustChangePassword": true,
|
|
"user": {
|
|
"id": "<id>",
|
|
"login": "gorbushka",
|
|
"displayName": "Gorbushka administrator",
|
|
"roles": ["MARKETPLACE_ADMIN"],
|
|
"tenantId": "<tenant-id>"
|
|
}
|
|
}
|
|
```
|
|
|
|
Errors:
|
|
|
|
- `400` malformed request.
|
|
- `401 INVALID_CREDENTIALS` with one generic message for unknown login and
|
|
wrong password.
|
|
- `403 TENANT_DISABLED` or `TENANT_MISMATCH`.
|
|
- `429 RATE_LIMITED` with `Retry-After`.
|
|
|
|
### Session lifecycle
|
|
|
|
```http
|
|
POST /api/identity/v1/session/refresh
|
|
DELETE /api/identity/v1/session
|
|
POST /api/identity/v1/session/change-password
|
|
GET /api/identity/v1/session/permissions
|
|
```
|
|
|
|
`change-password` accepts `{ currentPassword, newPassword }`. While
|
|
`mustChangePassword` is true, every non-auth admin endpoint returns
|
|
`403 PASSWORD_CHANGE_REQUIRED`.
|
|
|
|
## Provisioning and security requirements
|
|
|
|
- Generate a random one-time bootstrap password. Do not use the documented
|
|
deterministic `{slug}2026$` pattern in production.
|
|
- Store only an Argon2id password hash with a unique salt.
|
|
- Never log passwords, refresh tokens, authorization headers, or session IDs.
|
|
- Rate-limit by tenant, login, and source IP; add exponential backoff.
|
|
- Rotate refresh tokens and revoke the full token family on reuse.
|
|
- Enforce tenant and role authorization on every admin endpoint. Angular
|
|
guards are UI only.
|
|
- Audit login success/failure, password change, refresh-token reuse, logout,
|
|
and lockout without recording secrets.
|
|
|
|
## Required nginx invariants
|
|
|
|
Backend nginx changes must preserve:
|
|
|
|
```nginx
|
|
proxy_set_header X-Storefront-Host $storefront_host;
|
|
proxy_set_header Origin "";
|
|
|
|
add_header Access-Control-Allow-Headers \
|
|
"Authorization, Content-Type, AdminWebSessionID, WebSessionID, Currency, X-Language, X-Region, X-Requested-With" always;
|
|
```
|
|
|
|
For `Origin: https://admin.gorbushka.market`, `$storefront_host` must be
|
|
`gorbushka.market`. The API upstream remains `https://127.0.0.1:445` unless
|
|
the backend team deliberately changes the listening address.
|
|
|
|
## Frontend follow-up after backend delivery
|
|
|
|
Add the credential form to the admin-only login shell, submit only over HTTPS,
|
|
store the returned admin session separately from customer auth, force the
|
|
password-change screen when requested, and keep Telegram as an optional
|
|
fallback. Do not expose a non-functional credential form before the API ships.
|