Firebase auth/unauthorized-domain on localhost and 127.0.0.1

Updated Oct 27, 2026 · Pewterkit Guides

Firebase projects created after April 28, 2025 no longer include localhost in their authorized domains, so local sign-in fails with auth/unauthorized-domain until you add it. Add localhost (and 127.0.0.1 if your dev server uses it) under Security > Authentication > Settings > Authorized domains on a development project, then fully reload the page.

Why it happens on localhost

  • The default changed. Firebase's troubleshooting page: "In projects created after April 28, 2025, Firebase Authentication no longer includes localhost as an authorized domain by default." Google's Identity Platform docs say the same from the other side: "For projects created before April 28, 2025, localhost is enabled by default." An older project can work locally while a new one fails with the same code.
  • The SDK checks the exact host name. Before a popup or redirect sign-in, the Firebase JS SDK compares the page's host name with each authorized domain. localhost and 127.0.0.1 are different host names, and an IP address entry must match exactly.
  • Ports don't matter. Google's help page says an authorized domain allows "any URL and port of that domain", so one localhost entry covers localhost:3000, localhost:5173 and any other port.

Check which host your browser is on: the address bar, or window.location.hostname in the console. Vite's dev server, for example, listens on localhost by default and on your LAN addresses when started with --host.

Fix: add localhost to a development project

Google "strongly discourages the use of localhost in production projects", and Firebase suggests removing it from production so that code running on someone else's machine can't reach your production project. Use a separate Firebase project for local work.

  1. Open the development project in the Firebase console.
  2. Go to Security > Authentication > Settings (as of Oct 2026; older guides say Build > Authentication, and some show the list on the Sign-in method tab).
  3. Under Authorized domains, click Add domain and enter localhost. No http://, no port.
  4. If your dev server opens on 127.0.0.1, add 127.0.0.1 as a second entry.
  5. Fully reload the app tab. The SDK checks the list once per page load and keeps the result, so a tab that failed before you added the entry keeps failing until it reloads.

If you use Google Cloud Identity Platform, the same list is under Identity Platform > Identity providers > Project settings > Add Domain (as of Oct 2026).

Everything else about the list, including adding hosts by API, is in Firebase authorized domains.

Don't set authDomain to localhost

authDomain is not the list of allowed hosts. It names the host that serves Firebase's sign-in helper, and outside the emulator the SDK always opens it as https://<authDomain>/__/auth/handler. With authDomain: "localhost:5173", sign-in goes to https://localhost:5173/__/auth/handler. A plain-http dev server doesn't answer that, and it doesn't serve Firebase's helper files either.

Keep the value Firebase gave you while developing:

// firebase.js (Firebase JS SDK v9+ modular API)
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";

const firebaseConfig = {
  apiKey: "YOUR_DEV_PROJECT_API_KEY",
  authDomain: "your-dev-project.firebaseapp.com", // not "localhost"
  projectId: "your-dev-project",
  appId: "YOUR_DEV_APP_ID",
};

export const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);

Need redirect sign-in to run on the same origin locally? That takes a proxy for /__/auth/* and an HTTPS dev server. See signInWithRedirect on localhost.

Alternative: use the Auth emulator

The Firebase Local Emulator Suite runs Authentication on your machine. When the SDK is connected to the emulator it skips the authorized-domain check, and the emulator serves its own sign-in page for signInWithPopup and signInWithRedirect, creating mock third-party accounts as needed.

import { getAuth, connectAuthEmulator } from "firebase/auth";

const auth = getAuth(app);
if (import.meta.env.DEV) {
  // Start it first with: firebase emulators:start
  connectAuthEmulator(auth, "http://127.0.0.1:9099");
}

import.meta.env.DEV is Vite's flag for dev mode; use your framework's equivalent. Firebase recommends demo- project IDs with the emulators where possible, because a demo project has no live resources to change by accident.

The emulator can't tell you whether your live project's list is right. Before you deploy, test once against the real project too.

Testing on a phone or another computer (LAN IP)

When you open http://192.168.1.23:5173 on a phone, the page's host is 192.168.1.23, not localhost.

  1. Find your computer's LAN IP, and start the dev server so it listens on it (Vite only does this when started with --host).
  2. Add that IP (192.168.1.23, no port) to the development project's authorized domains.
  3. If your network later gives your computer a different IP, add the new one too; IP entries only match exactly. Remove old entries when you're done.

Firebase's docs don't describe IP address entries; the SDK does contain matching code for them. If the console won't save an IP in your project, use a host name that points to your computer instead (see the next section).

Custom dev host names

If you map a name such as myapp.test to your machine, that name is the page's host, so add myapp.test to the list as well. Vite also refuses requests for host names it doesn't know (localhost, names under .localhost and IP addresses are allowed by default), so add the name to server.allowedHosts in vite.config.js:

// vite.config.js
import { defineConfig } from "vite";

export default defineConfig({
  server: {
    allowedHosts: ["myapp.test"],
  },
});

How to confirm it worked

  1. In the console, check the exact host (localhost, 127.0.0.1, the LAN IP or your custom name) is in Authorized domains.
  2. Reload the app in a new tab.
  3. Start sign-in. If the popup or redirect opens Google's sign-in instead of throwing auth/unauthorized-domain, the host is accepted. Still failing? Work through Firebase authorized domains not working.

FAQ

Why does localhost work on my old Firebase project but not my new one?

Projects created after April 28, 2025 don't get localhost as an authorized domain by default; older projects did. Add it yourself on the new project's development copy.

Should I add localhost to my production Firebase project?

Google strongly discourages it, and Firebase suggests removing localhost from production projects. Use a separate development project for local sign-in.

Do I need to add the port, like localhost:5173?

No. An authorized domain allows any URL and port on that host, so a single localhost entry covers every dev server port.

Is 127.0.0.1 the same as localhost here?

No. The SDK compares host names, and an IP address entry must match exactly, so add 127.0.0.1 separately if your browser shows it.

Do I need localhost in my Google OAuth client's redirect URIs?

Not with the default authDomain. Firebase's own steps for a manual OAuth web client list http://localhost and http://localhost:5000 only as JavaScript origins, and the redirect URIs as https://PROJECT_ID.firebaseapp.com/__/auth/handler and https://PROJECT_ID.web.app/__/auth/handler.

Sources

  1. Authentication FAQ and troubleshooting: localhost change and manual OAuth client (Firebase docs)
  2. Signing in users with Google: Identity Platform (Google Cloud docs)
  3. Set a web app's OAuth redirect domains (Firebase Help)
  4. Authenticate with Firebase using Email Link in JavaScript: console path (Firebase docs)
  5. Connect your app to the Authentication Emulator (Firebase docs)
  6. Learn more about web apps and the Firebase config object (Firebase docs)
  7. firebase-js-sdk source: origin matching and emulator skip (validate_origin.ts)
  8. firebase-js-sdk source: origin check cached per page (popup_redirect.ts)
  9. firebase-js-sdk source: handler URL built from authDomain (handler.ts)
  10. Best practices for using signInWithRedirect: Option 3, proxy auth requests (Firebase docs)
  11. Vite server options: server.host and server.allowedHosts (Vite docs)
  12. Env variables and modes: import.meta.env.DEV (Vite docs)

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.

Related guides