Two different redirects
Two URLs in this flow are both called a redirect, and they are not the same thing.
The provider redirect URI is how Google or Apple hands the user back to Portal,
and it is covered in Google OAuth and
Apple OAuth. Everything below is about
the second one.
Supported forms
An App Link or Universal Link is not a separate kind of allow-list entry. To
Portal it is an ordinary HTTPS URL; what routes it to your app instead of a
browser is the association file you host on that domain
(
assetlinks.json on Android, apple-app-site-association on iOS). Portal
appends its parameters the same way either way.
Custom schemes are valid allow-list entries. If you are integrating a mobile
app, register the same custom scheme URL you will pass to the SDK — you do not
need to host a web page to complete a sign-in.
How matching works
Portal compares your redirect URL against the allow list by exact string comparison. There are no wildcards and no path prefixes.
A request whose
redirectUrl is not on the list is rejected with a 401. This
is what stops someone who has your Auth Environment ID from sending your users,
and their sign-in tokens, to a site they control. On the OAuth path the check
runs twice: once when the sign-in starts and again when the provider calls back.
Use one string everywhere
The same redirect URL has to appear, byte for byte, in up to three places.- The dashboard. The Redirect URLs allow list under Authentication > Configure. See Enable authentication.
- Your SDK configuration.
redirectUrlin the Web SDK’sclientAuthoption, or the equivalent for whichever client you are using. - Your native app registration. On mobile only: the URL scheme in
Info.plistand the intent filter inAndroidManifest.xml.
- Dashboard and SDK disagree — the sign-in never starts. You get a
401from the call that begins the flow. - SDK and native registration disagree — the sign-in completes, but the redirect never reaches your app. Nothing throws; the user is left in the browser.
What Portal appends
Portal appends its parameters to your redirect URL, using? or & depending
on whether your URL already has a query string.
token, the SDKs read
the last occurrence, which is always the one Portal appended.
Grants are single use
Thetoken parameter is a grant: proof that a sign-in completed. It is
short-lived and single use, and it is spent the moment the backend sees it.
Once a grant has been exchanged or has expired, the user has to sign in again.
There is no way to refresh one.
When a sign-in fails
The two methods fail differently, and your app has to handle both. OAuth returns the user to your redirect URL witherror=oauth_failed and no
token. The value is deliberately generic — it covers a cancelled consent
screen, a disabled method, and a rejected state nonce alike. Treat it as “the
user did not complete the sign-in” and offer to start again.
Magic links have no error redirect. An expired or already-used link still
arrives at your redirect URL carrying a token, and the failure only surfaces
when your app exchanges it. So a redirect that looks valid can still fail a
moment later. Your app needs an error path on the exchange, not just on the URL.
A redirect can arrive twice
Operating systems re-deliver deep links, and a browser can reload a callback page. Because a grant is spent on first use, a second delivery of the same redirect cannot produce a second session. Route every redirect through exactly one handler in your app. If two code paths both consume the same URL, the second one fails on an already-spent grant, which looks like a genuine authentication error to your user.Register the redirect in your app
- Web
Add a route at the exact URL on your allow list. It has to be reachable by
a full-page navigation, because the provider redirects the browser to it.The page reads its own URL and hands it to the SDK. See
Client Auth for the callback route.
Client Auth is available in the Portal Web SDK. If you are integrating on
another platform, you can drive the same flow against the
Authentication API directly.
Next steps
Web Client Auth
Build a callback route and complete a sign-in in a web app.