firebase / firebase/firebase-tools
firebase login: use 127.0.0.1 (not localhost) for OAuth loopback + surface --no-localhost hint on hang
- Dominant language
- TypeScript
- Stars
- 4.5k
- Forks
- 1.3k
- Avg merge
- 1d 12h
- Merged PRs (30d)
- 84
Description
### Which command?
login
### Version info
firebase-tools 15.22.3, Node 20.x, Windows 11 (corp-managed / SSO)
### Platform
Windows
### CLI/emulator log
(design/behaviour report — no crash log; behaviour observed on multiple corp Windows setups)
### Reproduction steps
1. On a corp-managed Windows machine (SSO-gated Google account, hosts file locked down, dual-stack IPv6 enabled), run `firebase login`.
2. Complete Google SSO in browser. The success page never loads; CLI hangs on `Waiting for authentication...`.
3. Root cause: `src/auth.ts` uses `http://localhost:${port}` as the OAuth `redirect_uri` (see `getCallbackUrl`, line ~286), and `server.listen(port, ...)` binds to all interfaces without an explicit host. On dual-stack Windows the browser may resolve `localhost` to `::1` while the loopback listener has the port claimed on `0.0.0.0` — or a corp hosts-file entry has `localhost` pointing somewhere unusable. Either way the callback is silently dropped.
The workaround (`firebase login --no-localhost`) works but is undiscoverable — the docs and CLI output on hang don't hint at it.
### Expected behavior
Two low-risk, additive fixes:
1. **Use `127.0.0.1` for the OAuth loopback**, per [Google's OAuth 2.0 for Native Apps guidance](https://developers.google.com/identity/protocols/oauth2/native-app#request-parameter-redirect_uri) which explicitly recommends `http://127.0.0.1:` over `http://localhost:` to avoid resolver ambiguity. Bind the http server to `127.0.0.1` too, so IPv6-only or hosts-file-locked machines can't miss the callback.
2. **After ~30s of no callback in `loginWithLocalhost`**, print a hint pointing at `firebase login --no-localhost` and `firebase login:ci`. Today the CLI hangs with only `Waiting for authentication...` — corp users often reach for Ctrl-C and start googling.
Files: `src/auth.ts` (`getCallbackUrl`, `loginWithLocalhost`).
Related (superset scope, generic auth failure): #8304. This issue is narrower and code-level.
Contributor guide
Research direction
Start in src/auth.ts by reading getCallbackUrl and loginWithLocalhost, then trace how the callback server is bound and how the waiting period is handled. Done means the loopback redirect and listener consistently use 127.0.0.1, and a roughly 30-second hang surfaces the --no-localhost and login:ci alternatives.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- authentication, cli
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100