feat: 切换邮箱认证并重构前后端启动与门禁
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
# Session Auth Protocol (Frontend <-> Backend)
|
||||
|
||||
This protocol defines login, refresh, and logout contract for Eryao Flutter app.
|
||||
|
||||
Protocol verification status:
|
||||
|
||||
- Last audited against backend source: `backend/src/v1/auth/router.py`, `backend/src/v1/auth/schemas.py`, `backend/src/v1/router.py`
|
||||
- Frontend mapping source: `apps/lib/features/auth/data/apis/auth_api.dart`
|
||||
- Current status: aligned
|
||||
|
||||
## Base URL
|
||||
|
||||
- Runtime injected by Flutter `--dart-define=BACKEND_URL=...`
|
||||
- Fallback:
|
||||
- Android emulator: `http://10.0.2.2:5775`
|
||||
- Others: `http://localhost:5775`
|
||||
|
||||
## Transport
|
||||
|
||||
- Content type: `application/json`
|
||||
- Error format: RFC7807 with extension fields `code`, `params`
|
||||
|
||||
## Route audit (current backend)
|
||||
|
||||
From `backend/src/v1/auth/router.py`:
|
||||
|
||||
- `POST /auth/otp/send` (204)
|
||||
- `POST /auth/email-session` (200, `SessionResponse`)
|
||||
- `POST /auth/sessions/refresh` (200, `SessionResponse`)
|
||||
- `DELETE /auth/sessions` (204)
|
||||
|
||||
Gateway error codes from `backend/src/v1/auth/gateway.py`:
|
||||
|
||||
- `AUTH_SERVICE_UNAVAILABLE`
|
||||
- `AUTH_TOO_MANY_REQUESTS`
|
||||
- `AUTH_VERIFICATION_CODE_INVALID`
|
||||
- `AUTH_REFRESH_TOKEN_INVALID`
|
||||
- `AUTH_REFRESH_TOKEN_MISSING`
|
||||
|
||||
## Frontend route mapping
|
||||
|
||||
- Send OTP: `POST /api/v1/auth/otp/send`
|
||||
- Login with OTP: `POST /api/v1/auth/email-session`
|
||||
- Refresh session: `POST /api/v1/auth/sessions/refresh`
|
||||
- Logout: `DELETE /api/v1/auth/sessions`
|
||||
|
||||
## Payload contract
|
||||
|
||||
### Send OTP
|
||||
|
||||
Request:
|
||||
|
||||
```json
|
||||
{ "email": "user@example.com" }
|
||||
```
|
||||
|
||||
Validation (backend):
|
||||
|
||||
- `email` must match `SUPABASE_EMAIL_PATTERN`
|
||||
|
||||
Response: `204 No Content`
|
||||
|
||||
### Create session
|
||||
|
||||
Request:
|
||||
|
||||
```json
|
||||
{ "email": "user@example.com", "token": "123456" }
|
||||
```
|
||||
|
||||
Validation (backend):
|
||||
|
||||
- `email` must match `SUPABASE_EMAIL_PATTERN`
|
||||
- `token` must be exactly 6 chars
|
||||
|
||||
Response:
|
||||
|
||||
```json
|
||||
{
|
||||
"access_token": "...",
|
||||
"refresh_token": "...",
|
||||
"expires_in": 3600,
|
||||
"token_type": "bearer",
|
||||
"user": {
|
||||
"id": "uuid",
|
||||
"email": "user@example.com"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Refresh session
|
||||
|
||||
Request:
|
||||
|
||||
```json
|
||||
{ "refresh_token": "..." }
|
||||
```
|
||||
|
||||
Validation (backend):
|
||||
|
||||
- `refresh_token` min length: 1
|
||||
|
||||
Response: same as create session.
|
||||
|
||||
### Logout
|
||||
|
||||
Request:
|
||||
|
||||
```json
|
||||
{ "refresh_token": "..." }
|
||||
```
|
||||
|
||||
Validation (backend):
|
||||
|
||||
- `refresh_token` min length: 1
|
||||
|
||||
Response: `204 No Content`
|
||||
|
||||
## Global auth state requirements
|
||||
|
||||
- Auth must be managed by single global `AuthBloc` instance.
|
||||
- App startup must attempt refresh if refresh token exists.
|
||||
- On refresh failure (`401` + `AUTH_REFRESH_TOKEN_INVALID`), clear local session and route to login.
|
||||
- Login success must persist access token + refresh token + display email.
|
||||
- Logout must call backend route then clear local session.
|
||||
- For protected requests, when backend returns `401`, frontend network layer must trigger global auth invalidation callback (single chain), not feature-level token clearing.
|
||||
|
||||
## Login identity mode
|
||||
|
||||
- Current app version supports **email OTP login only**.
|
||||
- Phone registration/login is removed from frontend flow.
|
||||
@@ -0,0 +1,20 @@
|
||||
# HTTP Error Codes
|
||||
|
||||
This document is the source of truth for backend RFC7807 `code` values consumed by frontend.
|
||||
|
||||
## Auth
|
||||
|
||||
| code | status | meaning | frontend handling |
|
||||
|---|---:|---|---|
|
||||
| `AUTH_SERVICE_UNAVAILABLE` | 503 | Auth upstream unavailable | Show retry message and allow retry |
|
||||
| `AUTH_TOO_MANY_REQUESTS` | 429 | OTP request throttled | Show wait message |
|
||||
| `AUTH_VERIFICATION_CODE_INVALID` | 401 | Invalid OTP code | Prompt user to re-enter code |
|
||||
| `AUTH_REFRESH_TOKEN_INVALID` | 401 | Invalid/expired refresh token | Clear local session and return login |
|
||||
| `AUTH_REFRESH_TOKEN_MISSING` | 401 | Refresh token missing on logout | Treat as local logout and clear session |
|
||||
| `AUTH_USER_NOT_FOUND` | 404 | User not found | Show not-found message where applicable |
|
||||
|
||||
Compatibility strategy:
|
||||
|
||||
- Additive changes only for new codes.
|
||||
- Existing codes must keep semantic meaning.
|
||||
- Frontend must map by `code`, not by `detail` text.
|
||||
Reference in New Issue
Block a user