verifyUrl as returned — do not build it, do not append to it, and do not navigate to it.
Proxy /verify/* to your API in vite.config if needed so fetch("/verify/start") stays same-origin.
Your registered
returnUrl is a plain GET landing page, so in dev it can be either a route proxied to your API or a served SPA route — the redirect is an ordinary navigation. Whatever you register must be the exact string your server sends on POST /session, dev port included.Start verify
The landing page
The browser comes back toreturnUrl with ?session_id=…&state=… — two non-secret identifiers. The verification itself is finished on your server, which reads GET /session/{id} with its own credentials. The landing component asks your backend for the outcome and renders; see the React example.
There is no callback route in the SPA and nothing sensitive to read from the URL.
More: Frontend overview · React · Backend overview
