Skip to main content
Social sign-in runs inside a secure browser session that is isolated from your app by design, and something has to carry the result back across that isolation. This feature ends the session the moment the provider redirects to your own domain, then loads that exact URL in your app, so the session cookie is written by your app on the first real request. There is no intermediate callback page, no custom URL scheme, and no path to configure: any redirect to your host finishes the login.
Your domain needs two verification files before this works, one for iOS and one for Android, and the native capability has to be turned on and shipped in a store build. All of it is covered under Verifying your domain below. On iOS the flow only runs on a physical device, never the Simulator.

Installation


How it works

Add type=https and the runtime watches your entire domain for the provider’s redirect. When that redirect lands, the secure session closes and your app loads the callback URL exactly as the provider sent it, query string and hash included.
Register https://yourapp.com/welcome as the redirect URI in your provider dashboard. Any URL on your host works, because the runtime watches the whole domain rather than one path. The redirect is never fetched inside the secure session: it is recognised at navigation time and handed to your app, which then makes the only real request to it. Wrap url once and only once. The runtime decodes it a single time, so a second encodeURIComponent reaches the provider still escaped, and hand-decoding before the call corrupts the request the other way: a state of xY%2Bz becomes xY+z, which a provider reads back as xY z, and a %26 becomes a real & that splits one parameter into two.

Passing the provider’s URL, not your own endpoint

The session watches your whole domain, so the URL you open has to live somewhere else. If url points at your own host, the session’s very first navigation already matches and it closes before the provider is ever shown. The runtime detects that, declines the HTTPS callback, logs a line naming the fix, and runs the legacy custom scheme flow instead.
Server-side auth libraries hand you an own-host entry point by default, a route on your domain that redirects onward to the provider. Build the provider’s authorize URL yourself for the native call, and keep your own endpoint as the redirect_uri it comes back to. The symptom of getting this wrong is a login that works but runs the legacy flow, which is easy to miss until someone reads the URL.

Reading the result

The callback URL arrives verbatim, so your page reads its token exactly as it would on the open web. Nothing is stripped and the fragment survives, so implicit flow providers that return tokens in the hash work without changes.
Because your app performs the request itself, any Set-Cookie header on that response is written into the app’s own cookie store, and the user stays signed in on the next launch.

Checking device support before you build the authorize URL

Your app picks its redirect URI before the flow starts, and that choice cannot be changed once the authorize URL is built. Read despia.httpsAuthCallback to find out whether the current device can finish on your domain, and fall back to your custom scheme redirect URI when it cannot.
Keep the fallback branch. It is what lets one build serve every device.

Verifying your domain

The operating system will only deliver the redirect to your app if it can confirm you own the host. Both files must be served over HTTPS with Content-Type: application/json and no redirects. The host that matters is the domain your app loads, and the match is exact. Publish the files on that hostname, spelled the same way, including any www prefix. A subdomain does not inherit its parent, so auth.yourapp.com is not covered by files served on yourapp.com, and a host carrying a port cannot be verified at all.
1

Enable Associated Domains on your main Bundle ID

Open the Apple Developer portal, go to Certificates, Identifiers and Profiles, then Identifiers, and select the Bundle ID your app ships under. On the Capabilities tab, tick Associated Domains and save.Enable it on the main Bundle ID, not on an extension identifier. Both halves of the Apple association file depend on this capability: applinks for the redirect and webcredentials for the sign-in session. Without it the operating system never reads your file at all, so the sheet opens, closes, and reports nothing.
2

Serve the Apple association file

Publish this at https://yourapp.com/.well-known/apple-app-site-association, replacing TEAMID.BUNDLEID with your own.
The webcredentials section is the part most existing setup guides leave out, because universal links never needed it. A file with only an applinks section verifies deep links correctly and fails sign-in, which is a confusing pair of symptoms to debug.
3

Copy your SHA-256 fingerprint from Play Console

