api-v1/AUTH_FLOW.md

4.8 KiB

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:

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):

{
  "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):

{
  "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

// 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:

AUTH_SERVICE_URL=http://localhost:3000

Optional:

AUTH_SERVICE_TIMEOUT=5000  # milliseconds

Testing

Test auth service endpoint directly:

# 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:

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.