Skip to content

fix(auth): use 127.0.0.1 for OAuth loopback and surface --no-localhost hint - #11000

Open
Prajeeth-12 wants to merge 2 commits into
firebase:mainfrom
Prajeeth-12:fix/login-loopback-127001
Open

fix(auth): use 127.0.0.1 for OAuth loopback and surface --no-localhost hint#11000
Prajeeth-12 wants to merge 2 commits into
firebase:mainfrom
Prajeeth-12:fix/login-loopback-127001

Conversation

@Prajeeth-12

Copy link
Copy Markdown

Summary

Fixes #10750

On dual-stack Windows and corp-managed machines, localhost can resolve to ::1 or a hosts-file override while the HTTP server binds to 0.0.0.0, causing the OAuth callback to silently fail and the CLI to hang indefinitely on "Waiting for authentication...".

Changes

src/auth.ts:

  1. getCallbackUrl(): Changed redirect URI from http://localhost:<port> to http://127.0.0.1:<port>, per Google's OAuth 2.0 for Native Apps guidance which explicitly recommends 127.0.0.1 over localhost to avoid resolver ambiguity.

  2. loginWithLocalhost(): Bind the HTTP server to 127.0.0.1 explicitly instead of all interfaces, ensuring the listener and redirect URI agree on the address.

  3. Timeout hint: After 30 seconds with no callback, print a message pointing users to firebase login --no-localhost and firebase login:ci. Today the CLI hangs silently — this gives corp/VPN users an actionable next step.

Test plan

  • getCallbackUrl(3000) returns http://127.0.0.1:3000
  • Server binds to 127.0.0.1 only (not 0.0.0.0 or ::)
  • After 30s of no callback, hint is printed
  • Hint is not printed if auth succeeds within 30s (server stops listening)

🤖 Generated with Claude Code

@google-cla

google-cla Bot commented Aug 29, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the local authentication server to bind explicitly to 127.0.0.1 instead of localhost and introduces a 30-second timeout that displays troubleshooting instructions if authentication is delayed. The review feedback correctly points out that the setTimeout timer is not cleared when the server closes, which could keep the Node.js event loop active or trigger unexpected warnings. It is recommended to capture the timeout ID and clear it on the server's close event.

Comment thread src/auth.ts Outdated
Comment on lines +644 to +654
setTimeout(() => {
if (server.listening) {
logger.info();
logger.info(
"Having trouble? Try " +
clc.bold("firebase login --no-localhost") +
" or " +
clc.bold("firebase login:ci"),
);
}
}, 30_000);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The setTimeout timer is not cleared when the server closes (either upon successful login or failure). This can keep the Node.js event loop active, preventing the CLI process from exiting cleanly, or it can cause the warning message to be printed unexpectedly in long-running programmatic environments (like the VS Code extension) long after the login has completed.

We should capture the timeout ID and clear it when the server is closed.

Suggested change
setTimeout(() => {
if (server.listening) {
logger.info();
logger.info(
"Having trouble? Try " +
clc.bold("firebase login --no-localhost") +
" or " +
clc.bold("firebase login:ci"),
);
}
}, 30_000);
const timeoutId = setTimeout(() => {
if (server.listening) {
logger.info();
logger.info(
"Having trouble? Try " +
clc.bold("firebase login --no-localhost") +
" or " +
clc.bold("firebase login:ci"),
);
}
}, 30_000);
server.on("close", () => {
clearTimeout(timeoutId);
});

…t hint

On dual-stack Windows and corp-managed machines, `localhost` can
resolve to `::1` or a hosts-file override while the HTTP server
binds to `0.0.0.0`. This causes the OAuth callback to silently fail.

Per Google's OAuth 2.0 for Native Apps guidance, use `127.0.0.1`
for both the redirect_uri and the server bind address to avoid
resolver ambiguity.

Also prints a hint about `--no-localhost` and `login:ci` after 30s
of no callback, so users stuck on a hang have an actionable next step.

Fixes firebase#10750
@Prajeeth-12
Prajeeth-12 force-pushed the fix/login-loopback-127001 branch from e05202f to 7221441 Compare August 30, 2026 15:05
@Prajeeth-12

Copy link
Copy Markdown
Author

@googlebot I fixed it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

firebase login: use 127.0.0.1 (not localhost) for OAuth loopback + surface --no-localhost hint on hang

2 participants