Authentication¶
MDU uses its own JWT-based authentication system with two login methods: Email OTP and Google OAuth.
Overview¶
- Access token: Short-lived JWT (HMAC-SHA256)
- Refresh token: Long-lived JWT for token renewal
- Storage:
localStoragekeysmdu_access_token,mdu_refresh_token,mdu_user - Header:
Authorization: Bearer <access_token>
Endpoints¶
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /api/auth/send-otp |
- | Send 6-digit OTP to email |
| POST | /api/auth/verify-otp |
- | Verify OTP, return JWT |
| GET | /api/auth/google |
- | Google OAuth redirect |
| GET | /api/auth/google/callback |
- | Google OAuth callback |
| POST | /api/auth/refresh |
- | Refresh access token |
| POST | /api/auth/logout |
Required | Invalidate refresh token |
Email OTP Flow¶
1. Send OTP¶
Response:
Rules:
- 6-digit numeric code
- 10-minute expiry
- Max 3 sends per 10 minutes per email
2. Verify OTP¶
POST /api/auth/verify-otp
Content-Type: application/json
{ "email": "user@example.com", "code": "123456" }
Response:
{
"access_token": "eyJhbGci...",
"refresh_token": "eyJhbGci...",
"user": { "id": "uuid", "email": "user@example.com", "name": "User" }
}
Google OAuth Flow¶
1. Redirect to Google¶
Redirects the user to Google's OAuth consent screen. The optional redirect parameter sets where to return after authentication.
2. Callback¶
Google redirects back to /api/auth/google/callback with an authorization code. The server exchanges it for user info, creates/updates the profile, generates JWT tokens, and redirects to the frontend with tokens in the URL hash.
Token Refresh¶
Response:
JWT Payload¶
Warning
The user ID is in payload.sub, NOT payload.userId. All middleware extracts req.userId = payload.sub.
Frontend Integration¶
// authService.ts
const token = localStorage.getItem('mdu_access_token');
// API calls
const response = await fetch('/api/generate-model', {
headers: { 'Authorization': `Bearer ${token}` }
});
// Token refresh on 401
if (response.status === 401) {
const newToken = await refreshToken();
// Retry request with new token
}
The getValidToken() helper in authService.ts handles JWT expiry checking and automatic refresh.
Logout¶
Clears the refresh token server-side. Frontend clears localStorage and dispatches mdu:auth:logout CustomEvent.