Authentication and authorization
SREDSimplify currently has two API authentication modes:
| Consumer | Mechanism | Where used |
|---|---|---|
| Browser and app clients | Authorization: Bearer <token> | Spring Boot /api/v1/** user and admin APIs |
| Internal backend-to-worker calls | X-Internal-Token | Spring Boot to FastAPI task execution contract |
User-facing backend APIs
The main application API uses JWT bearer authentication.
- Login, registration, refresh, logout, password reset, and verification routes live under
/api/v1/auth/** - Most non-auth
/api/v1/**endpoints require a valid bearer token - Admin APIs live under
/api/v1/admin/**and require an admin role in addition to authentication
Public backend routes that do not require bearer auth include:
/api/v1/auth/*public auth flows/api/v1/screener/api/v1/subscription-plans/api/v1/billing/stripe/webhook/api/v1/contact/**
Frontend BFF behavior
Browser code does not call the backend origin directly. It calls the Next.js BFF route:
- browser path:
/api/bff/api/v1/* - server-side proxy target:
${BACKEND_ORIGIN}/api/v1/*
The BFF forwards:
AuthorizationContent-Type- Cloudflare Access service headers (
CF-Access-Client-Id,CF-Access-Client-Secret)
This keeps the backend origin and Cloudflare service credentials out of browser code.
Refresh token behavior
The frontend keeps an access token in app state and retries 401 failures through a queued refresh flow:
- An authenticated request receives
401 - The frontend performs one refresh request
- Concurrent failed requests wait behind that refresh
- On success, the queued requests replay
- On failure, the user is logged out
Internal Python worker authentication
The FastAPI worker is an internal service dependency. Its main task endpoint:
POST /api/v1/task/process
is protected with the X-Internal-Token header, not user JWTs.
Treat this header as a service secret shared between the Java backend and Python worker. It should never be exposed to browser code.