Skip to content

fix: poll web-login done-check on the configured registry origin#191

Merged
owlstronaut merged 2 commits into
npm:mainfrom
manzoorwanijk:fix/web-login-doneurl-proxy-origin
Jun 18, 2026
Merged

fix: poll web-login done-check on the configured registry origin#191
owlstronaut merged 2 commits into
npm:mainfrom
manzoorwanijk:fix/web-login-doneurl-proxy-origin

Conversation

@manzoorwanijk

Copy link
Copy Markdown
Contributor

npm login --auth-type=web (the default) silently fails behind a proxy/mirror registry, then falls back to legacy couch auth, which also fails:

npm error code E401 - Incorrect or missing password
# or, depending on the proxy:
npm error Exit handler never called!
npm error code E405 - 405 Not Allowed - PUT .../-/user/org.couchdb.user:<name>

This is the common proxy/mirror case: the machine (or CI) is configured to use a private registry proxy/mirror with a different origin than registry.npmjs.org.

Why

Web login does two requests against the configured registry: a POST /-/v1/login that returns a loginUrl (opened in the browser) and a doneUrl (polled by npm until the token is issued).

A proxy/mirror forwards npm's response verbatim, so the doneUrl it returns points at the canonical https://registry.npmjs.org/-/v1/done?..., not at the proxy that actually created the session.
webAuth used that doneUrl as-is, so npm polled registry.npmjs.org directly and got a 403 (the session lives on the proxy, not on the public registry).
webAuth treats any 4xx/500 as "web login not supported" and falls back to couch (PUT /-/user/...), which proxies commonly reject (405/401) — the dead end users actually see.

This is the login analog of npm/cli#9550: a canonical registry.npmjs.org URL handed back by the server must be host-rewritten to the configured registry origin before npm fetches it.

How

replaceDoneUrlOrigin(doneUrl, opts.registry) rewrites the doneUrl to the configured registry's origin before polling, preserving any registry path prefix and the query string.
The session is created by the POST /-/v1/login to opts.registry, so the done-check must poll that same registry.

The rewrite is gated on the canonical npmjs host (done.hostname === 'registry.npmjs.org'), mirroring the conservative default of npm/cli#9550:

  • A proxy/mirror that leaks the canonical registry.npmjs.org doneUrl is corrected to poll the proxy.
  • A registry that intentionally serves the done endpoint on its own/other host is left untouched (a non-npmjs canonical host cannot be inferred here).
  • A non-proxied npmjs login is a no-op (same origin, no path prefix).

The browser-facing loginUrl is never rewritten.

References

Fixes npm/cli#8875
Related: npm/cli#9550

@manzoorwanijk
manzoorwanijk marked this pull request as ready for review June 16, 2026 17:37
@manzoorwanijk
manzoorwanijk requested a review from a team as a code owner June 16, 2026 17:37
@manzoorwanijk

Copy link
Copy Markdown
Contributor Author

CC: @owlstronaut

owlstronaut
owlstronaut previously approved these changes Jun 18, 2026
@manzoorwanijk

Copy link
Copy Markdown
Contributor Author

Let me fix the test coverage

@manzoorwanijk
manzoorwanijk force-pushed the fix/web-login-doneurl-proxy-origin branch from dae3cf8 to b359585 Compare June 18, 2026 19:22
@manzoorwanijk

manzoorwanijk commented Jun 18, 2026

Copy link
Copy Markdown
Contributor Author

@owlstronaut this fix will be backported to npm v11 when the dependency gets updated, right?

@owlstronaut

Copy link
Copy Markdown

@manzoorwanijk yeah we can do that

@manzoorwanijk

Copy link
Copy Markdown
Contributor Author

@manzoorwanijk yeah we can do that

Thanks

@owlstronaut
owlstronaut merged commit 3495f5f into npm:main Jun 18, 2026
21 checks passed
@manzoorwanijk
manzoorwanijk deleted the fix/web-login-doneurl-proxy-origin branch June 18, 2026 19:41
This was referenced Jun 18, 2026
owlstronaut pushed a commit that referenced this pull request Jun 18, 2026
🤖 I have created a release *beep* *boop*
---


##
[13.0.1](v13.0.0...v13.0.1)
(2026-06-18)
### Bug Fixes
*
[`3495f5f`](3495f5f)
[#191](#191) poll web-login
done-check on the configured registry origin (#191) (@manzoorwanijk)
### Chores
*
[`0ccab96`](0ccab96)
[#194](#194) template-oss-apply
(#194) (@owlstronaut)
*
[`92a1221`](92a1221)
[#192](#192) bump
@npmcli/template-oss from 5.1.0 to 5.1.1 (#192) (@dependabot[bot],
@npm-cli-bot)

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@github-actions github-actions Bot mentioned this pull request Jun 18, 2026
owlstronaut pushed a commit that referenced this pull request Jun 18, 2026
🤖 I have created a release *beep* *boop*
---


##
[12.0.2](v12.0.1...v12.0.2)
(2026-06-18)
### Bug Fixes
*
[`5afd320`](5afd320)
poll web-login done-check on the configured registry origin (#191)
(@manzoorwanijk)
### Dependencies
*
[`620903b`](620903b)
[#196](#196) `[email protected]`
### Chores
*
[`2580fde`](2580fde)
[#196](#196) template-oss-apply
(@owlstronaut)
*
[`efe56aa`](efe56aa)
[#196](#196)
`@npmcli/[email protected]` (@owlstronaut)
*
[`6fe9450`](6fe9450)
[#196](#196)
`@npmcli/[email protected]` (@owlstronaut)

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
owlstronaut pushed a commit to npm/cli that referenced this pull request Jun 19, 2026
)

Adds a regression test for #8875. The fix is in npm-profile
(npm/npm-profile#191).

This test is expected to be red until bundled `npm-profile` is bumped to
the release with the fix, and turns green after that.

## Why

`npm login --auth-type=web` silently fails behind a proxy/mirror: the
returned `doneUrl` points at the canonical `registry.npmjs.org` instead
of the proxy, so npm polls the wrong host, gets a `403`, and falls back
to couch auth (which also fails). Fixed in npm-profile by rewriting
`doneUrl` to the configured registry origin.

## How

- `@npmcli/mock-registry`: `weblogin()` gains an optional `doneRegistry`
to emulate a proxy advertising a `doneUrl` on another origin.
- `test/lib/commands/login.js`: proxy registry whose `doneUrl` is on
`registry.npmjs.org`; asserts the token is saved with no couch fallback.
Fails with the current bundled npm-profile, passes once it is bumped.

## References

Fixes #8875
Depends on: npm/npm-profile#191
Related: #9550
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.

[BUG] NPM Login Failure Blocking Package Installation

2 participants