Files
FastCheck/BACKEND_IMPLEMENTATION.md
sdarbinyan 34f6c80e57 fixed rout
2026-01-23 00:53:35 +04:00

11 KiB

FastCheck Backend Implementation Guide

QR Code Authentication Flow

Overview

The frontend displays a QR code that contains a session ID. When a user scans this QR code with the mobile app, the mobile app authenticates and links to that session. The frontend polls the backend every 2 seconds to check if the session has been authenticated.

Step-by-Step Implementation


1. Create WebSession (QR Code Generation)

Frontend Request:

GET https://api.fastcheck.store/websession
Headers: {
  "Content-Type": "application/json"
}

Backend Response:

{
  "sessionId": "1AF3781BF6B94604B771AEA1D44FA63A",
  "userId": "",
  "expires": "2026-01-19T10:50:00Z",
  "userSessionId": "",
  "Status": false
}

Backend Implementation:

// Example Node.js/Express
app.get('/websession', (req, res) => {
  // Generate unique session ID (UUID or similar)
  const sessionId = generateUUID(); // e.g., "1AF3781BF6B94604B771AEA1D44FA63A"
  
  // Set expiration time (e.g., 5 minutes from now)
  const expires = new Date(Date.now() + 5 * 60 * 1000).toISOString();
  
  // Store session in database or cache (Redis recommended)
  await sessionStore.create({
    sessionId: sessionId,
    userId: null,
    userSessionId: null,
    status: false,
    expiresAt: expires,
    createdAt: new Date()
  });
  
  // Return session data
  res.json({
    sessionId: sessionId,
    userId: "",
    expires: expires,
    userSessionId: "",
    Status: false
  });
});

What Frontend Does:

// Frontend generates QR code data from session ID
const qrData = `fastcheck://login?session=${sessionId}`;
// Example: "fastcheck://login?session=1AF3781BF6B94604B771AEA1D44FA63A"

QR Code Contains: Deep link URL with session ID

  • Format: fastcheck://login?session={sessionId}
  • Mobile app will parse this URL and extract the sessionId
  • Mobile app will then authenticate and update this session

2. Check WebSession Status (Polling)

Frontend Request (Every 2 seconds):

GET https://api.fastcheck.store/websession/1AF3781BF6B94604B771AEA1D44FA63A
Headers: {
  "Content-Type": "application/json"
}

Backend Response (Not Authenticated Yet):

{
  "sessionId": "1AF3781BF6B94604B771AEA1D44FA63A",
  "userId": "",
  "expires": "2026-01-19T10:50:00Z",
  "userSessionId": "",
  "Status": false
}

Backend Response (Authenticated):

{
  "sessionId": "1AF3781BF6B94604B771AEA1D44FA63A",
  "userId": "kHaAe9roaC2uq63AKGE/8+Ti/t/iFro68QhEZ1dRGLo",
  "expires": "2026-01-19T12:00:00Z",
  "userSessionId": "8A94EFEFD003426A9B456C48CAC99BE6",
  "Status": true
}

Backend Implementation:

app.get('/websession/:sessionId', async (req, res) => {
  const { sessionId } = req.params;
  
  // Retrieve session from database/cache
  const session = await sessionStore.get(sessionId);
  
  if (!session) {
    return res.status(404).json({ message: "Session not found" });
  }
  
  // Check if session expired
  if (new Date() > new Date(session.expiresAt)) {
    await sessionStore.delete(sessionId);
    return res.status(404).json({ message: "Session expired" });
  }
  
  // Return session status
  res.json({
    sessionId: session.sessionId,
    userId: session.userId || "",
    expires: session.expiresAt,
    userSessionId: session.userSessionId || "",
    Status: session.status || false
  });
});

3. Mobile App Authenticates Session

This is what the MOBILE APP does (not the web frontend):

Mobile App Flow:

  1. User scans QR code: fastcheck://login?session=1AF3781BF6B94604B771AEA1D44FA63A
  2. Mobile app extracts sessionId: 1AF3781BF6B94604B771AEA1D44FA63A
  3. Mobile app authenticates user (PIN, biometrics, etc.)
  4. Mobile app sends authentication request to backend:
POST https://api.fastcheck.store/websession/authenticate
Headers: {
  "Authorization": "Bearer {mobile_app_token}",
  "Content-Type": "application/json"
}
Body: {
  "sessionId": "1AF3781BF6B94604B771AEA1D44FA63A",
  "userId": "kHaAe9roaC2uq63AKGE/8+Ti/t/iFro68QhEZ1dRGLo"
}

Backend Implementation:

app.post('/websession/authenticate', authenticateMobileApp, async (req, res) => {
  const { sessionId, userId } = req.body;
  const mobileUserId = req.user.id; // From mobile app authentication
  
  // Verify the mobile user matches
  if (userId !== mobileUserId) {
    return res.status(403).json({ message: "Unauthorized" });
  }
  
  // Update session with user information
  const userSessionId = generateUUID();
  await sessionStore.update(sessionId, {
    userId: userId,
    userSessionId: userSessionId,
    status: true,
    authenticatedAt: new Date()
  });
  
  res.json({ message: "Session authenticated" });
});

4. Logout (Delete Session)

Frontend Request:

DELETE https://api.fastcheck.store/websession/1AF3781BF6B94604B771AEA1D44FA63A
Headers: {
  "Authorization": "{\"sessionID\": \"1AF3781BF6B94604B771AEA1D44FA63A\"}",
  "Content-Type": "application/json"
}

Backend Implementation:

