very first commit
This commit is contained in:
528
BACKEND_API.md
Normal file
528
BACKEND_API.md
Normal file
@@ -0,0 +1,528 @@
|
||||
# Backend API Documentation - Auth Service
|
||||
|
||||
Complete API documentation for implementing the backend for the DX Authentication Service.
|
||||
|
||||
## 📋 Overview
|
||||
|
||||
This authentication service provides QR code-based authentication with comprehensive device tracking for all DX projects (Dexar, Novo Markets, FastCheck, BackOffice).
|
||||
|
||||
**Base URL:**
|
||||
- Development: `http://localhost:3000/api`
|
||||
- Production: `https://api.dx-projects.com/api`
|
||||
|
||||
---
|
||||
|
||||
## 🔐 Endpoints
|
||||
|
||||
### 1. Generate QR Code
|
||||
|
||||
Generate a new QR code session for authentication.
|
||||
|
||||
**Endpoint:** `POST /auth/qr/generate`
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"project": "dexar",
|
||||
"deviceInfo": {
|
||||
"deviceType": "desktop",
|
||||
"deviceOS": "windows",
|
||||
"context": "browser",
|
||||
"project": "dexar",
|
||||
"userAgent": "Mozilla/5.0...",
|
||||
"screenResolution": "1920x1080",
|
||||
"browserName": "Chrome",
|
||||
"browserVersion": "120.0.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Request Schema:**
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| `project` | string | Yes | Project ID: dexar, novo, fastcheck, backoffice |
|
||||
| `deviceInfo.deviceType` | string\|null | No | mobile, desktop, tablet |
|
||||
| `deviceInfo.deviceOS` | string\|null | No | android, ios, windows, macos, linux |
|
||||
| `deviceInfo.context` | string\|null | No | browser, application, telegram |
|
||||
| `deviceInfo.project` | string | Yes | Same as root project |
|
||||
| `deviceInfo.userAgent` | string | No | Browser user agent |
|
||||
| `deviceInfo.screenResolution` | string | No | e.g. "1920x1080" |
|
||||
| `deviceInfo.browserName` | string | No | Browser name |
|
||||
| `deviceInfo.browserVersion` | string | No | Browser version |
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{
|
||||
"sessionId": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"qrCode": "data:image/png;base64,iVBORw0KGgo...",
|
||||
"expiresAt": "2026-01-26T15:30:00.000Z",
|
||||
"expiresIn": 60
|
||||
}
|
||||
```
|
||||
|
||||
**QR Code Content Should Be:**
|
||||
```json
|
||||
{
|
||||
"sessionId": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"apiUrl": "https://api.dx-projects.com/api"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. Scan QR Code (Mobile Auth)
|
||||
|
||||
Scan and authenticate using a QR code session.
|
||||
|
||||
**Endpoint:** `POST /auth/qr/scan`
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"sessionId": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"deviceInfo": {
|
||||
"deviceType": "mobile",
|
||||
"deviceOS": "android",
|
||||
"context": "application",
|
||||
"project": "dexar",
|
||||
"userAgent": "Mozilla/5.0...",
|
||||
"screenResolution": "1080x2400",
|
||||
"browserName": "Chrome Mobile",
|
||||
"browserVersion": "120.0.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||||
"userId": "user-123",
|
||||
"expiresAt": "2026-01-27T14:30:00.000Z",
|
||||
"message": "Authentication successful",
|
||||
"userInfo": {
|
||||
"username": "john_doe",
|
||||
"email": "john@example.com",
|
||||
"role": "admin"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. Check Auth Status (Polling)
|
||||
|
||||
Check if a QR session has been authenticated. Used for polling every 2 seconds.
|
||||
|
||||
**Endpoint:** `GET /auth/qr/status/:sessionId`
|
||||
|
||||
**Response (Not Authenticated):** `200 OK`
|
||||
```json
|
||||
{
|
||||
"authenticated": false
|
||||
}
|
||||
```
|
||||
|
||||
**Response (Authenticated):** `200 OK`
|
||||
```json
|
||||
{
|
||||
"authenticated": true,
|
||||
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||||
"userId": "user-123",
|
||||
"expiresAt": "2026-01-27T14:30:00.000Z",
|
||||
"userInfo": {
|
||||
"username": "john_doe",
|
||||
"email": "john@example.com",
|
||||
"role": "admin"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. Traditional Login
|
||||
|
||||
Username/password authentication (alternative to QR).
|
||||
|
||||
**Endpoint:** `POST /auth/login`
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"username": "john_doe",
|
||||
"password": "secure_password_123",
|
||||
"deviceInfo": {
|
||||
"deviceType": "desktop",
|
||||
"deviceOS": "windows",
|
||||
"context": "browser",
|
||||
"project": "backoffice"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||||
"userId": "user-123",
|
||||
"expiresAt": "2026-01-27T14:30:00.000Z",
|
||||
"message": "Login successful",
|
||||
"userInfo": {
|
||||
"username": "john_doe",
|
||||
"email": "john@example.com",
|
||||
"role": "admin"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5. Validate Session
|
||||
|
||||
Validate an existing JWT token.
|
||||
|
||||
**Endpoint:** `POST /auth/validate`
|
||||
|
||||
**Headers:**
|
||||
```
|
||||
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
```
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"deviceInfo": {
|
||||
"deviceType": "desktop",
|
||||
"deviceOS": "windows",
|
||||
"context": "browser",
|
||||
"project": "dexar"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{
|
||||
"valid": true,
|
||||
"userId": "user-123",
|
||||
"expiresAt": "2026-01-27T14:30:00.000Z",
|
||||
"userInfo": {
|
||||
"username": "john_doe",
|
||||
"email": "john@example.com",
|
||||
"role": "admin"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 6. Logout
|
||||
|
||||
Invalidate current session.
|
||||
|
||||
**Endpoint:** `POST /auth/logout`
|
||||
|
||||
**Headers:**
|
||||
```
|
||||
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
```
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"deviceInfo": {
|
||||
"deviceType": "desktop",
|
||||
"deviceOS": "windows",
|
||||
"context": "browser",
|
||||
"project": "dexar"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Logged out successfully"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 💾 Database Schema
|
||||
|
||||
### Sessions Table
|
||||
```sql
|
||||
CREATE TABLE auth_sessions (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
session_id VARCHAR(255) UNIQUE NOT NULL,
|
||||
project VARCHAR(50) NOT NULL,
|
||||
device_type VARCHAR(20),
|
||||
device_os VARCHAR(20),
|
||||
context VARCHAR(20),
|
||||
user_agent TEXT,
|
||||
screen_resolution VARCHAR(20),
|
||||
browser_name VARCHAR(50),
|
||||
browser_version VARCHAR(20),
|
||||
authenticated BOOLEAN DEFAULT FALSE,
|
||||
user_id UUID,
|
||||
ip_address VARCHAR(45),
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
expires_at TIMESTAMP NOT NULL,
|
||||
authenticated_at TIMESTAMP,
|
||||
INDEX idx_session_id (session_id),
|
||||
INDEX idx_expires_at (expires_at),
|
||||
INDEX idx_user_id (user_id)
|
||||
);
|
||||
```
|
||||
|
||||
### Auth Logs Table
|
||||
```sql
|
||||
CREATE TABLE auth_logs (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID,
|
||||
project VARCHAR(50) NOT NULL,
|
||||
action VARCHAR(50) NOT NULL, -- login, logout, qr_scan, validate, qr_generate
|
||||
device_type VARCHAR(20),
|
||||
device_os VARCHAR(20),
|
||||
context VARCHAR(20),
|
||||
user_agent TEXT,
|
||||
ip_address VARCHAR(45),
|
||||
success BOOLEAN,
|
||||
error_message TEXT,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
INDEX idx_user_id (user_id),
|
||||
INDEX idx_created_at (created_at),
|
||||
INDEX idx_project (project)
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔒 Security Implementation
|
||||
|
||||
### Password Hashing
|
||||
```javascript
|
||||
const bcrypt = require('bcrypt');
|
||||
const saltRounds = 12;
|
||||
|
||||
// Hash password
|
||||
const hashedPassword = await bcrypt.hash(password, saltRounds);
|
||||
|
||||
// Verify password
|
||||
const isValid = await bcrypt.compare(password, hashedPassword);
|
||||
```
|
||||
|
||||
### JWT Token Generation
|
||||
```javascript
|
||||
const jwt = require('jsonwebtoken');
|
||||
|
||||
const token = jwt.sign(
|
||||
{
|
||||
userId: user.id,
|
||||
project: deviceInfo.project,
|
||||
deviceType: deviceInfo.deviceType
|
||||
},
|
||||
process.env.JWT_SECRET,
|
||||
{ expiresIn: '24h' }
|
||||
);
|
||||
```
|
||||
|
||||
### QR Code Generation
|
||||
```javascript
|
||||
const QRCode = require('qrcode');
|
||||
|
||||
const qrData = {
|
||||
sessionId: sessionId,
|
||||
apiUrl: process.env.API_URL
|
||||
};
|
||||
|
||||
const qrCodeImage = await QRCode.toDataURL(JSON.stringify(qrData));
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Implementation Flow
|
||||
|
||||
### QR Authentication Flow
|
||||
|
||||
1. **Desktop Browser Requests QR Code**
|
||||
- POST `/auth/qr/generate` with desktop device info
|
||||
- Backend creates session in database
|
||||
- Returns QR code image
|
||||
|
||||
2. **Frontend Starts Polling**
|
||||
- Every 2 seconds: GET `/auth/qr/status/:sessionId`
|
||||
- Backend returns `{ authenticated: false }`
|
||||
|
||||
3. **Mobile App Scans QR**
|
||||
- Parse QR code to get sessionId
|
||||
- POST `/auth/qr/scan` with mobile device info
|
||||
- Backend authenticates user
|
||||
- Backend updates session as authenticated
|
||||
- Returns JWT token
|
||||
|
||||
4. **Desktop Polling Detects Auth**
|
||||
- Next poll returns `{ authenticated: true, token: "..." }`
|
||||
- Frontend stores token
|
||||
- Redirects to application
|
||||
|
||||
---
|
||||
|
||||
## 📊 Device Info Tracking
|
||||
|
||||
### When to Send Device Info
|
||||
|
||||
**Send device info on:**
|
||||
- ✅ QR code generation (desktop)
|
||||
- ✅ QR code scanning (mobile)
|
||||
- ✅ Traditional login
|
||||
- ✅ Session validation
|
||||
- ✅ Logout
|
||||
|
||||
**Device Info Rules:**
|
||||
- All fields except `project` are optional
|
||||
- Send `null` for unknown values
|
||||
- Never fail request if device info is incomplete
|
||||
- Log all device info for analytics
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ Error Handling
|
||||
|
||||
### Error Response Format
|
||||
```json
|
||||
{
|
||||
"error": true,
|
||||
"message": "Invalid credentials",
|
||||
"code": "INVALID_CREDENTIALS"
|
||||
}
|
||||
```
|
||||
|
||||
### Error Codes
|
||||
| Code | HTTP Status | Description |
|
||||
|------|-------------|-------------|
|
||||
| `INVALID_PROJECT` | 400 | Unknown project identifier |
|
||||
| `INVALID_SESSION` | 401 | Session not found or expired |
|
||||
| `INVALID_CREDENTIALS` | 401 | Wrong username/password |
|
||||
| `INVALID_TOKEN` | 401 | JWT token invalid or expired |
|
||||
| `SESSION_EXPIRED` | 401 | QR code session expired |
|
||||
| `RATE_LIMIT_EXCEEDED` | 429 | Too many requests |
|
||||
| `SERVER_ERROR` | 500 | Internal server error |
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Testing
|
||||
|
||||
### Test Data
|
||||
|
||||
**Test User:**
|
||||
```json
|
||||
{
|
||||
"username": "test_user",
|
||||
"password": "Test123!",
|
||||
"email": "test@dx-projects.com",
|
||||
"role": "user"
|
||||
}
|
||||
```
|
||||
|
||||
### Example cURL Commands
|
||||
|
||||
**Generate QR Code:**
|
||||
```bash
|
||||
curl -X POST http://localhost:3000/api/auth/qr/generate \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"project": "dexar",
|
||||
"deviceInfo": {
|
||||
"deviceType": "desktop",
|
||||
"deviceOS": "windows",
|
||||
"context": "browser",
|
||||
"project": "dexar"
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
**Check Status:**
|
||||
```bash
|
||||
curl http://localhost:3000/api/auth/qr/status/{sessionId}
|
||||
```
|
||||
|
||||
**Login:**
|
||||
```bash
|
||||
curl -X POST http://localhost:3000/api/auth/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"username": "test_user",
|
||||
"password": "Test123!",
|
||||
"deviceInfo": {
|
||||
"deviceType": "desktop",
|
||||
"deviceOS": "windows",
|
||||
"context": "browser",
|
||||
"project": "dexar"
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📌 Important Notes
|
||||
|
||||
1. **QR Code Expiration:** 60 seconds (configurable)
|
||||
2. **JWT Token Expiration:** 24 hours (configurable)
|
||||
3. **Polling Interval:** 2 seconds
|
||||
4. **Rate Limiting:** 60 requests/minute per IP
|
||||
5. **CORS:** Allow all project domains
|
||||
6. **Session Cleanup:** Delete expired sessions every hour
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Environment Variables
|
||||
|
||||
```env
|
||||
# API Configuration
|
||||
PORT=3000
|
||||
API_URL=http://localhost:3000/api
|
||||
NODE_ENV=development
|
||||
|
||||
# JWT
|
||||
JWT_SECRET=your-super-secret-jwt-key-change-this
|
||||
JWT_EXPIRATION=24h
|
||||
|
||||
# Database
|
||||
DB_HOST=localhost
|
||||
DB_PORT=5432
|
||||
DB_NAME=dx_auth
|
||||
DB_USER=postgres
|
||||
DB_PASSWORD=your-password
|
||||
|
||||
# QR Code
|
||||
QR_EXPIRATION=60
|
||||
QR_SIZE=240
|
||||
|
||||
# CORS
|
||||
CORS_ORIGINS=http://localhost:4200,http://localhost:4300,http://localhost:4400
|
||||
|
||||
# Rate Limiting
|
||||
RATE_LIMIT_WINDOW=60000
|
||||
RATE_LIMIT_MAX_REQUESTS=60
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 Additional Resources
|
||||
|
||||
- **Frontend Integration:** See `HOW_TO_USE.md`
|
||||
- **Project Setup:** See `README.md`
|
||||
- **FastCheck APIs:** Reference similar implementation in FastCheck project
|
||||
|
||||
---
|
||||
|
||||
## 🆘 Support
|
||||
|
||||
For backend implementation questions:
|
||||
- Email: backend@dx-projects.com
|
||||
- Slack: #backend-auth
|
||||
- Documentation: https://docs.dx-projects.com/auth
|
||||
Reference in New Issue
Block a user