Firebase Auth on Replit: domains, Secrets and custom domains
Firebase rejects sign-in from any host that isn't on your project's Authorized domains list, and a Replit app runs on at least two hosts: a temporary *.replit.dev development URL that can change, and your published *.replit.app (or custom) domain. Add the exact hosts you use, keep authDomain on firebaseapp.com unless you can proxy /__/auth/*, and re-check the dev host whenever Sign in with Google starts failing again.
Why it breaks on Replit
- The development URL is temporary. Replit's docs describe it as
UUID.servername.replit.dev, live only while you work in the app, and say it "can change each time you reopen the app." An authorized domain you added yesterday may not match today's URL, so you getauth/unauthorized-domain("This domain is not authorized for OAuth operations for your Firebase project"). - The published app is a different host. Publishing gives you
<name>.replit.app, and each custom domain or subdomain (includingwww) is another host. - Old
repl.coaddresses have moved. Replit movedrepl.cohosting toreplit.devon January 1, 2024. If your authorized domains or OAuth settings still list arepl.cohost, it does nothing for current apps.
Step 1: Find the exact hosts your app uses
Replit sets environment variables you can print from the Shell tool:
echo "$REPLIT_DEV_DOMAIN" # current development host
echo "$REPLIT_DOMAINS" # domains Replit reports for this app
You can also open Preview and read the ...replit.dev host from its location bar, or use "Open in new tab" and copy it from the address bar. For the published app, the host is shown in the Publishing tool (<name>.replit.app, plus any custom domains).
Step 2: Add them to Firebase's authorized domains
- In the Firebase console, open Security > Authentication > Settings (older guides say Build > Authentication > Settings; the Firebase docs use Security as of Oct 2026).
- Under Authorized domains, click Add domain and add, host name only (no
https://, no path): - the current development host, e.g.1a2b3c4d-....servername.replit.dev-yourapp.replit.app- each custom domain you serve, e.g.example.comandwww.example.com - When the dev host changes, add the new one and remove the stale one.
Don't add the bare platform domain replit.dev or replit.app as a shortcut. The Firebase JS SDK's origin check treats an authorized domain as also covering its subdomains, so a shared platform domain would also accept other people's Replit apps. Why wildcards aren't the answer: authorized domains wildcard.
Step 3: Put the Firebase config somewhere sensible
Firebase's web config is not a secret: Firebase says API keys for Firebase services "are OK to include in code or checked-in config files." Restrict the key in Google Cloud and protect data with Security Rules. Real secrets (a service account JSON for the Admin SDK, for example) belong in Replit Secrets.
If you still want the config out of the code:
- Open Tools > Secrets (under Setup) and add keys, e.g.
VITE_FIREBASE_API_KEY,VITE_FIREBASE_AUTH_DOMAIN,VITE_FIREBASE_PROJECT_ID,VITE_FIREBASE_APP_ID. Secrets reach your app as environment variables. - If your frontend is built with Vite, only variables prefixed
VITE_are exposed to browser code, and their values are baked into the bundle at build time:
```js // src/firebase.js import { initializeApp } from 'firebase/app'; import { getAuth, GoogleAuthProvider, signInWithPopup } from 'firebase/auth';
const app = initializeApp({ apiKey: import.meta.env.VITE_FIREBASE_API_KEY, authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN, // YOUR-PROJECT.firebaseapp.com projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID, appId: import.meta.env.VITE_FIREBASE_APP_ID, });
export const auth = getAuth(app); export const signInWithGoogle = () => signInWithPopup(auth, new GoogleAuthProvider()); ```
- Check the published app's values too: in Publishing > Adjust settings > Production app secrets. Replit notes Secrets are available for all deployment types except Static Deployments, so a Static Deployment needs the values in code or in a build step that has them.
Step 4: Decide what a custom domain means for authDomain
Adding a custom domain to a Replit deployment does not change authDomain. Leave it as YOUR-PROJECT.firebaseapp.com and signInWithPopup() keeps working on every authorized host; Google's screen will show the firebaseapp.com name.
To make sign-in run on your own domain (needed for signInWithRedirect() on browsers that block third-party storage, and to show your domain on the Google screen), https://your-domain/__/auth/* must be forwarded to https://YOUR-PROJECT.firebaseapp.com/__/auth/*. What you can do depends on the deployment type:
- Autoscale or Reserved VM (your server runs): add a transparent proxy in your Express server, before your other routes.
```js import { createProxyMiddleware } from 'http-proxy-middleware';
app.use( createProxyMiddleware({ target: 'https://YOUR-PROJECT.firebaseapp.com', changeOrigin: true, pathFilter: '//auth', // keeps the full //auth/... path }), ); ```
Firebase's docs say the proxy must forward GET and POST requests transparently. Register it before any body parser such as express.json(). Test this on a preview deployment before relying on it.
- Static Deployment: there is no server, and Replit's rewrites "can only redirect to files within your Static Deployment," so they can't proxy to Firebase. Firebase's alternative is to self-host the helper files (
/__/auth/handler,handler.js,experiments.js,iframe,iframe.js,links,links.js,/__/firebase/init.json) and re-sync them periodically; it doesn't support Apple sign-in or SAML. Otherwise keep the defaultauthDomain. - Cloudflare in front of Replit is not a documented route: Replit's custom-domain docs warn that proxied (orange-cloud) Cloudflare records cause setup issues, because Replit can't renew certificates for them, and say to set records to DNS only.
Once /__/auth is served from your domain:
- Set
authDomainto that domain, e.g.app.example.com. - In Google Cloud, open the Clients page (
console.cloud.google.com/auth/clients, as of Oct 2026), edit the Web client Firebase created, and addhttps://app.example.com/__/auth/handlerunder Authorized redirect URIs. - Keep
app.example.comin Firebase's authorized domains.
Do this only on a stable host such as your custom domain or yourapp.replit.app; the changing replit.dev host can't hold a stable redirect URI. The full switch is covered in change Firebase authDomain.
How to confirm it worked
- Open the dev URL in a new tab, click Sign in with Google, pick an account. The popup should close and
auth.currentUsershould be set (log it, or watchonAuthStateChanged). - Repeat on
yourapp.replit.appand each custom domain. A host that still fails is a host missing from the list. - If you added the proxy,
https://your-domain/__/auth/handlershould return a Firebase page, not your app's 404 or index page.
Related problems
- Not sure whether popup or redirect suits a Replit app: popup or redirect?
- A different error code: Firebase Auth errors
FAQ
Why does Firebase sign-in break every time I reopen my Repl?
Replit's development URL can change each time you reopen the app, and Firebase only accepts hosts on your authorized domains list. Print $REPLIT_DEV_DOMAIN, add the new host and remove the old one.
Can I just add replit.dev to Firebase authorized domains?
It would cover the changing dev host, but the Firebase JS SDK's origin check also accepts subdomains of an authorized domain, so it would open your project to every app on that shared domain. Add exact hosts instead, and use your published domain for anything real.
Should my Firebase config go in Replit Secrets?
It can, but it doesn't have to: Firebase API keys for Firebase services are OK in client code. Use Secrets for real secrets such as Admin SDK credentials, and remember a Vite frontend only exposes VITE_-prefixed variables.
Does connecting a custom domain on Replit change my authDomain?
No. authDomain stays YOUR-PROJECT.firebaseapp.com until you change it yourself, and you should only change it once your domain serves /__/auth/* through a proxy or self-hosted helper files.
Do repl.co URLs still work for Firebase Auth?
Replit moved repl.co hosting to replit.dev on January 1, 2024. Authorize your current replit.dev, replit.app or custom hosts instead.
Sources
- Replit Docs: Development URLs
- Replit Docs: Preview
- Replit Docs: Secrets
- Replit Docs: Custom domains
- Replit Docs: Deployment types
- Replit Docs: Static Deployments advanced configuration
- Replit Blog: Changes to Hosting on Replit
- Firebase: Authenticate with Firebase Using Email Link in JavaScript (authorized domains path)
- Firebase: Best practices for using signInWithRedirect on browsers that block third-party storage access
- Firebase: Learn about using and managing API keys
- Firebase JS SDK source: auth error messages
- Firebase JS SDK source: origin validation
- Vite: Env Variables and Modes
- http-proxy-middleware README
- Google Identity: Using OAuth 2.0 for Web Server Applications
How this page was made: drafted with AI from the sources listed, reviewed by Pewterkit. Docs checked Oct 27, 2026. Spotted something out of date? Tell us.