app.delete('/websession/:sessionId', async (req, res) => {
  const { sessionId } = req.params;
  
  // Delete session from database/cache
  await sessionStore.delete(sessionId);
  
  res.json({ message: "Session deleted" });
});

5. Authenticated API Requests

After login, all API requests include the sessionId in the Authorization header:

Frontend Request:

POST https://api.fastcheck.store/fastcheck
Headers: {
  "Authorization": "{\"sessionID\": \"1AF3781BF6B94604B771AEA1D44FA63A\"}",
  "Content-Type": "application/json"
}
Body: {
  "amount": 150000,
  "currency": "RUB"
}

Backend Authentication Middleware:

// Middleware to verify session
const authenticateSession = async (req, res, next) => {
  try {
    // Parse Authorization header
    const authHeader = req.headers.authorization;
    if (!authHeader) {
      return res.status(401).json({ message: "not authorized" });
    }
    
    // Parse JSON from Authorization header
    const { sessionID } = JSON.parse(authHeader);
    
    // Verify session exists and is authenticated
    const session = await sessionStore.get(sessionID);
    
    if (!session || !session.status) {
      return res.status(401).json({ message: "not authorized" });
    }
    
    // Check if session expired
    if (new Date() > new Date(session.expiresAt)) {
      await sessionStore.delete(sessionID);
      return res.status(401).json({ message: "not authorized" });
    }
    
    // Attach user info to request
    req.user = {
      userId: session.userId,
      userSessionId: session.userSessionId,
      sessionId: sessionID
    };
    
    next();
  } catch (error) {
    return res.status(401).json({ message: "not authorized" });
  }
};

// Use middleware on protected routes
app.post('/fastcheck', authenticateSession, async (req, res) => {
  const { amount, currency } = req.body;
  const userId = req.user.userId;
  
  // Create FastCheck logic...
});

QR Code Data Format

What the QR Code Contains:

fastcheck://login?session=1AF3781BF6B94604B771AEA1D44FA63A

Format breakdown:

  • Scheme: fastcheck:// - Deep link scheme for mobile app
  • Path: login - Indicates this is a login QR code
  • Parameter: session={sessionId} - The web session ID

Frontend QR Code Implementation:

// In login.component.ts
const sessionResponse = await createWebSession();
const qrData = `fastcheck://login?session=${sessionResponse.sessionId}`;

// QR code component displays this as a QR image
<qrcode [qrdata]="qrData" [width]="250"></qrcode>

Database Schema Recommendations

WebSession Table:

CREATE TABLE web_sessions (
  session_id VARCHAR(64) PRIMARY KEY,
  user_id VARCHAR(255),
  user_session_id VARCHAR(64),
  status BOOLEAN DEFAULT FALSE,
  expires_at TIMESTAMP NOT NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  authenticated_at TIMESTAMP,
  INDEX idx_expires (expires_at),
  INDEX idx_status (status)
);

-- Auto-delete expired sessions
CREATE EVENT cleanup_expired_sessions
ON SCHEDULE EVERY 1 HOUR
DO
  DELETE FROM web_sessions WHERE expires_at < NOW();
// Redis structure
const sessionKey = `websession:${sessionId}`;
await redis.setex(sessionKey, 300, JSON.stringify({
  sessionId: sessionId,
  userId: userId,
  userSessionId: userSessionId,
  status: true
}));

Security Considerations

  1. Session Expiration: Sessions should expire after 5 minutes if not authenticated
  2. HTTPS Only: All communication must be over HTTPS
  3. CORS Configuration: Configure CORS to allow frontend domain
  4. Session Cleanup: Regularly clean up expired sessions
  5. Rate Limiting: Limit polling requests to prevent abuse
  6. Mobile App Authentication: Mobile app must authenticate before linking session

Testing the Flow

1. Test Session Creation:

curl -X GET https://api.fastcheck.store/websession

Expected: New session with Status: false

2. Test Polling:

curl -X GET https://api.fastcheck.store/websession/{sessionId}

Expected: Same session, Status: false (until mobile app authenticates)

3. Test Mobile Authentication (simulate):

curl -X POST https://api.fastcheck.store/websession/authenticate \
  -H "Authorization: Bearer {mobile_token}" \
  -H "Content-Type: application/json" \
  -d '{"sessionId": "{sessionId}", "userId": "{userId}"}'

Expected: Session updated with Status: true

4. Test Polling After Auth:

curl -X GET https://api.fastcheck.store/websession/{sessionId}

Expected: Session with Status: true, userId populated


Frontend Polling Implementation (Already Done)

// In auth.service.ts
startPolling(sessionId: string): Observable<WebSession> {
  return interval(2000).pipe(  // Poll every 2 seconds
    switchMap(() => this.checkWebSessionStatus(sessionId)),
    tap(session => {
      if (session.Status) {
        this.setAuthenticated(session);
      }
    }),
    takeWhile(session => !session.Status, true)  // Stop when authenticated
  );
}

Summary for Backend Team

Required Endpoints:

  1. GET /websession - Create session for QR
  2. GET /websession/:id - Check session status (polled)
  3. ⚠️ POST /websession/authenticate - Mobile app authenticates session (NEW)
  4. DELETE /websession/:id - Logout

Required Logic:

  • Generate unique session IDs
  • Store sessions with expiration
  • Mobile app updates session status
  • Web frontend polls until Status = true
  • All authenticated APIs verify session in Authorization header

QR Code Data:

  • Format: fastcheck://login?session={sessionId}
  • Mobile app parses and authenticates
  • Web polls until mobile authenticates