diff --git a/apps/edr-freight-api/.env.example b/apps/edr-freight-api/.env.example index 9338a958f..c579eb388 100644 --- a/apps/edr-freight-api/.env.example +++ b/apps/edr-freight-api/.env.example @@ -98,10 +98,10 @@ FAYDA_PRIVATE_KEY_BASE64= # OAuth redirect_uri for MOBILE clients (must be registered with eSignet) FAYDA_REDIRECT_URI=http://localhost:3001/api/fayda/verification/complete # OAuth redirect_uri for WEB clients. Defaults to FAYDA_REDIRECT_URI when unset. -FAYDA_WEB_REDIRECT_URI=http://localhost:3000/callback +FAYDA_WEB_REDIRECT_URI=http://localhost:3000/fayda/callback # OAuth redirect_uri for the customer portal (its own origin — must also be # registered with eSignet). Defaults to FAYDA_WEB_REDIRECT_URI when unset. -FAYDA_PORTAL_REDIRECT_URI=http://localhost:5173/callback +FAYDA_PORTAL_REDIRECT_URI=http://localhost:5173/fayda/callback CLIENT_ASSERTION_TYPE=urn:ietf:params:oauth:client-assertion-type:jwt-bearer FAYDA_SCOPE=openid profile email phone address FAYDA_ACR_VALUES=mosip:idp:acr:generated-code diff --git a/apps/edr-freight-api/docs/FREIGHT_MASTER_FLOW.md b/apps/edr-freight-api/docs/FREIGHT_MASTER_FLOW.md index ea68e6938..98657843c 100644 --- a/apps/edr-freight-api/docs/FREIGHT_MASTER_FLOW.md +++ b/apps/edr-freight-api/docs/FREIGHT_MASTER_FLOW.md @@ -21,7 +21,7 @@ flowchart TD S0(["Customer visits portal"]):::start S0 --> S1["Signup via IAM
GET /auth/check-availability @Public
POST /otp/send + /otp/verify (P)"]:::port S1 --> S2{"Identity proofing
(VeriFayda)?"}:::dec - S2 -->|"Yes"| S3["POST /fayda/verification/start →
/callback → /complete
upsert iam.users (verified_by=fayda) (P)"]:::port + S2 -->|"Yes"| S3["POST /fayda/verification/start →
/fayda/callback → /complete
upsert iam.users (verified_by=fayda) (P)"]:::port S2 -->|"No"| S4 S3 --> S4["POST /companies/onboarding/start
draft company (placeholder TIN, PENDING) (P)"]:::port S4 --> S4b["Wizard: PATCH /profile, /onboarding-step,
upload license + docs
GET /onboarding/requirements (P)"]:::port diff --git a/apps/edr-freight-api/docs/FREIGHT_SYSTEM_FLOW.md b/apps/edr-freight-api/docs/FREIGHT_SYSTEM_FLOW.md index a6fd8bbeb..b29763060 100644 --- a/apps/edr-freight-api/docs/FREIGHT_SYSTEM_FLOW.md +++ b/apps/edr-freight-api/docs/FREIGHT_SYSTEM_FLOW.md @@ -131,7 +131,7 @@ sequenceDiagram `HasActiveDelegationGuard` as **global `APP_GUARD`s** — *every* route is JWT-protected unless it carries `@Public()`. Fine-grained `FreightPermissionGuard([perm])` decorators add permission checks on staff routes. Explicitly **public** endpoints: `GET /api/files/:fileId`, `POST /api/otp/{send,verify}`, -`GET /api/auth/check-availability`, the `fayda/verification/*` + `/callback` endpoints, +`GET /api/auth/check-availability`, the `fayda/verification/*` + `/fayda/callback` endpoints, `GET /api/payments/{checkout,receipt/:orderId}`, and the service-to-service `POST /api/internal/payments/mark-paid`. Real login / JWT issuance lives in the **external IAM package**, not this repo. (Note: `@edr/api-common`'s `@Public` and `@tria-plc/api-common`'s `@IsPublic` both set the same `"isPublic"` metadata key the guard reads.) @@ -288,7 +288,7 @@ flowchart TD chk --> otp["POST /otp/send + /otp/verify (P) @Public"] otp --> fayda{"Identity proofing?"} fayda -->|"VeriFayda 2.0"| fstart["POST /fayda/verification/start
→ eSignet authorize URL"] - fstart --> fcb["Fayda redirect → GET /callback (ack)
→ GET /fayda/verification/complete
(PKCE code exchange → upsert iam.users)"] + fstart --> fcb["Fayda redirect → GET /fayda/callback (ack)
→ GET /fayda/verification/complete
(PKCE code exchange → upsert iam.users)"] fcb --> onb fayda -->|"skip"| onb @@ -313,7 +313,7 @@ drives the required document set. Booking guards elsewhere `403` if the acting p | POST | `/api/fayda/verification/start` | start eSignet session (PKCE) | `@Public` + OptionalJwt | (B) verifayda.service | | GET | `/api/fayda/verification/complete` | code→identity, upsert `iam.users` | `@Public` | (B) verifayda.service | | GET | `/api/fayda/verification/status` | current user's Fayda link | JwtGuard | — | -| GET | `/callback` | passive Fayda redirect ack (no `/api`) | `@Public` | popup postMessage | +| GET | `/fayda/callback` | passive Fayda redirect ack (no `/api`) | `@Public` | popup postMessage | | GET·PUT | `/api/me/signature` | reusable signature (MinIO, base64) | JwtGuard | (P)(B) signatures.service | | GET | `/api/test_user1` · `/api/test_user2` | permission-guard demo | `PermissionGuard` | (B) demo pages | | GET | `/api/companies/getInfo` · `/profile` · `/dashboard` | company info / KPIs | JwtGuard | (P) companies.service | diff --git a/apps/edr-freight-api/src/main.ts b/apps/edr-freight-api/src/main.ts index f13c596d2..6a51fecb6 100644 --- a/apps/edr-freight-api/src/main.ts +++ b/apps/edr-freight-api/src/main.ts @@ -130,8 +130,11 @@ async function bootstrap() { maxAge: 86400, // cache preflight for 24h to cut chatter in dev }); - // /callback stays un-prefixed: it's the Fayda OAuth redirect_uri ack endpoint. - app.setGlobalPrefix("api", { exclude: ["callback"] }); + // /fayda/callback stays un-prefixed: it's the Fayda OAuth redirect_uri ack + // endpoint. Exact path, not "fayda" — exclusion is an exact route match, so + // "fayda" would leave /fayda/callback prefixed (404 at the registered + // redirect_uri) while still reading as if it covered the whole subtree. + app.setGlobalPrefix("api", { exclude: ["fayda/callback"] }); // enableImplicitConversion is OFF: class-transformer's implicit boolean // coercion turns any non-empty multipart/form-data string (including the // literal "false") into `true`, silently corrupting flags like isHazardous diff --git a/apps/edr-freight-api/src/modules/verifayda/fayda-callback.controller.ts b/apps/edr-freight-api/src/modules/verifayda/fayda-callback.controller.ts index 1c5569750..7f19eb313 100644 --- a/apps/edr-freight-api/src/modules/verifayda/fayda-callback.controller.ts +++ b/apps/edr-freight-api/src/modules/verifayda/fayda-callback.controller.ts @@ -6,12 +6,14 @@ import { VerifaydaCallbackDto } from './verifayda.dto'; /** * Plain acknowledgement endpoint for the Fayda redirect_uri when it points at * the API instead of the web app (e.g. MOBILE clients or connectivity checks). - * Registered at /callback (excluded from the global /api prefix in main.ts). + * Registered at /fayda/callback (excluded by exact path from the global /api + * prefix in main.ts — the exclusion must NOT be widened to "fayda", or + * /api/fayda/verification/* loses its prefix too). * It does NOT consume the verification session — the client must still call * GET /api/fayda/verification/complete with the echoed code+state. */ @ApiTags('Fayda Verification') -@Controller('callback') +@Controller('fayda/callback') export class FaydaCallbackController { @Get() @IsPublic() diff --git a/apps/edr-freight-web/backoffice/src/App.tsx b/apps/edr-freight-web/backoffice/src/App.tsx index 4dc1fb9e9..51fcd7e42 100644 --- a/apps/edr-freight-web/backoffice/src/App.tsx +++ b/apps/edr-freight-web/backoffice/src/App.tsx @@ -292,7 +292,10 @@ const buildSidebarSections = (demoItems: SidebarItem[]): SidebarSection[] => [ label: "Locomotives", href: "/dashboard/locomotives", icon: , - permission: [FREIGHT_PERMS.locomotives.view, FREIGHT_PERMS.fleet.view], + permission: [ + FREIGHT_PERMS.locomotives.view, + FREIGHT_PERMS.fleet.view, + ], }, { label: "Train Builder", @@ -818,7 +821,7 @@ const App = () => { {UserManagementRoutes()} {/* } /> */} } /> - } /> + } /> } /> { } /> } /> } /> - } /> + } + /> } /> } /> } /> @@ -1173,7 +1179,9 @@ const App = () => { + } @@ -1181,7 +1189,12 @@ const App = () => { + } @@ -1189,7 +1202,9 @@ const App = () => { + } @@ -1197,7 +1212,9 @@ const App = () => { + } @@ -1205,7 +1222,9 @@ const App = () => { + } @@ -1213,7 +1232,9 @@ const App = () => { + } @@ -1221,7 +1242,9 @@ const App = () => { + } @@ -1242,7 +1265,12 @@ const App = () => { + } @@ -1250,7 +1278,12 @@ const App = () => { + } @@ -1336,7 +1369,9 @@ const App = () => { + } @@ -1424,7 +1459,12 @@ const App = () => { + } @@ -1432,7 +1472,9 @@ const App = () => { + } @@ -1440,7 +1482,9 @@ const App = () => { + } @@ -1448,7 +1492,9 @@ const App = () => { + } @@ -1456,7 +1502,9 @@ const App = () => { + } @@ -1464,7 +1512,9 @@ const App = () => { + } @@ -1485,7 +1535,12 @@ const App = () => { + } @@ -1493,7 +1548,12 @@ const App = () => { + } diff --git a/apps/edr-freight-web/backoffice/src/complaints/utils/complaintVerificationStorage.ts b/apps/edr-freight-web/backoffice/src/complaints/utils/complaintVerificationStorage.ts index f7a500cfc..44441a26f 100644 --- a/apps/edr-freight-web/backoffice/src/complaints/utils/complaintVerificationStorage.ts +++ b/apps/edr-freight-web/backoffice/src/complaints/utils/complaintVerificationStorage.ts @@ -47,7 +47,7 @@ export function isComplaintAuthContext(pathname = ""): boolean { pathname.startsWith("/complaints") || pathname === "/complaint-form" || pathname === "/follow-complaint" || - pathname === "/callback" + pathname === "/fayda/callback" ); } diff --git a/apps/edr-freight-web/backoffice/src/components/errors/ApiErrorModal.tsx b/apps/edr-freight-web/backoffice/src/components/errors/ApiErrorModal.tsx index 07c9a39d1..4f8b0186a 100644 --- a/apps/edr-freight-web/backoffice/src/components/errors/ApiErrorModal.tsx +++ b/apps/edr-freight-web/backoffice/src/components/errors/ApiErrorModal.tsx @@ -28,7 +28,7 @@ let listener: Listener | null = null; /** Current-page path patterns where the global modal must stay silent. */ const EXCLUDED_PATH_PATTERNS = [ /^\/auth/, - /^\/callback/, + /^\/fayda/, /warehouse/i, /first-mile/i, /last-mile/i, diff --git a/apps/edr-freight-web/backoffice/src/components/fleet/FleetFormDialog.tsx b/apps/edr-freight-web/backoffice/src/components/fleet/FleetFormDialog.tsx index f0ccf0be0..b43c03f18 100644 --- a/apps/edr-freight-web/backoffice/src/components/fleet/FleetFormDialog.tsx +++ b/apps/edr-freight-web/backoffice/src/components/fleet/FleetFormDialog.tsx @@ -148,7 +148,7 @@ const FleetFormDialog = ({ }); }, [open, fields]); - // Receive the ?code&state relayed by the /callback popup, exchange it for + // Receive the ?code&state relayed by the /fayda/callback popup, exchange it for // the verified identity, and prefill the matching form fields. useEffect(() => { if (!open || !verifyWithFayda) return; diff --git a/apps/edr-freight-web/backoffice/src/pages/FaydaCallbackPage.tsx b/apps/edr-freight-web/backoffice/src/pages/FaydaCallbackPage.tsx index 5febb664a..48b9d32ce 100644 --- a/apps/edr-freight-web/backoffice/src/pages/FaydaCallbackPage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/FaydaCallbackPage.tsx @@ -5,7 +5,7 @@ import type { FaydaCallbackMessage } from "@/services/verifayda.service"; /** * Landing page for the eSignet redirect_uri (FAYDA_WEB_REDIRECT_URI → - * http://localhost:5183/callback). Runs inside the verification popup: + * http://localhost:5183/fayda/callback). Runs inside the verification popup: * relays ?code&state (or ?error) to the window that opened it via * postMessage, then closes itself. The opener performs the /complete call * so the single-use session is only consumed once, in one place. diff --git a/apps/edr-freight-web/backoffice/src/services/verifayda.service.ts b/apps/edr-freight-web/backoffice/src/services/verifayda.service.ts index d02394278..064a4c78f 100644 --- a/apps/edr-freight-web/backoffice/src/services/verifayda.service.ts +++ b/apps/edr-freight-web/backoffice/src/services/verifayda.service.ts @@ -17,7 +17,7 @@ export interface FaydaCompleteResult { userDataSaved?: boolean; } -/** Message posted from the /callback popup back to the opener window. */ +/** Message posted from the /fayda/callback popup back to the opener window. */ export interface FaydaCallbackMessage { type: 'fayda-callback'; code?: string; diff --git a/apps/edr-freight-web/backoffice/src/shared/components/FaydaCallbackDispatcher.tsx b/apps/edr-freight-web/backoffice/src/shared/components/FaydaCallbackDispatcher.tsx index 8f41a4b98..b4a14fddd 100644 --- a/apps/edr-freight-web/backoffice/src/shared/components/FaydaCallbackDispatcher.tsx +++ b/apps/edr-freight-web/backoffice/src/shared/components/FaydaCallbackDispatcher.tsx @@ -5,7 +5,7 @@ import ExternalPortalCallback from "@/external-portal/components/Registration/Ex /** * Single FAYDA OIDC callback entry point. - * Fayda only allows whitelisted redirect URIs (e.g. /callback) — route + * Fayda only allows whitelisted redirect URIs (e.g. /fayda/callback) — route * internally based on the `state` param sent during authorization. */ export default function FaydaCallbackDispatcher() { diff --git a/apps/edr-freight-web/backoffice/src/shared/services/sessionExpiry.ts b/apps/edr-freight-web/backoffice/src/shared/services/sessionExpiry.ts index e3da80b9c..af3c39dd5 100644 --- a/apps/edr-freight-web/backoffice/src/shared/services/sessionExpiry.ts +++ b/apps/edr-freight-web/backoffice/src/shared/services/sessionExpiry.ts @@ -11,7 +11,7 @@ const PUBLIC_PATHS = [ "/set-password", "/verify-otp", "/verification_page", - "/callback", + "/fayda/callback", "/complaints", "/complaint-form", "/follow-complaint", diff --git a/apps/edr-freight-web/backoffice/src/shared/utils/faydaOidc.ts b/apps/edr-freight-web/backoffice/src/shared/utils/faydaOidc.ts index 3f4693b2b..9d8376ec1 100644 --- a/apps/edr-freight-web/backoffice/src/shared/utils/faydaOidc.ts +++ b/apps/edr-freight-web/backoffice/src/shared/utils/faydaOidc.ts @@ -12,7 +12,7 @@ const DEFAULT_CODE_CHALLENGE = "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM"; const DEFAULT_NONCE = "g4DEuje5Fx57Vb64dO4oqLHXGT8L8G7g"; const DEFAULT_STATE = "ptOO76SD"; -/** OIDC state value that routes the shared /callback to the complaint flow (legacy sign-in). */ +/** OIDC state value that routes the shared /fayda/callback to the complaint flow (legacy sign-in). */ export const COMPLAINT_FLOW_STATE = "complaint_flow"; /** Complaint flow OIDC states — distinguish sign-in vs sign-up endpoints. */ @@ -66,9 +66,7 @@ export function startExternalPortalFaydaAuth(): void { export function generateFaydaAuthorizationUrl( options: FaydaOidcOptions = {}, ): string { - const redirectUri = - options.redirectUri || - getDefaultFaydaRedirectUri(); + const redirectUri = options.redirectUri || getDefaultFaydaRedirectUri(); const params = new URLSearchParams({ client_id: import.meta.env.VITE_CLIENT_ID || "", @@ -98,7 +96,7 @@ export function generateFaydaAuthorizationUrl( export function getDefaultFaydaRedirectUri(): string { return ( import.meta.env.VITE_REDIRECT_URI || - `${window.location.origin}/callback` + `${window.location.origin}/fayda/callback` ); } @@ -106,13 +104,12 @@ export function getDefaultFaydaRedirectUri(): string { * Returns the redirect URI registered with FAYDA for the complaint flow. * * Must exactly match a URI whitelisted in the FAYDA OIDC client — we reuse - * the same /callback path as external-portal registration and distinguish + * the same /fayda/callback path as external-portal registration and distinguish * flows via the `state` parameter (see COMPLAINT_FLOW_STATE). */ export function getComplaintFaydaRedirectUri(): string { return ( - import.meta.env.VITE_COMPLAINT_REDIRECT_URI || - getDefaultFaydaRedirectUri() + import.meta.env.VITE_COMPLAINT_REDIRECT_URI || getDefaultFaydaRedirectUri() ); } diff --git a/apps/edr-freight-web/portal/src/App.tsx b/apps/edr-freight-web/portal/src/App.tsx index 2f661af75..f1715f740 100644 --- a/apps/edr-freight-web/portal/src/App.tsx +++ b/apps/edr-freight-web/portal/src/App.tsx @@ -253,113 +253,115 @@ const App = () => { {/* Global API error modal — shows the server's actual error message for every failed request (suppressed on onboarding/auth pages). */} - - {/* Public routes */} - } /> - } /> - } - /> - {/* Payment provider browser redirects (PAYMENT_RETURN_URL / PAYMENT_FAILURE_URL) */} - {/* Fayda (eSignet) redirect_uri — runs in the verification popup and - relays the code/state back to the form that opened it. */} - } /> - } /> - } /> + + {/* Public routes */} + } /> + } /> + } + /> + {/* Payment provider browser redirects (PAYMENT_RETURN_URL / PAYMENT_FAILURE_URL) */} + {/* Fayda (eSignet) redirect_uri — the whole tab lands here after + verification, completes the code/state exchange and navigates back + to the page that started it. Public on purpose: behind RequireAuth + the onboarding gate would redirect away before the exchange ran. */} + } /> + } /> + } /> - {/* Auth pages — inaccessible once logged in */} - }> - } /> - } /> - } /> - + {/* Auth pages — inaccessible once logged in */} + }> + } /> + } /> + } /> + - {/* Staff-issued reset links land here. Deliberately outside + {/* Staff-issued reset links land here. Deliberately outside RedirectIfAuthed: a customer with a stale session still needs the link to work, and the token — not the session — is what authorises it. */} - } /> + } /> - {/* Signup-flow pages; reached while a session already exists */} - } /> - } /> + {/* Signup-flow pages; reached while a session already exists */} + } /> + } /> - }> - }> - - - - } - > - } /> - {/* Bookings are created against a contract, but the full list is + }> + }> + + + + } + > + } /> + {/* Bookings are created against a contract, but the full list is browsable here. New-booking entry still routes via a contract. */} - } /> - } - /> - } /> - } /> - } - /> - } /> - } /> - } - /> - } - /> - } - /> - {/* Completion of an initiated (bare) booking after per-booking + } /> + } + /> + } /> + } /> + } + /> + } /> + } /> + } + /> + } + /> + } + /> + {/* Completion of an initiated (bare) booking after per-booking clearance — same form, submits to the complete endpoint. */} - } - /> - } - /> - } /> - } /> - } /> - } /> - {/* Profile was merged into Settings — keep old links working. */} - } - /> - } /> - } /> + } + /> + } + /> + } /> + } /> + } /> + } /> + {/* Profile was merged into Settings — keep old links working. */} + } + /> + } /> + } /> + - - } /> - + } /> + ); }; diff --git a/apps/edr-freight-web/portal/src/components/FaydaVerifyPanel.tsx b/apps/edr-freight-web/portal/src/components/FaydaVerifyPanel.tsx index 8ecb87854..4e6921e14 100644 --- a/apps/edr-freight-web/portal/src/components/FaydaVerifyPanel.tsx +++ b/apps/edr-freight-web/portal/src/components/FaydaVerifyPanel.tsx @@ -61,7 +61,7 @@ function getInitials(name: string | null): string { * The identity is proved on eSignet, which the whole tab navigates to — no * popup, because a popup opened after the /start round-trip has lost its user * activation and iOS Safari blocks it outright. eSignet redirects back to - * /callback, which completes the exchange and returns the user here; the API + * /fayda/callback, which completes the exchange and returns the user here; the API * writes the person's name, phone, email and address from the verified * payload. Nothing on this panel is typed. */ @@ -82,7 +82,7 @@ export default function FaydaVerifyPanel({ try { const authorizationUrl = await verifaydaService.start(); // Record who is being verified and where to come back to before the tab - // leaves — /callback has no other way to know either. + // leaves — /fayda/callback has no other way to know either. stashPendingVerification({ subject, returnTo: @@ -96,7 +96,7 @@ export default function FaydaVerifyPanel({ setError( (err as { response?: { data?: { message?: string } } })?.response?.data ?.message ?? - (err instanceof Error ? err.message : "Could not start verification"), + (err instanceof Error ? err.message : "Could not start verification"), ); } }; @@ -189,7 +189,13 @@ function DataRow({ icon, value }: { icon: ReactNode; value: string | null }) { if (!value) return null; return ( - + {icon} diff --git a/apps/edr-freight-web/portal/src/pages/FaydaCallbackPage.tsx b/apps/edr-freight-web/portal/src/pages/FaydaCallbackPage.tsx index 16e7d43ac..50b3812ca 100644 --- a/apps/edr-freight-web/portal/src/pages/FaydaCallbackPage.tsx +++ b/apps/edr-freight-web/portal/src/pages/FaydaCallbackPage.tsx @@ -9,7 +9,7 @@ import { /** * Landing page for the portal's eSignet redirect_uri - * (FAYDA_PORTAL_REDIRECT_URI → http://localhost:5173/callback). + * (FAYDA_PORTAL_REDIRECT_URI → http://localhost:5173/fayda/callback). * * The verification is a full-page redirect, so the page that started it no * longer exists: this page completes the code+state exchange itself against diff --git a/apps/edr-freight-web/portal/src/services/verifayda.pending.test.ts b/apps/edr-freight-web/portal/src/services/verifayda.pending.test.ts index cdf8b772b..04604d787 100644 --- a/apps/edr-freight-web/portal/src/services/verifayda.pending.test.ts +++ b/apps/edr-freight-web/portal/src/services/verifayda.pending.test.ts @@ -7,7 +7,7 @@ import { /** * The stash is the only thing that survives the full-page handoff to eSignet, - * so /callback completing against the wrong subject — or throwing on junk left + * so /fayda/callback completing against the wrong subject — or throwing on junk left * behind by an older build — would either misfile a verified identity or dead- * end the flow. */ diff --git a/apps/edr-freight-web/portal/src/services/verifayda.service.ts b/apps/edr-freight-web/portal/src/services/verifayda.service.ts index c7521adda..e51f612a1 100644 --- a/apps/edr-freight-web/portal/src/services/verifayda.service.ts +++ b/apps/edr-freight-web/portal/src/services/verifayda.service.ts @@ -41,8 +41,8 @@ export interface CompanyIdentityState { /** * What the panel was doing when it handed the tab over to eSignet. The * verification is a full-page redirect, so the page that started it is gone by - * the time /callback runs — this is how /callback knows whose identity the - * code+state belongs to and where to put the user back. + * the time /fayda/callback runs — this is how that page knows whose identity + * the code+state belongs to and where to put the user back. * * sessionStorage, not localStorage: it is scoped to this tab, so two tabs * verifying different people can't overwrite each other, and it dies with the diff --git a/docker-compose.e2e.yaml b/docker-compose.e2e.yaml index 4df2cc1e4..621919a56 100644 --- a/docker-compose.e2e.yaml +++ b/docker-compose.e2e.yaml @@ -235,8 +235,8 @@ services: PAYMENT_API_URL: http://payment-mock-e2e:4500 FAYDA_TOKEN_ENDPOINT: http://fayda-mock-e2e:4400/token FAYDA_USERINFO_ENDPOINT: http://fayda-mock-e2e:4400/userinfo - FAYDA_REDIRECT_URI: http://localhost:${E2E_PORTAL_PORT:-5373}/callback - FAYDA_PORTAL_REDIRECT_URI: http://localhost:${E2E_PORTAL_PORT:-5373}/callback + FAYDA_REDIRECT_URI: http://localhost:${E2E_PORTAL_PORT:-5373}/fayda/callback + FAYDA_PORTAL_REDIRECT_URI: http://localhost:${E2E_PORTAL_PORT:-5373}/fayda/callback # Throwaway e2e-only RSA JWK (client_assertion signing) — the mock # never verifies the signature, this just has to be well-formed. # Generated fresh per launch by e2e.mjs (fakeFaydaPrivateKeyBase64),