API Authentication
This page covers the practical details of authenticating with the Tech Strategy Tool API, including login flow, session management, and CSRF requirements.
Overview
Section titled “Overview”The API uses cookie-based session authentication. After logging in, a session cookie is set on the browser and automatically included in subsequent requests.
Login Flow
Section titled “Login Flow”1. Authenticate
Section titled “1. Authenticate”curl -X POST https://localhost:5001/api/auth/login \ -H "Content-Type: application/json" \ -d '{"username": "editor", "password": "editor"}' \ -c cookies.txtOn success, the server sets the techstrat_session cookie:
Set-Cookie: techstrat_session=<session-id>; HttpOnly; Secure; SameSite=Strict; Path=/2. Make authenticated requests
Section titled “2. Make authenticated requests”Include the cookie on subsequent requests:
curl https://localhost:5001/api/teams \ -b cookies.txt3. Make mutating requests
Section titled “3. Make mutating requests”All POST, PUT, PATCH, and DELETE requests require the CSRF header:
curl -X POST https://localhost:5001/api/events \ -H "Content-Type: application/json" \ -H "X-CSRF-Token: 1" \ -b cookies.txt \ -d '{"eventType": "create_entity", "targetType": "Team", "data": {"id": "...", "name": "New Team", "color": "#3498db"}}'4. Logout
Section titled “4. Logout”curl -X POST https://localhost:5001/api/auth/logout \ -H "X-CSRF-Token: 1" \ -b cookies.txtCSRF Protection
Section titled “CSRF Protection”All mutating API requests must include the header:
X-CSRF-Token: 1The value is always the string 1. This prevents cross-site request forgery by ensuring the request was made from JavaScript code (browsers cannot set custom headers on cross-origin form submissions without CORS preflight).
Exempt from CSRF: POST /api/auth/login (no session exists yet).
If the header is missing on a mutating request, the API returns:
HTTP/1.1 403 ForbiddenRoles and Permissions
Section titled “Roles and Permissions”Three authorization policies control access:
| Policy | Roles | Applied To |
|---|---|---|
| ViewerOrAbove | viewer, editor, admin | Read endpoints (GET teams, principles, objectives, history, SSE, export) |
| EditorOrAbove | editor, admin | Event submission (POST events) |
| AdminOnly | admin | User management, global event log |
Additionally, certain events submitted through POST /api/events require admin role even though the endpoint only requires EditorOrAbove:
update_team_color,restore_history,import_teamcreate_entity,delete_entity,update_namewhentargetTypeis"Team"
Non-admin users attempting these events receive a 403 response.
Session Details
Section titled “Session Details”| Property | Value |
|---|---|
| Cookie name | techstrat_session |
| Lifetime | 7 days from creation |
| Storage | PostgreSQL sessions table |
| Cache | In-memory, 5-minute TTL |
Sessions are cleaned up automatically by a background service that runs hourly.
Check Current Session
Section titled “Check Current Session”To verify your authentication status and retrieve your user info:
curl https://localhost:5001/api/auth/me \ -b cookies.txtResponse (200):
{ "success": true, "userId": "a1b2c3d4-...", "username": "editor", "role": "editor", "error": null}Response (401): Session is invalid or expired.
Rate Limiting
Section titled “Rate Limiting”Login attempts are rate-limited per username:
- Threshold: 5 failed attempts within 15 minutes
- Lockout: Account is temporarily locked after threshold is reached
- Reset: Successful login clears the failure counter
- Scope: In-memory only (resets on application restart)
Blazor Client Integration
Section titled “Blazor Client Integration”Both Blazor WASM applications handle authentication automatically:
- The browser sends the
techstrat_sessioncookie with every request (same-origin) - The API clients (
StrategyApiClientandAdminApiClient) includeX-CSRF-Token: 1on all mutating requests - Session state is tracked in the application state services (
StrategyStateandAdminState) - Unauthenticated users are redirected to the login page