Wildcards in Firebase authorized domains: what works for subdomains and previews
Firebase documents no wildcard syntax such as *.example.com for authorized domains: Google's help page says to add the full domain name of each host your app uses. List every subdomain, preview and customer host on its own, and script the list with the Identity Toolkit API when those hosts change often.
What the docs say about wildcards
- Authorized domains: Google's help page says you must add "the full domain names" of the hosts your web app uses. The API stores the list as plain strings (
authorizedDomains, a "List of domains authorized for OAuth redirects") and describes no pattern syntax (checked Oct 2026). - Firebase's own tooling adds hosts one at a time. When you deploy a Firebase Hosting preview channel, the Firebase CLI appends that channel's exact host to the list. It doesn't add a pattern.
- A developer guide that automates this list reports plainly that "Firebase doesn't allow wildcard to be added", and adds each new subdomain through the API instead.
- OAuth redirect URIs reject wildcards too. If you moved
authDomain, Google's validation rules say redirect URIs cannot contain wildcard characters (*), so every host you use asauthDomainneeds its ownhttps://HOST/__/auth/handlerentry. See redirect_uri_mismatch.
Does example.com cover app.example.com?
The docs don't say it does. The Firebase JS SDK's in-browser check behaves differently from what the docs describe, so it helps to know what it does:
- The SDK compares each entry with the page's host name. For a name entry, it accepts the exact host or any host ending in
.plus that entry. The source comment readsdomain.com = *.domain.com OR domain.com. - An IP address entry must match exactly.
- The match only works downward: listing
app.example.comdoes not coverexample.com.
This is one check, in code, with no documentation behind it. Firebase's hosted sign-in helper and the server-side continue-URL checks are not documented to match the same way, and the code can change. Add each host you serve as its own entry rather than relying on the parent domain.
Never add a shared platform domain such as web.app, firebaseapp.com, vercel.app, netlify.app or pages.dev as a bare entry. Under the suffix match above, every site on that platform would pass the SDK's check for your project. Add your own full host (my-app.vercel.app) instead.
Subdomains you know in advance
- Write down every host that loads your sign-in code: apex,
www,app,admin,staging, and so on. - In the Firebase console, open Security > Authentication > Settings > Authorized domains (as of Oct 2026; older guides say Build > Authentication) and click Add domain for each one.
- Enter host names only, with no
https://, path or port. One entry covers any URL and port on that host.
The full walkthrough of the list, its defaults and the console path is in Firebase authorized domains.
Preview and branch URLs
Preview hosts change, so pick the approach that matches how often:
| Platform | Preview host shape | Approach |
|---|---|---|
| Firebase Hosting preview channels | SITE_ID--CHANNEL_ID-RANDOM_HASH.web.app |
firebase hosting:channel:deploy adds the channel host for you unless you pass --no-authorized-domains, and later channel deploys remove hosts of expired channels (from the firebase-tools source). Check the list after a deploy. |
| Vercel | Commit URL <project-name>-<unique-hash>-<scope-slug>.vercel.app, new for each commit; branch URL <project-name>-git-<branch-name>-<scope-slug>.vercel.app, stable for a branch |
Add the branch URL once per long-lived branch, or add each preview host from CI. Vercel exposes the branch host as VERCEL_BRANCH_URL. Details: auth/unauthorized-domain on Vercel. |
| Netlify | Deploy Preview deploy-preview-42--mysitename.netlify.app for pull request 42 |
Add each preview host from CI when the preview deploys. Details: auth/unauthorized-domain on Netlify. |
Add or remove a host from CI
The list is the authorizedDomains field of projects/PROJECT_ID/config, and PATCH replaces the whole field. This script reads the list, adds or removes one host, and writes the full list back, the same read-then-write pattern Firebase's CLI uses. It needs gcloud and jq.
#!/usr/bin/env bash
# Usage: PROJECT_ID=my-project ./authorized-domain.sh add|remove HOST
set -euo pipefail
ACTION="$1"
HOST="$2"
: "${PROJECT_ID:?set PROJECT_ID}"
TOKEN="$(gcloud auth print-access-token)"
URL="https://identitytoolkit.googleapis.com/admin/v2/projects/${PROJECT_ID}/config"
AUTH=(-H "Authorization: Bearer ${TOKEN}" -H "x-goog-user-project: ${PROJECT_ID}")
CURRENT="$(curl -sf "${AUTH[@]}" "${URL}" | jq -c '.authorizedDomains // []')"
if [ "${ACTION}" = "add" ]; then
NEW="$(jq -c --arg h "${HOST}" 'if any(.[]; . == $h) then . else . + [$h] end' <<<"${CURRENT}")"
elif [ "${ACTION}" = "remove" ]; then
NEW="$(jq -c --arg h "${HOST}" 'map(select(. != $h))' <<<"${CURRENT}")"
else
echo "Usage: PROJECT_ID=my-project $0 add|remove HOST" >&2
exit 1
fi
curl -sf -X PATCH "${AUTH[@]}" -H "Content-Type: application/json" \
-d "{\"authorizedDomains\": ${NEW}}" \
"${URL}?updateMask=authorizedDomains" | jq '.authorizedDomains'
Run it with add after the preview deploys (for example add "${VERCEL_BRANCH_URL}") and with remove when the pull request closes.
- Permissions: the CI identity needs
firebaseauth.configs.getandfirebaseauth.configs.update; the Identity Toolkit Admin and Identity Toolkit Editor roles include both. Setting thex-goog-user-projectheader also needsserviceusage.services.useon the project, which is in the Service Usage Consumer role. - One writer at a time: because each run writes the full list, two jobs running at once can overwrite each other's change. Run this step in a single CI concurrency group.
- Test it on a development Firebase project first. A wrong list removes hosts your users need.
Customer subdomains and multi-tenant apps
- Every customer host is its own entry. That includes
acme.yourapp.comand any custom domain a customer points at you. Add the host when you onboard the customer, using the script above or the same API call from your backend, and remove it when they leave. - Identity Platform tenants share one list. In the Identity Platform v2 API, the
Tenantresource has noauthorizedDomainsfield; the list lives on the project-levelConfig. Splitting customers into tenants doesn't give each one a separate list. - Changed authDomain per customer? Each of those hosts must also serve Firebase's
/__/auth/*helper and needs its own redirect URI, because Google doesn't accept wildcards there either.
How to confirm it worked
- Read the list the script prints after the
PATCH(or reload the console list) and check the exact host is present. - Open the subdomain or preview URL in a fresh tab. The SDK checks the list once per page load and keeps that result, so a tab that was already open can keep failing.
- Start sign-in. If
auth/unauthorized-domainis gone, the host is accepted. Still failing? See Firebase authorized domains not working.
FAQ
Can I add *.example.com as a Firebase authorized domain?
Firebase documents no wildcard syntax, and Google's help page says to add full domain names. Add each host, or automate additions with the Identity Toolkit API.
Does adding example.com also allow its subdomains?
The docs don't say so. The Firebase JS SDK's in-browser check does accept subdomains of a listed name, but that isn't documented for the rest of the sign-in flow, so add each subdomain explicitly.
How do I handle Vercel or Netlify preview URLs?
Add stable branch hosts once, and have CI add each preview host after it deploys and remove it when the pull request closes. Never add vercel.app or netlify.app on its own.
Do Identity Platform tenants have their own authorized domains?
No. The list is part of the project-level config, and the tenant resource in the v2 API has no authorized domains field.
Do OAuth redirect URIs accept wildcards?
No. Google's redirect URI validation rules forbid the * character, so each authDomain host needs its own /__/auth/handler redirect URI.
Sources
- Set a web app's OAuth redirect domains (Firebase Help)
- Identity Platform REST v2: Config resource (Google Cloud)
- Identity Platform REST v2: projects.updateConfig (Google Cloud)
- Identity Platform REST v2: projects.tenants (Google Cloud)
- Identity Platform access control with IAM (Google Cloud)
- Identity Toolkit IAM roles and permissions (Google Cloud)
- Authenticate for using REST: setting the quota project (Google Cloud)
- Authenticate with Firebase using Email Link in JavaScript: console path (Firebase docs)
- Manage Hosting resources: preview channel URLs (Firebase docs)
- Using OAuth 2.0 for Web Server Applications: redirect URI validation rules (Google Identity)
- firebase-js-sdk source: origin matching (validate_origin.ts)
- firebase-js-sdk source: origin check cached per page (popup_redirect.ts)
- firebase-tools source: getAuthDomains and updateAuthDomains (gcp/auth.ts)
- firebase-tools source: preview channel auth domains (hosting/api.ts)
- firebase-tools source: hosting:channel:deploy (hosting-channel-deploy.ts)
- Generated URLs for deployments (Vercel docs)
- System environment variables: VERCEL_BRANCH_URL (Vercel docs)
- Site deploys overview: Deploy Preview URLs (Netlify docs)
- Whitelist new domains to Firebase from code (DEV Community)
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.