189 lines
4.8 KiB
Markdown
189 lines
4.8 KiB
Markdown
# Authentication Flow - BuySellService → Auth Service
|
|
|
|
## Overview
|
|
|
|
BuySellService **does NOT validate JWT tokens locally**. Instead, it calls the auth service API to validate and authorize every request.
|
|
|
|
## Flow Diagram
|
|
|
|
```
|
|
Android App → BuySellService → Auth Service → BuySellService → Response
|
|
| | | |
|
|
| | | |
|
|
[Token] [Extract Token] [Validate Token] [User Info]
|
|
| | | |
|
|
| | | |
|
|
└──────────────┴────────────────┴───────────────┘
|
|
```
|
|
|
|
## Detailed Flow
|
|
|
|
### 1. Request Arrives at BuySellService
|
|
|
|
**Android App sends:**
|
|
```
|
|
GET http://localhost:3200/users/user-123
|
|
Authorization: Bearer eyJhbGc...
|
|
```
|
|
|
|
### 2. BuySellService Middleware Chain
|
|
|
|
**Step 1: requestContext**
|
|
- Extracts IP, User-Agent, generates Request-ID
|
|
|
|
**Step 2: auditLogger**
|
|
- Attaches audit logger to request
|
|
|
|
**Step 3: jwtAuthenticate** ⭐ **CALLS AUTH SERVICE**
|
|
- Extracts token from `Authorization: Bearer <token>` header
|
|
- **Calls auth service**: `POST http://localhost:3000/auth/validate-token`
|
|
- **Request body**: `{ token: "eyJhbGc..." }`
|
|
- **Waits for response**
|
|
|
|
### 3. Auth Service Validates Token
|
|
|
|
**Auth Service receives:**
|
|
```json
|
|
POST /auth/validate-token
|
|
Body: { "token": "eyJhbGc..." }
|
|
```
|
|
|
|
**Auth Service validates:**
|
|
- ✅ Token signature (using JWT secret)
|
|
- ✅ Token expiry (`exp` claim)
|
|
- ✅ Issuer (`iss` claim)
|
|
- ✅ Audience (`aud` claim)
|
|
- ✅ Token version (checks database for logout-all-devices)
|
|
- ✅ User exists in database
|
|
|
|
**Auth Service responds (if valid):**
|
|
```json
|
|
{
|
|
"valid": true,
|
|
"payload": {
|
|
"sub": "user-123",
|
|
"role": "user",
|
|
"user_type": "seller",
|
|
"phone_number": "+919876543210",
|
|
"token_version": 1,
|
|
"high_assurance": false
|
|
}
|
|
}
|
|
```
|
|
|
|
**Auth Service responds (if invalid):**
|
|
```json
|
|
{
|
|
"valid": false,
|
|
"error": "Invalid or expired token"
|
|
}
|
|
```
|
|
|
|
### 4. BuySellService Receives Response
|
|
|
|
**If valid:**
|
|
- Extracts user info from `payload`
|
|
- Sets `req.user = { userId: "user-123", role: "user", ... }`
|
|
- Logs successful authentication
|
|
- Continues to next middleware
|
|
|
|
**If invalid:**
|
|
- Returns `401 Unauthorized`
|
|
- Logs failed authentication
|
|
- Stops request processing
|
|
|
|
### 5. Continue with Authorization
|
|
|
|
**After authentication:**
|
|
- Rate limiting (checks limits for userId)
|
|
- Coarse-grained authorization (checks role)
|
|
- Fine-grained authorization (checks resource ownership)
|
|
- Route handler (fetches user data)
|
|
- Response returned to Android app
|
|
|
|
## Code Flow
|
|
|
|
```javascript
|
|
// Backend/middleware/jwtAuthenticate.js
|
|
|
|
async function jwtAuthenticate(req, res, next) {
|
|
// 1. Extract token
|
|
const token = req.headers.authorization?.slice(7); // "Bearer <token>"
|
|
|
|
// 2. Call auth service
|
|
const response = await axios.post(
|
|
'http://localhost:3000/auth/validate-token',
|
|
{ token }
|
|
);
|
|
|
|
// 3. Check response
|
|
if (response.data.valid === true) {
|
|
// 4. Extract user info
|
|
req.user = {
|
|
userId: response.data.payload.sub,
|
|
role: response.data.payload.role,
|
|
// ... other fields
|
|
};
|
|
next(); // Continue to next middleware
|
|
} else {
|
|
// 5. Return 401 if invalid
|
|
return res.status(401).json({ error: 'Unauthorized' });
|
|
}
|
|
}
|
|
```
|
|
|
|
## Benefits
|
|
|
|
✅ **Centralized Validation**: All token validation logic in one place (auth service)
|
|
✅ **No Secret Sharing**: BuySellService doesn't need JWT secret
|
|
✅ **Token Version Checking**: Auth service checks database for logout-all-devices
|
|
✅ **Consistent**: All services use same validation logic
|
|
✅ **Easy Updates**: Update validation logic once in auth service
|
|
|
|
## Error Handling
|
|
|
|
**Auth Service Unavailable:**
|
|
- Returns `401 Unauthorized` with message: "Authentication service unavailable"
|
|
- Request is blocked (fail closed for security)
|
|
|
|
**Token Invalid:**
|
|
- Returns `401 Unauthorized` with error details
|
|
- Request is blocked
|
|
|
|
**Timeout:**
|
|
- 5 second timeout by default (configurable via `AUTH_SERVICE_TIMEOUT`)
|
|
- Returns `401 Unauthorized` if timeout exceeded
|
|
|
|
## Configuration
|
|
|
|
**Required Environment Variables:**
|
|
```env
|
|
AUTH_SERVICE_URL=http://localhost:3000
|
|
```
|
|
|
|
**Optional:**
|
|
```env
|
|
AUTH_SERVICE_TIMEOUT=5000 # milliseconds
|
|
```
|
|
|
|
## Testing
|
|
|
|
**Test auth service endpoint directly:**
|
|
```bash
|
|
# Valid token
|
|
curl -X POST http://localhost:3000/auth/validate-token \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"token":"your_valid_token_here"}'
|
|
|
|
# Response:
|
|
# {"valid":true,"payload":{"sub":"user-123","role":"user",...}}
|
|
```
|
|
|
|
**Test through BuySellService:**
|
|
```bash
|
|
curl -X GET http://localhost:3200/users/user-123 \
|
|
-H "Authorization: Bearer your_valid_token_here"
|
|
```
|
|
|
|
The BuySellService will call the auth service internally to validate the token.
|