Skip to content

Authentication and authorization

SREDSimplify currently has two API authentication modes:

ConsumerMechanismWhere used
Browser and app clientsAuthorization: Bearer <token>Spring Boot /api/v1/** user and admin APIs
Internal backend-to-worker callsX-Internal-TokenSpring 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:

  • Authorization
  • Content-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:

  1. An authenticated request receives 401
  2. The frontend performs one refresh request
  3. Concurrent failed requests wait behind that refresh
  4. On success, the queued requests replay
  5. 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.