From f2eddaf8eb56a5b439a09020bcf461850da7b893 Mon Sep 17 00:00:00 2001 From: Manzoor Wani Date: Fri, 19 Jun 2026 20:12:30 +0530 Subject: [PATCH] chore: add web-login proxy doneUrl regression for npm-profile fix (#9560) Adds a regression test for npm/cli#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 npm/cli#8875 Depends on: npm/npm-profile#191 Related: npm/cli#9550 (cherry picked from commit 059c06e52f00e2d9cd2fa28baf6a6acd5be3b297) --- mock-registry/lib/index.js | 9 ++++++--- test/lib/commands/login.js | 13 +++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/mock-registry/lib/index.js b/mock-registry/lib/index.js index b99dfe6b156aa..504aaa5166526 100644 --- a/mock-registry/lib/index.js +++ b/mock-registry/lib/index.js @@ -282,15 +282,18 @@ class MockRegistry { .reply(200, { token }) } - weblogin ({ token = 'npm_default-test-token' }) { - const doneUrl = new URL('/npm-cli-test/done', this.origin).href + weblogin ({ token = 'npm_default-test-token', doneRegistry } = {}) { + const donePath = '/npm-cli-test/done' + // doneRegistry emulates a proxy/mirror that advertises a doneUrl on a different origin than the configured registry. + // The poll itself is always mocked on this registry, since that is where the session lives. + const doneUrl = new URL(donePath, doneRegistry ?? this.origin).href const loginUrl = new URL('/npm-cli-test/login/cli/00000000-0000-0000-0000-000000000000', this.origin).href this.nock = this.nock .post(this.fullPath('/-/v1/login'), () => { return true }) .reply(200, { doneUrl, loginUrl }) - .get('/npm-cli-test/done') + .get(donePath) .reply(200, { token }) } diff --git a/test/lib/commands/login.js b/test/lib/commands/login.js index 55568edd09f9d..4ebc7147e46ae 100644 --- a/test/lib/commands/login.js +++ b/test/lib/commands/login.js @@ -130,6 +130,19 @@ t.test('web', t => { }) t.match(outputs[0], '/npm-cli-test/login/cli/00000000-0000-0000-0000-000000000000') }) + t.test('proxy registry whose doneUrl points at the canonical registry', async t => { + // Regression for npm/cli#8875: a proxy/mirror returns a doneUrl on registry.npmjs.org. + // npm must poll the configured proxy where the session lives, not the canonical registry. + const proxy = 'https://proxy.registry.example/' + const { npm, registry, login, rc } = await mockLogin(t, { + registry: proxy, + config: { 'auth-type': 'web', registry: proxy }, + }) + registry.weblogin({ token: 'npm_proxy-token', doneRegistry: 'https://registry.npmjs.org' }) + await login.exec([]) + t.same(npm.config.get('//proxy.registry.example/:_authToken'), 'npm_proxy-token') + t.match(rc(), { '//proxy.registry.example/:_authToken': 'npm_proxy-token' }) + }) t.test('server error', async t => { const { registry, login } = await mockLogin(t, { config: { 'auth-type': 'web' },