The Despia Editor does not show this value, because the certificate that matters is held by Google rather than produced by your build. Open the Play Console, select your app, then go to Test and release, App integrity, and open the App signing tab. On older consoles the same page sits under Release, Setup, App integrity.Under App signing key certificate, copy the SHA-256 certificate fingerprint, a colon separated hex string.
Take the app signing key, not the upload key. Google re-signs every install it serves using the app signing key, so a file carrying only the upload key fingerprint verifies nothing for users who install from Play. The app signing key certificate only appears once the app exists in Play Console and a first bundle has been uploaded, so finish that before publishing the file.
4

Serve the Android association file

Publish this at https://yourapp.com/.well-known/assetlinks.json, using the fingerprint from the previous step and the package name of your app.
sha256_cert_fingerprints is an array, so add the Upload key certificate fingerprint from that same App integrity page as a second entry if you also install build artifacts directly onto a test device. Those builds are signed with the upload key rather than the app signing key, and without its fingerprint the domain will not verify on them.One file covers both Android paths, the in-browser session and the verified link fallback, so serving it correctly is what makes either of them work.
5

Set the domain in the Despia Editor

Enter the same host in your app’s deep link domain settings, using the exact hostname the association files are published on, including any www prefix.This has to be the domain your app itself loads. The session watches your app’s own host, while the iOS association is granted from this setting, so if the two name different hosts the sheet opens on a domain the build was never associated with and closes without completing.
6

Turn on Web App Synchronization

Go to Addons, open Web App Synchronization, and enable it. This is what activates the native capability in the build. The association files and the domain setting on their own do nothing until this is on.
7

Raise the version and deploy to the store

Open Settings, then Versioning, and raise the version with the Big, Medium, or Small button. Then run a new store deployment for the platform you are enabling, iOS or Android.The capability is written into the binary at build time, so it only reaches users through a deployment that carries the new version. Deploy to each store separately if you are enabling both.
None of the above reaches your app without a fresh store deployment on a raised version. Skip it and the installed binary carries no association for the domain and no native capability, so on iOS the sign-in sheet opens, closes immediately, and reports nothing that looks like an error.
Once both files are live, check the Android side from Google’s own view of your domain before you build.
An empty statements array means the file is unreachable, redirected, or served with the wrong content type. Play Console also reports verification state per domain on its Deep links page after a release, which is the fastest way to catch a fingerprint mismatch on a build that is already live. Apple fetches your association file through a CDN when the app installs or updates, and a failed first fetch is cached with no way to invalidate it. If the file was missing or misconfigured at that moment, correcting it is not enough on its own: reinstall the app or increment the build number.

Handling a broken domain association

A missing association is not reported when the session starts. It arrives later as the same cancellation code iOS uses when a user dismisses the sheet, which means an app that treats every cancellation as a user action will swallow a real misconfiguration in silence. Assign window.onAuthCallbackError to catch it. The runtime only calls it when it is a function, so it costs nothing to leave undefined.
The runtime invokes it with two positional arguments.
string
The domain the session was watching. Compare it against your configured host to confirm the association files are published on the right hostname, including any www prefix.
number
The underlying platform error code. On iOS a value of 1 is the shared cancellation code, which here means the domain is not associated with the app. On Android the value identifies a failed or timed out domain verification, which points at assetlinks.json.
The runtime does not retry on the legacy flow after this fires, because the authorize URL was already built for the HTTPS redirect URI. Use the callback to surface a fallback path to the user, and treat it as a signal to check your association files. A user who simply dismisses the sheet or closes the tab does not reach this callback. That case is an ordinary cancellation and is not reported as a failure.

Keeping older devices on the legacy flow

Leave type out and the runtime runs the original custom scheme flow, unchanged. Existing integrations need no edits, and a device that reports despia.httpsAuthCallback as false lands here automatically when you branch on the flag.
Two provider notes are worth checking before you migrate. Google installed app clients accept custom scheme and loopback redirect URIs only, and Microsoft Entra requires its own scheme, so both stay on this flow. Okta, Auth0, and Clerk support HTTPS redirect URIs on a verified domain. Use a top level server redirect for the final hop as well, since matching applies to main frame navigations and an iframe navigation never matches.

Resources

NPM Package

despia-native