Test OAuth redirect URLs locally
Test OAuth and social login on localhost with a stable HTTPS redirect URL from a Horizon tunnel, and fix redirect URI mismatches.
A reserved Horizon subdomain gives your local app a stable HTTPS URL, so you register an OAuth redirect URI once and it keeps working.
What a redirect URI is
OAuth is the protocol behind "Sign in with Google" and similar buttons. Your app sends the user to the provider. The user approves. The provider then sends the user back to a URL on your app, with a code in the query string. That URL is the redirect URI.
You register the redirect URI in the provider's dashboard. On every sign-in, the provider compares the redirect_uri your app sends with the ones you registered. If they differ, the provider stops the flow.
Why providers reject localhost and plain HTTP
Some providers accept only HTTPS redirect URIs. Amazon, for example, documents that redirect URIs must use HTTPS. Others restrict localhost, or limit what a development app can register. The rules differ per provider, so each provider page in this section shows where to register the URL.
A tunnel sidesteps the question. Horizon serves every tunnel over HTTPS, so the redirect URI is a normal public HTTPS URL.
Why a random subdomain breaks it
Without -s, Horizon picks a random subdomain and changes it every run. The redirect URI you registered points at a subdomain that no longer exists. The provider then rejects the sign-in, or sends the user to a dead URL.
A reserved subdomain stays yours across restarts. Reserve one on the Subdomains page. Reserved subdomains are a paid feature, see Pricing. Use it with -s:
hrzn tunnel http://localhost:3000 -s my-appYour redirect URI is now https://my-app.hrzn.run/<callback path>. The callback path comes from your auth library. Register it once.
The Host header gotcha
The Horizon CLI sets the Host header to the local address, localhost:3000. This keeps dev-server host checks from blocking the tunnel. The public host arrives in X-Forwarded-Host.
Many auth libraries build the redirect URI from the Host header. Behind a tunnel they then build a localhost redirect URI, and the provider rejects it.
Fix it in one of two ways:
- Set the public URL explicitly in your auth library's config.
- Tell the library to trust
X-Forwarded-Host.
The Auth.js and Better Auth pages show both for those libraries.
The one-time browser warning
The first time a browser visits your tunnel URL, it sees a Before you continue page. Select Continue to site. Horizon shows it once every 7 days per IP address.
The page never appears for requests with an x-hrzn-skip-warning header (any value), for non-browser user agents, or for the OPTIONS method. Provider callbacks arrive in the user's browser, so you see the page once on the first sign-in test, before the provider redirects back. Open the tunnel URL in your browser first and select Continue to site.
Provider guides
Social and identity providers:
Authentication platforms:
Libraries:
Next steps
- Reserve a subdomain on the Subdomains page.
- Pick the provider you use from the list above.
Sign-in and OAuth
Test OAuth and social sign-in on localhost with a stable HTTPS redirect URL from Horizon, for Google, Apple, Auth0, WorkOS, Firebase and more.
Test Auth0 sign-in locally with a public callback URL
Test Auth0 sign-in on localhost with a Horizon tunnel, and set Allowed Callback URLs, Allowed Logout URLs and Allowed Web Origins once.