Skip to content

Commit 16abc53

Browse files
committed
feat(auth): Add basic auth support for pathed registries
1 parent 1b78b1a commit 16abc53

File tree

3 files changed

+54
-3
lines changed

3 files changed

+54
-3
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ Please add one entry in this file for each change in Yarn's behavior. Use the sa
44

55
## Master
66

7-
*Nothing yet*
7+
- Adds support for basic auth for registries with paths, such as artifactory
8+
9+
[#5322](https://github.com/yarnpkg/yarn/pull/5322) - [**Karolis Narkevicius**](https://twitter.com/KidkArolis)
810

911
## 1.12.0
1012

__tests__/registries/npm-registry.js

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ import NpmRegistry from '../../src/registries/npm-registry.js';
66
import {BufferReporter} from '../../src/reporters/index.js';
77
import homeDir, {home} from '../../src/util/user-home-dir.js';
88

9+
function basicAuth(username, password): string {
10+
const pw = Buffer.from(String(password), 'base64').toString();
11+
return Buffer.from(String(username) + ':' + pw).toString('base64');
12+
}
13+
914
describe('normalizeConfig', () => {
1015
beforeAll(() => {
1116
process.env.REPLACE = 'REPLACED';
@@ -554,6 +559,46 @@ describe('request', () => {
554559
},
555560
],
556561
},
562+
{
563+
title: 'using username/password config for registries where pathnames play a role',
564+
config: {
565+
'@private:registry': 'https://registry.myorg.com/api/npm/registry/',
566+
'//registry.myorg.com/api/npm/registry/:username': 'scopedPrivateUsername',
567+
'//registry.myorg.com/api/npm/registry/:_password': 'scopedPrivatePassword',
568+
'//registry.myorg.com/api/packages/:username': 'scopedPrivateUsername',
569+
'//registry.myorg.com/api/packages/:_password': 'scopedPrivatePassword',
570+
},
571+
requests: [
572+
{
573+
url: '@private/pkg',
574+
pkg: '@private/pkg',
575+
expect: {
576+
root: 'https://registry.myorg.com/api/npm/registry/',
577+
auth: basicAuth('scopedPrivateUsername', 'scopedPrivatePassword'),
578+
basicAuth: true,
579+
},
580+
},
581+
{
582+
url: 'https://some.cdn.com/some-hash/@private-pkg-1.0.0.tar.gz',
583+
pkg: '@private/pkg',
584+
expect: {root: 'https://some.cdn.com', auth: false},
585+
},
586+
{
587+
url: 'https://some.cdn.com/@private/pkg',
588+
pkg: null,
589+
expect: {root: 'https://some.cdn.com', auth: false},
590+
},
591+
{
592+
url: 'https://registry.myorg.com/api/packages/private---pkg.tar.gz',
593+
pkg: '@private/pkg',
594+
expect: {
595+
root: 'https://registry.myorg.com/api/packages/',
596+
auth: basicAuth('scopedPrivateUsername', 'scopedPrivatePassword'),
597+
basicAuth: true,
598+
},
599+
},
600+
],
601+
},
557602
];
558603

559604
testCases.forEach(testCase => {
@@ -566,7 +611,11 @@ describe('request', () => {
566611
(req.skip ? it.skip : req.only ? it.only : it)(desc, () => {
567612
const requestParams = registry.request(req.url, {}, req.pkg);
568613
expect(requestParams.url.substr(0, req.expect.root.length)).toBe(req.expect.root);
569-
expect(requestParams.headers.authorization).toBe(req.expect.auth ? `Bearer ${req.expect.auth}` : undefined);
614+
if (req.expect.basicAuth) {
615+
expect(requestParams.headers.authorization).toBe(req.expect.auth ? `Basic ${req.expect.auth}` : undefined);
616+
} else {
617+
expect(requestParams.headers.authorization).toBe(req.expect.auth ? `Bearer ${req.expect.auth}` : undefined);
618+
}
570619
});
571620
});
572621
});

src/registries/npm-registry.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ export default class NpmRegistry extends Registry {
179179
const requestParts = urlParts(requestUrl);
180180
return !!Object.keys(config).find(option => {
181181
const parts = option.split(':');
182-
if (parts.length === 2 && parts[1] === '_authToken') {
182+
if ((parts.length === 2 && parts[1] === '_authToken') || parts[1] === '_password') {
183183
const registryParts = urlParts(parts[0]);
184184
if (requestParts.host === registryParts.host && requestParts.path.startsWith(registryParts.path)) {
185185
return true;

0 commit comments

Comments
 (0)