@@ -4,8 +4,8 @@ const npa = require('npm-package-arg')
4
4
const { URL } = require ( 'url' )
5
5
6
6
// Find the longest registry key that is used for some kind of auth
7
- // in the options.
8
- const regKeyFromURI = ( uri , opts ) => {
7
+ // in the options. Returns the registry key and the auth config.
8
+ const regFromURI = ( uri , opts ) => {
9
9
const parsed = new URL ( uri )
10
10
// try to find a config key indicating we have auth for this registry
11
11
// can be one of :_authToken, :_auth, :_password and :username, or
@@ -14,23 +14,40 @@ const regKeyFromURI = (uri, opts) => {
14
14
// stopping when we reach '//'.
15
15
let regKey = `//${ parsed . host } ${ parsed . pathname } `
16
16
while ( regKey . length > '//' . length ) {
17
+ const authKey = hasAuth ( regKey , opts )
17
18
// got some auth for this URI
18
- if ( hasAuth ( regKey , opts ) ) {
19
- return regKey
19
+ if ( authKey ) {
20
+ return { regKey, authKey }
20
21
}
21
22
22
23
// can be either //host/some/path/:_auth or //host/some/path:_auth
23
24
// walk up by removing EITHER what's after the slash OR the slash itself
24
25
regKey = regKey . replace ( / ( [ ^ / ] + | \/ ) $ / , '' )
25
26
}
27
+ return { regKey : false , authKey : null }
26
28
}
27
29
28
- const hasAuth = ( regKey , opts ) => (
29
- opts [ `${ regKey } :_authToken` ] ||
30
- opts [ `${ regKey } :_auth` ] ||
31
- opts [ `${ regKey } :username` ] && opts [ `${ regKey } :_password` ] ||
32
- opts [ `${ regKey } :certfile` ] && opts [ `${ regKey } :keyfile` ]
33
- )
30
+ // Not only do we want to know if there is auth, but if we are calling `npm
31
+ // logout` we want to know what config value specifically provided it. This is
32
+ // so we can look up where the config came from to delete it (i.e. user vs
33
+ // project)
34
+ const hasAuth = ( regKey , opts ) => {
35
+ if ( opts [ `${ regKey } :_authToken` ] ) {
36
+ return '_authToken'
37
+ }
38
+ if ( opts [ `${ regKey } :_auth` ] ) {
39
+ return '_auth'
40
+ }
41
+ if ( opts [ `${ regKey } :username` ] && opts [ `${ regKey } :_password` ] ) {
42
+ // 'password' can be inferred to also be present
43
+ return 'username'
44
+ }
45
+ if ( opts [ `${ regKey } :certfile` ] && opts [ `${ regKey } :keyfile` ] ) {
46
+ // 'keyfile' can be inferred to also be present
47
+ return 'certfile'
48
+ }
49
+ return false
50
+ }
34
51
35
52
const sameHost = ( a , b ) => {
36
53
const parsedA = new URL ( a )
@@ -63,11 +80,14 @@ const getAuth = (uri, opts = {}) => {
63
80
if ( ! uri ) {
64
81
throw new Error ( 'URI is required' )
65
82
}
66
- const regKey = regKeyFromURI ( uri , forceAuth || opts )
83
+ const { regKey, authKey } = regFromURI ( uri , forceAuth || opts )
67
84
68
85
// we are only allowed to use what's in forceAuth if specified
69
86
if ( forceAuth && ! regKey ) {
70
87
return new Auth ( {
88
+ // if we force auth we don't want to refer back to anything in config
89
+ regKey : false ,
90
+ authKey : null ,
71
91
scopeAuthKey : null ,
72
92
token : forceAuth . _authToken || forceAuth . token ,
73
93
username : forceAuth . username ,
@@ -88,8 +108,8 @@ const getAuth = (uri, opts = {}) => {
88
108
// registry where we logged in, but the same auth SHOULD be sent
89
109
// to that artifact host, then we track where it was coming in from,
90
110
// and warn the user if we get a 4xx error on it.
91
- const scopeAuthKey = regKeyFromURI ( registry , opts )
92
- return new Auth ( { scopeAuthKey } )
111
+ const { regKey : scopeAuthKey , authKey : _authKey } = regFromURI ( registry , opts )
112
+ return new Auth ( { scopeAuthKey, regKey : scopeAuthKey , authKey : _authKey } )
93
113
}
94
114
}
95
115
@@ -104,6 +124,8 @@ const getAuth = (uri, opts = {}) => {
104
124
105
125
return new Auth ( {
106
126
scopeAuthKey : null ,
127
+ regKey,
128
+ authKey,
107
129
token,
108
130
auth,
109
131
username,
@@ -114,8 +136,22 @@ const getAuth = (uri, opts = {}) => {
114
136
}
115
137
116
138
class Auth {
117
- constructor ( { token, auth, username, password, scopeAuthKey, certfile, keyfile } ) {
139
+ constructor ( {
140
+ token,
141
+ auth,
142
+ username,
143
+ password,
144
+ scopeAuthKey,
145
+ certfile,
146
+ keyfile,
147
+ regKey,
148
+ authKey,
149
+ } ) {
150
+ // same as regKey but only present for scoped auth. Should have been named scopeRegKey
118
151
this . scopeAuthKey = scopeAuthKey
152
+ // `${regKey}:${authKey}` will get you back to the auth config that gave us auth
153
+ this . regKey = regKey
154
+ this . authKey = authKey
119
155
this . token = null
120
156
this . auth = null
121
157
this . isBasicAuth = false
0 commit comments