IdNot front-agnostic flow (durable setup) Overview - Goal: Backend is agnostic of the frontend, supports any domain and localhost. IdNot keeps the fixed redirect_uri, Nginx forwards to backend, backend returns to the real frontend with an authToken in the fragment. Data flow 1) Frontend (Next.js) requests state - POST https://dev3.4nkweb.com/api/v1/idnot/state - Body: { next_url: } - Returns: { state } 2) Frontend builds authorize URL and redirects - authorize = ${NEXT_PUBLIC_IDNOT_BASE_URL}${NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT} - query: client_id, redirect_uri = NEXT_PUBLIC_IDNOT_REDIRECT_URI_FIXED, scope=openid,profile, response_type=code, state 3) IdNot redirects to the fixed redirect - https://lecoffreio.4nkweb.com/authorized-client?code=...&state=... 4) Nginx (dev4) 301 → dev3 backend callback - https://dev3.4nkweb.com/idnot/callback?code=...&state=... 5) Backend callback - Verifies state (HMAC, TTL, nonce, host allowlist) - Exchanges code with IdNot - Creates session/authToken - 302 → next_url#authToken=... Frontend requirements - Expose runtime variables in Next.js (NEXT_PUBLIC_*): - NEXT_PUBLIC_IDNOT_BASE_URL=https://qual-connexion.idnot.fr - NEXT_PUBLIC_IDNOT_AUTHORIZE_ENDPOINT=/IdPOAuth2/authorize/ (or provider-specific) - NEXT_PUBLIC_IDNOT_CLIENT_ID= - NEXT_PUBLIC_IDNOT_REDIRECT_URI_FIXED=https://lecoffreio.4nkweb.com/authorized-client - NEXT_PUBLIC_FRONT_APP_HOST=https://dev4.4nkweb.com/lecoffre - NEXT_PUBLIC_BACK_BASE=https://dev3.4nkweb.com - Login button flow (simplified): 1) POST ${NEXT_PUBLIC_BACK_BASE}/api/v1/idnot/state { next_url: window.location.origin + '/authorized-client' } 2) On {state}, redirect to authorize with &state= - Callback page - Read authToken from window.location.hash - Store token then clear hash Backend requirements (summary) - Env: - BACK_HMAC_SECRET= - STATE_TTL_SECONDS=180 - ALLOW_LOCALHOST_REDIRECTS=true - ALLOWED_REDIRECT_HOST_PATTERNS=^dev4\.4nkweb\.com$,^localhost$,^127\.0\.0\.1$ - Endpoints: - POST /api/v1/idnot/state → returns signed state with {next_url, nonce, ts} - GET /idnot/callback → verifies state, exchanges code, then 302 to next_url#authToken=... Curl note (important) - When testing with curl, ensure a valid JSON body is actually sent. Some shells/options can result in an empty or malformed body, causing HTTP 500. - Use Content-Type: application/json and --data-binary, for example: curl -i -m 8 -X POST "https://dev3.4nkweb.com/api/v1/idnot/state" \ -H "Origin: https://lecoffreio.4nkweb.com" \ -H "Content-Type: application/json" \ --data-binary '{"next_url":"https://lecoffreio.4nkweb.com/authorized-client"}' Nginx notes - On dev4 (front): host lecoffreio.4nkweb.com must return 301 to dev3 callback, preserving full query string. - On dev3 (back): proxy /idnot/callback and /api/ to the backend server. Docker Compose (durable) - Build lecoffre-front locally to ensure latest code and env are used: lecoffre-front: build: context: ../lecoffre-front dockerfile: Dockerfile env_file: - .env.master - Keep .env.master at lecoffre_node/.env.master and include the NEXT_PUBLIC_* variables above. See .env.master.example. Testing checklist - On login: - Network shows POST /api/v1/idnot/state before redirect - IdNot authorize URL contains &state= - dev3 /idnot/callback returns 302 to next_url#authToken=... - Front stores token and proceeds Security considerations - HMAC-signed state with TTL and nonce (anti-replay) - Strict host allowlist for next_url and localhost allowed only if ALLOW_LOCALHOST_REDIRECTS=true - Prefer fragment (#authToken) to avoid logging tokens in proxies Operations - To rebuild and restart only the frontend after changes: docker compose build lecoffre-front docker compose up -d --no-deps --force-recreate lecoffre-front