- Development:
http://localhost:3000 - Production: (To be configured)
The API uses JWT (JSON Web Tokens) for authentication. Tokens are stored in HTTP-only cookies and automatically sent with each request.
- User signs up or logs in
- Server sets
tokencookie with JWT - Client includes cookie in subsequent requests automatically
- Protected routes verify token via
jwtMiddleware
Create a new user account.
Example Request:
curl -X POST http://localhost:3000/api/v1/signup \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "securePassword123",
"confirmPassword": "securePassword123"
}'Request Body:
{
"email": "user@example.com",
"password": "securePassword123",
"confirmPassword": "securePassword123",
"solvedCtf": []
}Example Response (201 Created):
{
"id": "507f1f77bcf86cd799439011",
"email": "user@example.com",
"numberOfSolvedCtf": 0,
"solvedCtf": []
}Example Error Response (400 Bad Request):
{
"message": "Email already used"
}Error Responses:
400 Bad Request: Missing fields, email already used, passwords don't match500 Internal Server Error: Server error
Authenticate user and receive JWT token.
Example Request:
curl -X POST http://localhost:3000/api/v1/login \
-H "Content-Type: application/json" \
-c cookies.txt \
-d '{
"email": "user@example.com",
"password": "securePassword123"
}'Request Body:
{
"email": "user@example.com",
"password": "securePassword123"
}Example Response (200 OK):
{
"userWithoutPassword": {
"id": "507f1f77bcf86cd799439011",
"email": "user@example.com",
"numberOfSolvedCtf": 0,
"solvedCtf": []
}
}Note: Token is set as HTTP-only cookie automatically. Use -c cookies.txt with curl to save cookies.
Example Error Response (401 Unauthorized):
{
"message": "Invalid credentials"
}Error Responses:
400 Bad Request: Missing email or password401 Unauthorized: Invalid credentials
Logout user and clear authentication cookie.
Example Request:
curl -X POST http://localhost:3000/api/v1/logout \
-H "Content-Type: application/json" \
-b cookies.txtExample Response (200 OK):
{
"message": "Logout successful"
}Get list of all available CTF challenges.
Authentication: Not required
Example Request:
curl -X GET http://localhost:3000/api/v1/ctfsExample Response (200 OK):
[
{
"id": "507f1f77bcf86cd799439011",
"name": "SSRF-RACE",
"type": "WEB_EXPLOIT",
"description": "Who said education has to be expensive? This platform seems to handle enrollment and pricing automatically. Still, nothing is ever as perfect as it looks.",
"difficulty": "MID",
"hints": [
"Hint 1: The server talks to itself. What happens when you make it ask the right questions?",
"Hint 2: Speed beats logic. Sometimes clicking faster than the server can think pays off."
],
"resources": [],
"withSite": true
}
]Example Response (200 OK) - Empty:
[]Create a new CTF instance (launch containers for a challenge).
Authentication: Required
URL Parameters:
id: CTF challenge ID
Example Request:
curl -X POST http://localhost:3000/api/v1/ctfs/507f1f77bcf86cd799439011/instances \
-H "Content-Type: application/json" \
-b cookies.txtExample Response (200 OK):
{
"id": "507f1f77bcf86cd799439012",
"ctfId": "507f1f77bcf86cd799439011",
"userId": "507f1f77bcf86cd799439010",
"status": "RUNNING",
"url": "http://localhost:3500",
"expiresAt": "2024-01-01T12:00:00.000Z"
}Error Responses:
400 Bad Request: CTF has no site, validation error401 Unauthorized: Not authenticated404 Not Found: CTF not found409 Conflict: CTF already solved, or another instance is active500 Internal Server Error: Docker error, port allocation failed, database error
Business Rules:
- User can only have one active instance at a time
- Cannot start instance for already-solved CTF
- If PENDING instance exists for same CTF, setup is resumed
- If RUNNING instance exists for same CTF, it is returned immediately
Get current user's active CTF instance (if any).
Authentication: Required
Example Request:
curl -X GET http://localhost:3000/api/v1/ctfs/instances \
-b cookies.txtExample Response (200 OK) - Has Active Instance:
{
"success": true,
"instance": {
"id": "507f1f77bcf86cd799439012",
"ctfId": "507f1f77bcf86cd799439011",
"status": "RUNNING",
"url": "http://localhost:3500",
"expiresAt": "2024-01-01T12:00:00.000Z"
}
}Example Response (200 OK) - No Active Instance:
{
"success": true,
"instance": null
}Error Responses:
401 Unauthorized: Not authenticated500 Internal Server Error: Server error
Stop a running CTF instance.
Authentication: Required
URL Parameters:
id: CTF instance ID
Example Request:
curl -X PATCH http://localhost:3000/api/v1/ctfs/instances/507f1f77bcf86cd799439012 \
-H "Content-Type: application/json" \
-b cookies.txtExample Response (200 OK):
{
"success": true,
"message": "CTF instance stopped successfully"
}Example Response (200 OK) - Already Stopped:
{
"success": true,
"message": "CTF instance already stopped"
}Error Responses:
401 Unauthorized: Not authenticated404 Not Found: Instance not found or doesn't belong to user500 Internal Server Error: Server error
Submit a flag for a CTF challenge.
Authentication: Required
URL Parameters:
id: CTF challenge ID
Example Request:
curl -X PATCH http://localhost:3000/api/v1/ctfs/507f1f77bcf86cd799439011 \
-H "Content-Type: application/json" \
-b cookies.txt \
-d '{
"flag": "CTF{flag_1_abc123}"
}'Request Body:
{
"flag": "CTF{flag_1_abc123}"
}Example Response (200 OK) - Correct Flag:
{
"success": true,
"message": "Congratulations! You solved this CTF"
}Example Response (200 OK) - Already Solved:
{
"success": true,
"message": "Congratulations! You already solved this CTF"
}Example Error Response (400 Bad Request):
{
"message": "Wrong flag"
}Error Responses:
400 Bad Request: Missing flag, wrong flag401 Unauthorized: Not authenticated404 Not Found: CTF not found500 Internal Server Error: Database error
Note: Token is automatically refreshed after successful flag submission to update numberOfSolvedCtf in the JWT payload.
All error responses follow this format:
{
"message": "Error message describing what went wrong"
}For internal server errors (500), the message is always:
{
"message": "Internal Server"
}200 OK: Request successful201 Created: Resource created successfully400 Bad Request: Invalid request data401 Unauthorized: Authentication required or invalid404 Not Found: Resource not found409 Conflict: Resource conflict (e.g., already solved, active instance exists)500 Internal Server Error: Server error
Note: Rate limiting is currently NOT implemented. This is a security concern that should be addressed before production deployment.
Recommended rate limits:
- Authentication endpoints: 5 requests per 15 minutes per IP
- CTF instance creation: 3 requests per hour per user
- Flag submission: 10 requests per minute per user
- General API: 100 requests per minute per IP
Note: CORS (Cross-Origin Resource Sharing) is currently NOT configured. The frontend must be served from the same origin as the backend, or CORS middleware must be added.
Recommended CORS configuration:
{
origin: process.env.FRONTEND_URL || 'http://localhost:5173',
credentials: true
}