@verdaccio/auth 9.0.0-next-9.3 → 9.0.0-next-9.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/_virtual/_rolldown/runtime.js +23 -0
- package/build/auth.d.ts +3 -3
- package/build/auth.js +421 -668
- package/build/auth.js.map +1 -1
- package/build/auth.mjs +420 -0
- package/build/auth.mjs.map +1 -0
- package/build/index.js +19 -39
- package/build/index.mjs +3 -0
- package/build/types.d.ts +4 -4
- package/build/utils.d.ts +3 -3
- package/build/utils.js +156 -238
- package/build/utils.js.map +1 -1
- package/build/utils.mjs +168 -0
- package/build/utils.mjs.map +1 -0
- package/package.json +24 -13
- package/build/index.js.map +0 -1
- package/build/types.js +0 -6
- package/build/types.js.map +0 -1
package/build/auth.js
CHANGED
|
@@ -1,670 +1,423 @@
|
|
|
1
|
-
|
|
1
|
+
const require_runtime = require("./_virtual/_rolldown/runtime.js");
|
|
2
|
+
const require_utils = require("./utils.js");
|
|
3
|
+
let debug = require("debug");
|
|
4
|
+
debug = require_runtime.__toESM(debug);
|
|
5
|
+
let lodash = require("lodash");
|
|
6
|
+
lodash = require_runtime.__toESM(lodash);
|
|
7
|
+
let verdaccio_htpasswd = require("verdaccio-htpasswd");
|
|
8
|
+
let _verdaccio_config = require("@verdaccio/config");
|
|
9
|
+
let _verdaccio_core = require("@verdaccio/core");
|
|
10
|
+
let _verdaccio_loaders = require("@verdaccio/loaders");
|
|
11
|
+
let _verdaccio_signature = require("@verdaccio/signature");
|
|
12
|
+
//#region src/auth.ts
|
|
13
|
+
var debug$1 = (0, debug.default)("verdaccio:auth");
|
|
14
|
+
var Auth = class {
|
|
15
|
+
config;
|
|
16
|
+
secret;
|
|
17
|
+
logger;
|
|
18
|
+
plugins;
|
|
19
|
+
options;
|
|
20
|
+
constructor(config, logger, options = { legacyMergeConfigs: false }) {
|
|
21
|
+
this.config = config;
|
|
22
|
+
this.secret = config.secret;
|
|
23
|
+
this.logger = logger;
|
|
24
|
+
this.plugins = [];
|
|
25
|
+
this.options = options;
|
|
26
|
+
if (!this.secret) throw new TypeError("secret it is required value on initialize the auth class");
|
|
27
|
+
}
|
|
28
|
+
async init() {
|
|
29
|
+
let plugins = await this.loadPlugin();
|
|
30
|
+
debug$1("auth plugins found %s", plugins.length);
|
|
31
|
+
if (this.config.auth !== null && (!plugins || plugins.length === 0)) plugins = this.loadDefaultPlugin();
|
|
32
|
+
this.plugins = plugins;
|
|
33
|
+
this.applyFallbackPluginMethods();
|
|
34
|
+
}
|
|
35
|
+
loadDefaultPlugin() {
|
|
36
|
+
debug$1("load default auth plugin");
|
|
37
|
+
let authPlugin;
|
|
38
|
+
try {
|
|
39
|
+
authPlugin = new verdaccio_htpasswd.HTPasswd({ file: "./htpasswd" }, {
|
|
40
|
+
config: this.config,
|
|
41
|
+
logger: this.logger
|
|
42
|
+
});
|
|
43
|
+
this.logger.info({
|
|
44
|
+
name: "verdaccio-htpasswd",
|
|
45
|
+
pluginCategory: _verdaccio_core.PLUGIN_CATEGORY.AUTHENTICATION
|
|
46
|
+
}, "plugin @{name} successfully loaded (@{pluginCategory})");
|
|
47
|
+
} catch (error) {
|
|
48
|
+
debug$1("error on loading auth htpasswd plugin stack: %o", error);
|
|
49
|
+
this.logger.info({}, "no auth plugin has been found");
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
return [authPlugin];
|
|
53
|
+
}
|
|
54
|
+
async loadPlugin() {
|
|
55
|
+
return (0, _verdaccio_loaders.asyncLoadPlugin)(this.config.auth, {
|
|
56
|
+
config: this.config,
|
|
57
|
+
logger: this.logger
|
|
58
|
+
}, (plugin) => {
|
|
59
|
+
const { authenticate, allow_access, allow_publish } = plugin;
|
|
60
|
+
return typeof authenticate !== "undefined" || typeof allow_access !== "undefined" || typeof allow_publish !== "undefined";
|
|
61
|
+
}, this.options.legacyMergeConfigs, this.config?.server?.pluginPrefix ?? _verdaccio_core.PLUGIN_PREFIX, _verdaccio_core.PLUGIN_CATEGORY.AUTHENTICATION);
|
|
62
|
+
}
|
|
63
|
+
applyFallbackPluginMethods() {
|
|
64
|
+
this.plugins.push(require_utils.getDefaultPluginMethods(this.logger));
|
|
65
|
+
}
|
|
66
|
+
changePassword(username, password, newPassword, cb) {
|
|
67
|
+
const validPlugins = lodash.default.filter(this.plugins, (plugin) => lodash.default.isFunction(plugin.changePassword));
|
|
68
|
+
if (lodash.default.isEmpty(validPlugins)) return cb(_verdaccio_core.errorUtils.getInternalError(_verdaccio_core.SUPPORT_ERRORS.PLUGIN_MISSING_INTERFACE));
|
|
69
|
+
for (const plugin of validPlugins) if (lodash.default.isNil(plugin) || lodash.default.isFunction(plugin.changePassword) === false) {
|
|
70
|
+
debug$1("auth plugin does not implement changePassword, trying next one");
|
|
71
|
+
continue;
|
|
72
|
+
} else {
|
|
73
|
+
debug$1("updating password for %o", username);
|
|
74
|
+
plugin.changePassword(username, password, newPassword, (err, profile) => {
|
|
75
|
+
if (err) {
|
|
76
|
+
this.logger.error({
|
|
77
|
+
username,
|
|
78
|
+
err
|
|
79
|
+
}, `An error has been produced
|
|
80
|
+
updating the password for @{username}. Error: @{err.message}`);
|
|
81
|
+
return cb(err);
|
|
82
|
+
}
|
|
83
|
+
debug$1("updated password for %o was successful", username);
|
|
84
|
+
return cb(null, profile);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
async invalidateToken(token) {
|
|
89
|
+
console.log("invalidate token pending to implement", token);
|
|
90
|
+
return Promise.resolve();
|
|
91
|
+
}
|
|
92
|
+
authenticate(username, password, cb) {
|
|
93
|
+
const plugins = this.plugins.slice(0);
|
|
94
|
+
(function next() {
|
|
95
|
+
const plugin = plugins.shift();
|
|
96
|
+
if (typeof plugin?.authenticate !== "function") return next();
|
|
97
|
+
debug$1("authenticating %o", username);
|
|
98
|
+
plugin.authenticate(username, password, function(err, groups) {
|
|
99
|
+
if (err) {
|
|
100
|
+
debug$1("authenticating for user %o failed. Error: %o", username, err?.message);
|
|
101
|
+
return cb(err);
|
|
102
|
+
}
|
|
103
|
+
if (!!groups && groups.length !== 0) {
|
|
104
|
+
if (lodash.default.isString(groups)) throw new TypeError("plugin group error: invalid type for function");
|
|
105
|
+
if (!lodash.default.isArray(groups)) throw new TypeError(_verdaccio_core.API_ERROR.BAD_FORMAT_USER_GROUP);
|
|
106
|
+
debug$1("authentication for user %o was successfully. Groups: %o", username, groups);
|
|
107
|
+
return cb(err, (0, _verdaccio_config.createRemoteUser)(username, groups));
|
|
108
|
+
}
|
|
109
|
+
next();
|
|
110
|
+
});
|
|
111
|
+
})();
|
|
112
|
+
}
|
|
113
|
+
add_user(user, password, cb) {
|
|
114
|
+
const self = this;
|
|
115
|
+
const plugins = this.plugins.slice(0);
|
|
116
|
+
debug$1("add user %o", user);
|
|
117
|
+
(function next() {
|
|
118
|
+
let method = "adduser";
|
|
119
|
+
const plugin = plugins.shift();
|
|
120
|
+
if (typeof plugin.adduser === "undefined" && typeof plugin.add_user === "function") {
|
|
121
|
+
method = "add_user";
|
|
122
|
+
_verdaccio_core.warningUtils.emit(_verdaccio_core.warningUtils.Codes.VERWAR006);
|
|
123
|
+
}
|
|
124
|
+
if (typeof plugin[method] !== "function") next();
|
|
125
|
+
else plugin[method](user, password, function(err, ok) {
|
|
126
|
+
if (err) {
|
|
127
|
+
debug$1("the user %o could not be added. Error: %o", user, err?.message);
|
|
128
|
+
return cb(err);
|
|
129
|
+
}
|
|
130
|
+
if (ok) {
|
|
131
|
+
debug$1("the user %o has been added", user);
|
|
132
|
+
return self.authenticate(user, password, cb);
|
|
133
|
+
}
|
|
134
|
+
debug$1("user could not be added, skip to next auth plugin");
|
|
135
|
+
next();
|
|
136
|
+
});
|
|
137
|
+
})();
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Allow user to access a package.
|
|
141
|
+
*/
|
|
142
|
+
allow_access({ packageName, packageVersion }, user, callback) {
|
|
143
|
+
const plugins = this.plugins.slice(0);
|
|
144
|
+
const pkg = Object.assign({
|
|
145
|
+
name: packageName,
|
|
146
|
+
version: packageVersion
|
|
147
|
+
}, _verdaccio_core.authUtils.getMatchedPackagesSpec(packageName, this.config.packages));
|
|
148
|
+
debug$1("check access permissions for user %o to package %o", user.name, packageName);
|
|
149
|
+
const next = () => {
|
|
150
|
+
const plugin = plugins.shift();
|
|
151
|
+
if (typeof plugin?.allow_access !== "function") {
|
|
152
|
+
debug$1("plugin does not implement allow_access");
|
|
153
|
+
return next();
|
|
154
|
+
}
|
|
155
|
+
plugin.allow_access(user, pkg, (err, ok) => {
|
|
156
|
+
if (err) {
|
|
157
|
+
debug$1("forbidden access. Error: %o", err);
|
|
158
|
+
return callback(err);
|
|
159
|
+
}
|
|
160
|
+
if (ok) {
|
|
161
|
+
debug$1("access was granted");
|
|
162
|
+
this.logger.trace({
|
|
163
|
+
user: user.name,
|
|
164
|
+
name: pkg.name
|
|
165
|
+
}, `access was granted for @{name} by @{user}`);
|
|
166
|
+
return callback(null, ok);
|
|
167
|
+
}
|
|
168
|
+
debug$1("access was denied. Rolling to next plugin");
|
|
169
|
+
this.logger.trace({
|
|
170
|
+
user: user.name,
|
|
171
|
+
name: pkg.name
|
|
172
|
+
}, `intermediate access denial for @{name} by @{user}, rolling to next plugin`);
|
|
173
|
+
return next();
|
|
174
|
+
});
|
|
175
|
+
};
|
|
176
|
+
return next();
|
|
177
|
+
}
|
|
178
|
+
allow_unpublish({ packageName, packageVersion }, user, callback) {
|
|
179
|
+
const plugins = this.plugins.slice(0);
|
|
180
|
+
const pkg = Object.assign({
|
|
181
|
+
name: packageName,
|
|
182
|
+
version: packageVersion
|
|
183
|
+
}, _verdaccio_core.authUtils.getMatchedPackagesSpec(packageName, this.config.packages));
|
|
184
|
+
debug$1("check unpublish permissions for user %o to package %o", user.name, packageName);
|
|
185
|
+
const next = () => {
|
|
186
|
+
const plugin = plugins.shift();
|
|
187
|
+
if (typeof plugin?.allow_unpublish !== "function") {
|
|
188
|
+
debug$1("plugin does not implement allow_unpublish");
|
|
189
|
+
return next();
|
|
190
|
+
}
|
|
191
|
+
plugin.allow_unpublish(user, pkg, (err, ok) => {
|
|
192
|
+
if (err) {
|
|
193
|
+
debug$1("forbidden unpublish. Error: %o", err);
|
|
194
|
+
return callback(err);
|
|
195
|
+
}
|
|
196
|
+
if (lodash.default.isNil(ok) === true) {
|
|
197
|
+
debug$1("bypass unpublish for %o, publish will handle the access", packageName);
|
|
198
|
+
this.logger.trace({
|
|
199
|
+
user: user.name,
|
|
200
|
+
name: pkg.name
|
|
201
|
+
}, `bypass unpublish for @{name} by @{user}, publish will handle the access`);
|
|
202
|
+
return this.allow_publish({
|
|
203
|
+
packageName,
|
|
204
|
+
packageVersion
|
|
205
|
+
}, user, callback);
|
|
206
|
+
}
|
|
207
|
+
if (ok) {
|
|
208
|
+
debug$1("unpublish was granted");
|
|
209
|
+
this.logger.trace({
|
|
210
|
+
user: user.name,
|
|
211
|
+
name: pkg.name
|
|
212
|
+
}, `unpublish was granted for @{name} by @{user}`);
|
|
213
|
+
return callback(null, ok);
|
|
214
|
+
}
|
|
215
|
+
debug$1("unpublish was denied. Rolling to next plugin");
|
|
216
|
+
this.logger.trace({
|
|
217
|
+
user: user.name,
|
|
218
|
+
name: pkg.name
|
|
219
|
+
}, `intermediate unpublish denial for @{name} by @{user}, rolling to next plugin`);
|
|
220
|
+
return next();
|
|
221
|
+
});
|
|
222
|
+
};
|
|
223
|
+
return next();
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Allow user to publish a package.
|
|
227
|
+
*/
|
|
228
|
+
allow_publish({ packageName, packageVersion }, user, callback) {
|
|
229
|
+
const plugins = this.plugins.slice(0);
|
|
230
|
+
const pkg = Object.assign({
|
|
231
|
+
name: packageName,
|
|
232
|
+
version: packageVersion
|
|
233
|
+
}, _verdaccio_core.authUtils.getMatchedPackagesSpec(packageName, this.config.packages));
|
|
234
|
+
debug$1("check publish permissions for user %o to package %o", user.name, packageName);
|
|
235
|
+
const next = () => {
|
|
236
|
+
const plugin = plugins.shift();
|
|
237
|
+
if (typeof plugin?.allow_publish !== "function") {
|
|
238
|
+
debug$1("plugin does not implement allow_publish");
|
|
239
|
+
return next();
|
|
240
|
+
}
|
|
241
|
+
plugin.allow_publish(user, pkg, (err, ok) => {
|
|
242
|
+
if (err) {
|
|
243
|
+
debug$1("forbidden publish. Error: %o", err);
|
|
244
|
+
return callback(err);
|
|
245
|
+
}
|
|
246
|
+
if (ok) {
|
|
247
|
+
debug$1("publish was granted");
|
|
248
|
+
this.logger.trace({
|
|
249
|
+
user: user.name,
|
|
250
|
+
name: pkg.name
|
|
251
|
+
}, `publish was granted for @{name} by @{user}`);
|
|
252
|
+
return callback(null, ok);
|
|
253
|
+
}
|
|
254
|
+
debug$1("publish was denied. Rolling to next plugin");
|
|
255
|
+
this.logger.trace({
|
|
256
|
+
user: user.name,
|
|
257
|
+
name: pkg.name
|
|
258
|
+
}, `intermediate publish denial for @{name} by @{user}, rolling to next plugin`);
|
|
259
|
+
return next();
|
|
260
|
+
});
|
|
261
|
+
};
|
|
262
|
+
return next();
|
|
263
|
+
}
|
|
264
|
+
apiJWTmiddleware() {
|
|
265
|
+
debug$1("jwt middleware");
|
|
266
|
+
const plugins = this.plugins.slice(0);
|
|
267
|
+
const helpers = {
|
|
268
|
+
createAnonymousRemoteUser: _verdaccio_config.createAnonymousRemoteUser,
|
|
269
|
+
createRemoteUser: _verdaccio_config.createRemoteUser
|
|
270
|
+
};
|
|
271
|
+
for (const plugin of plugins) if (plugin.apiJWTmiddleware) return plugin.apiJWTmiddleware(helpers);
|
|
272
|
+
return (req, res, _next) => {
|
|
273
|
+
req.pause();
|
|
274
|
+
const next = function(err) {
|
|
275
|
+
req.resume();
|
|
276
|
+
if (err) req.remote_user.error = err.message;
|
|
277
|
+
return _next();
|
|
278
|
+
};
|
|
279
|
+
const remoteUser = (0, _verdaccio_config.createAnonymousRemoteUser)();
|
|
280
|
+
req.remote_user = remoteUser;
|
|
281
|
+
res.locals.remote_user = remoteUser;
|
|
282
|
+
const { authorization } = req.headers;
|
|
283
|
+
if (lodash.default.isNil(authorization)) {
|
|
284
|
+
debug$1("jwt, authentication header is missing");
|
|
285
|
+
return next();
|
|
286
|
+
}
|
|
287
|
+
if (!require_utils.isAuthHeaderValid(authorization)) {
|
|
288
|
+
debug$1("api middleware authentication heather is invalid");
|
|
289
|
+
return next(_verdaccio_core.errorUtils.getBadRequest(_verdaccio_core.API_ERROR.BAD_AUTH_HEADER));
|
|
290
|
+
}
|
|
291
|
+
const { secret, security } = this.config;
|
|
292
|
+
if (require_utils.isAESLegacy(security)) {
|
|
293
|
+
debug$1("api middleware using legacy auth token");
|
|
294
|
+
this.handleAESMiddleware(req, security, secret, authorization, next);
|
|
295
|
+
} else {
|
|
296
|
+
debug$1("api middleware using JWT auth token");
|
|
297
|
+
this.handleJWTAPIMiddleware(req, security, secret, authorization, next);
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
handleJWTAPIMiddleware(req, security, secret, authorization, next) {
|
|
302
|
+
debug$1("handle JWT api middleware");
|
|
303
|
+
const { scheme, token } = require_utils.parseAuthTokenHeader(authorization);
|
|
304
|
+
if (scheme.toUpperCase() === _verdaccio_core.TOKEN_BASIC.toUpperCase()) {
|
|
305
|
+
debug$1("handle basic token");
|
|
306
|
+
const parsedCredentials = (0, _verdaccio_signature.parseBasicPayload)(require_utils.convertPayloadToBase64(token).toString());
|
|
307
|
+
if (!parsedCredentials) {
|
|
308
|
+
debug$1("invalid basic credentials format (missing colon separator)");
|
|
309
|
+
next(_verdaccio_core.errorUtils.getBadRequest(_verdaccio_core.API_ERROR.BAD_USERNAME_PASSWORD));
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
const { user, password } = parsedCredentials;
|
|
313
|
+
debug$1("authenticating %o", user);
|
|
314
|
+
this.authenticate(user, password, (err, user) => {
|
|
315
|
+
if (!err) {
|
|
316
|
+
debug$1("generating a remote user");
|
|
317
|
+
req.remote_user = user;
|
|
318
|
+
next();
|
|
319
|
+
} else {
|
|
320
|
+
debug$1("generating anonymous user");
|
|
321
|
+
req.remote_user = (0, _verdaccio_config.createAnonymousRemoteUser)();
|
|
322
|
+
next(err);
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
} else {
|
|
326
|
+
debug$1("handle jwt token");
|
|
327
|
+
const credentials = require_utils.getMiddlewareCredentials(security, secret, authorization);
|
|
328
|
+
if (credentials) {
|
|
329
|
+
req.remote_user = credentials;
|
|
330
|
+
debug$1("generating a remote user");
|
|
331
|
+
next();
|
|
332
|
+
} else {
|
|
333
|
+
debug$1("jwt invalid token");
|
|
334
|
+
next(_verdaccio_core.errorUtils.getForbidden(_verdaccio_core.API_ERROR.BAD_USERNAME_PASSWORD));
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
handleAESMiddleware(req, security, secret, authorization, next) {
|
|
339
|
+
debug$1("handle legacy api middleware");
|
|
340
|
+
debug$1("api middleware has a secret? %o", typeof secret === "string");
|
|
341
|
+
debug$1("api middleware authorization %o", typeof authorization === "string");
|
|
342
|
+
const credentials = require_utils.getMiddlewareCredentials(security, secret, authorization);
|
|
343
|
+
debug$1("api middleware credentials %o", credentials?.name);
|
|
344
|
+
if (credentials) {
|
|
345
|
+
const { user, password } = credentials;
|
|
346
|
+
debug$1("authenticating %o", user);
|
|
347
|
+
this.authenticate(user, password, (err, user) => {
|
|
348
|
+
if (!err) {
|
|
349
|
+
req.remote_user = user;
|
|
350
|
+
debug$1("generating a remote user");
|
|
351
|
+
next();
|
|
352
|
+
} else {
|
|
353
|
+
req.remote_user = (0, _verdaccio_config.createAnonymousRemoteUser)();
|
|
354
|
+
debug$1("generating anonymous user");
|
|
355
|
+
next(err);
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
} else {
|
|
359
|
+
debug$1("legacy invalid header");
|
|
360
|
+
return next(_verdaccio_core.errorUtils.getBadRequest(_verdaccio_core.API_ERROR.BAD_AUTH_HEADER));
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
_isRemoteUserValid(remote_user) {
|
|
364
|
+
return lodash.default.isUndefined(remote_user) === false && lodash.default.isUndefined(remote_user?.name) === false;
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* JWT middleware for WebUI
|
|
368
|
+
*/
|
|
369
|
+
webUIJWTmiddleware() {
|
|
370
|
+
return (req, res, _next) => {
|
|
371
|
+
if (this._isRemoteUserValid(req.remote_user)) return _next();
|
|
372
|
+
req.pause();
|
|
373
|
+
const next = (err) => {
|
|
374
|
+
req.resume();
|
|
375
|
+
if (err) {
|
|
376
|
+
req.remote_user.error = err.message;
|
|
377
|
+
res.status(err.statusCode).send(err.message);
|
|
378
|
+
}
|
|
379
|
+
return _next();
|
|
380
|
+
};
|
|
381
|
+
const { authorization } = req.headers;
|
|
382
|
+
if (lodash.default.isNil(authorization)) return next();
|
|
383
|
+
if (!require_utils.isAuthHeaderValid(authorization)) return next(_verdaccio_core.errorUtils.getBadRequest(_verdaccio_core.API_ERROR.BAD_AUTH_HEADER));
|
|
384
|
+
const token = (authorization || "").replace(`${_verdaccio_core.TOKEN_BEARER} `, "");
|
|
385
|
+
if (!token) return next();
|
|
386
|
+
let credentials;
|
|
387
|
+
try {
|
|
388
|
+
credentials = require_utils.verifyJWTPayload(token, this.config.secret, this.config.security);
|
|
389
|
+
} catch {}
|
|
390
|
+
if (this._isRemoteUserValid(credentials)) {
|
|
391
|
+
const { name, groups } = credentials;
|
|
392
|
+
req.remote_user = (0, _verdaccio_config.createRemoteUser)(name, groups);
|
|
393
|
+
} else req.remote_user = (0, _verdaccio_config.createAnonymousRemoteUser)();
|
|
394
|
+
next();
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
async jwtEncrypt(user, signOptions) {
|
|
398
|
+
const { real_groups, name, groups } = user;
|
|
399
|
+
debug$1("jwt encrypt %o", name);
|
|
400
|
+
const realGroupsValidated = lodash.default.isNil(real_groups) ? [] : real_groups;
|
|
401
|
+
return await (0, _verdaccio_signature.signPayload)({
|
|
402
|
+
real_groups: realGroupsValidated,
|
|
403
|
+
name,
|
|
404
|
+
groups: lodash.default.isNil(groups) ? real_groups : Array.from(new Set([...groups.concat(realGroupsValidated)]))
|
|
405
|
+
}, this.secret, signOptions);
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* Encrypt a string.
|
|
409
|
+
*/
|
|
410
|
+
aesEncrypt(value) {
|
|
411
|
+
if (this.secret.length === _verdaccio_config.TOKEN_VALID_LENGTH) {
|
|
412
|
+
debug$1("signing with enhanced aes legacy");
|
|
413
|
+
return (0, _verdaccio_signature.aesEncrypt)(value, this.secret);
|
|
414
|
+
} else {
|
|
415
|
+
debug$1("signing with enhanced aes deprecated legacy");
|
|
416
|
+
return (0, _verdaccio_signature.aesEncryptDeprecated)(Buffer.from(value), this.secret).toString("base64");
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
};
|
|
420
|
+
//#endregion
|
|
421
|
+
exports.Auth = Auth;
|
|
2
422
|
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.Auth = void 0;
|
|
7
|
-
var _debug = _interopRequireDefault(require("debug"));
|
|
8
|
-
var _lodash = _interopRequireDefault(require("lodash"));
|
|
9
|
-
var _verdaccioHtpasswd = require("verdaccio-htpasswd");
|
|
10
|
-
var _config = require("@verdaccio/config");
|
|
11
|
-
var _core = require("@verdaccio/core");
|
|
12
|
-
var _loaders = require("@verdaccio/loaders");
|
|
13
|
-
var _signature = require("@verdaccio/signature");
|
|
14
|
-
var _utils = require("./utils");
|
|
15
|
-
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
|
|
16
|
-
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
17
|
-
function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
|
|
18
|
-
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
19
|
-
function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
|
|
20
|
-
function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
|
|
21
|
-
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
|
|
22
|
-
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
23
|
-
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
24
|
-
function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i["return"]) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
|
|
25
|
-
function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
|
|
26
|
-
function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
|
|
27
|
-
function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
|
|
28
|
-
function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
|
|
29
|
-
function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
|
|
30
|
-
function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
|
|
31
|
-
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
|
|
32
|
-
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
33
|
-
var debug = (0, _debug["default"])('verdaccio:auth');
|
|
34
|
-
var Auth = exports.Auth = /*#__PURE__*/function () {
|
|
35
|
-
function Auth(config, logger) {
|
|
36
|
-
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
|
|
37
|
-
legacyMergeConfigs: false
|
|
38
|
-
};
|
|
39
|
-
_classCallCheck(this, Auth);
|
|
40
|
-
this.config = config;
|
|
41
|
-
this.secret = config.secret;
|
|
42
|
-
this.logger = logger;
|
|
43
|
-
this.plugins = [];
|
|
44
|
-
this.options = options;
|
|
45
|
-
if (!this.secret) {
|
|
46
|
-
throw new TypeError('secret it is required value on initialize the auth class');
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
return _createClass(Auth, [{
|
|
50
|
-
key: "init",
|
|
51
|
-
value: function () {
|
|
52
|
-
var _init = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
|
|
53
|
-
var plugins;
|
|
54
|
-
return _regenerator().w(function (_context) {
|
|
55
|
-
while (1) switch (_context.n) {
|
|
56
|
-
case 0:
|
|
57
|
-
_context.n = 1;
|
|
58
|
-
return this.loadPlugin();
|
|
59
|
-
case 1:
|
|
60
|
-
plugins = _context.v;
|
|
61
|
-
debug('auth plugins found %s', plugins.length);
|
|
62
|
-
// Missing auth config or no loaded plugins -> load default htpasswd plugin
|
|
63
|
-
// Empty auth config (null) -> just use fallback methods
|
|
64
|
-
if (this.config.auth !== null && (!plugins || plugins.length === 0)) {
|
|
65
|
-
plugins = this.loadDefaultPlugin();
|
|
66
|
-
}
|
|
67
|
-
this.plugins = plugins;
|
|
68
|
-
this.applyFallbackPluginMethods();
|
|
69
|
-
case 2:
|
|
70
|
-
return _context.a(2);
|
|
71
|
-
}
|
|
72
|
-
}, _callee, this);
|
|
73
|
-
}));
|
|
74
|
-
function init() {
|
|
75
|
-
return _init.apply(this, arguments);
|
|
76
|
-
}
|
|
77
|
-
return init;
|
|
78
|
-
}()
|
|
79
|
-
}, {
|
|
80
|
-
key: "loadDefaultPlugin",
|
|
81
|
-
value: function loadDefaultPlugin() {
|
|
82
|
-
debug('load default auth plugin');
|
|
83
|
-
var authPlugin;
|
|
84
|
-
try {
|
|
85
|
-
authPlugin = new _verdaccioHtpasswd.HTPasswd({
|
|
86
|
-
file: './htpasswd'
|
|
87
|
-
}, {
|
|
88
|
-
config: this.config,
|
|
89
|
-
logger: this.logger
|
|
90
|
-
});
|
|
91
|
-
this.logger.info({
|
|
92
|
-
name: 'verdaccio-htpasswd',
|
|
93
|
-
pluginCategory: _core.PLUGIN_CATEGORY.AUTHENTICATION
|
|
94
|
-
}, 'plugin @{name} successfully loaded (@{pluginCategory})');
|
|
95
|
-
} catch (error) {
|
|
96
|
-
debug('error on loading auth htpasswd plugin stack: %o', error);
|
|
97
|
-
this.logger.info({}, 'no auth plugin has been found');
|
|
98
|
-
return [];
|
|
99
|
-
}
|
|
100
|
-
return [authPlugin];
|
|
101
|
-
}
|
|
102
|
-
}, {
|
|
103
|
-
key: "loadPlugin",
|
|
104
|
-
value: function () {
|
|
105
|
-
var _loadPlugin = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
|
|
106
|
-
var _this$config$server$p, _this$config;
|
|
107
|
-
return _regenerator().w(function (_context2) {
|
|
108
|
-
while (1) switch (_context2.n) {
|
|
109
|
-
case 0:
|
|
110
|
-
return _context2.a(2, (0, _loaders.asyncLoadPlugin)(this.config.auth, {
|
|
111
|
-
config: this.config,
|
|
112
|
-
logger: this.logger
|
|
113
|
-
}, function (plugin) {
|
|
114
|
-
var authenticate = plugin.authenticate,
|
|
115
|
-
allow_access = plugin.allow_access,
|
|
116
|
-
allow_publish = plugin.allow_publish;
|
|
117
|
-
return typeof authenticate !== 'undefined' || typeof allow_access !== 'undefined' || typeof allow_publish !== 'undefined';
|
|
118
|
-
}, this.options.legacyMergeConfigs, (_this$config$server$p = (_this$config = this.config) === null || _this$config === void 0 || (_this$config = _this$config.server) === null || _this$config === void 0 ? void 0 : _this$config.pluginPrefix) !== null && _this$config$server$p !== void 0 ? _this$config$server$p : _core.PLUGIN_PREFIX, _core.PLUGIN_CATEGORY.AUTHENTICATION));
|
|
119
|
-
}
|
|
120
|
-
}, _callee2, this);
|
|
121
|
-
}));
|
|
122
|
-
function loadPlugin() {
|
|
123
|
-
return _loadPlugin.apply(this, arguments);
|
|
124
|
-
}
|
|
125
|
-
return loadPlugin;
|
|
126
|
-
}()
|
|
127
|
-
}, {
|
|
128
|
-
key: "applyFallbackPluginMethods",
|
|
129
|
-
value: function applyFallbackPluginMethods() {
|
|
130
|
-
this.plugins.push((0, _utils.getDefaultPluginMethods)(this.logger));
|
|
131
|
-
}
|
|
132
|
-
}, {
|
|
133
|
-
key: "changePassword",
|
|
134
|
-
value: function changePassword(username, password, newPassword, cb) {
|
|
135
|
-
var _this = this;
|
|
136
|
-
var validPlugins = _lodash["default"].filter(this.plugins, function (plugin) {
|
|
137
|
-
return _lodash["default"].isFunction(plugin.changePassword);
|
|
138
|
-
});
|
|
139
|
-
if (_lodash["default"].isEmpty(validPlugins)) {
|
|
140
|
-
return cb(_core.errorUtils.getInternalError(_core.SUPPORT_ERRORS.PLUGIN_MISSING_INTERFACE));
|
|
141
|
-
}
|
|
142
|
-
var _iterator = _createForOfIteratorHelper(validPlugins),
|
|
143
|
-
_step;
|
|
144
|
-
try {
|
|
145
|
-
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
146
|
-
var plugin = _step.value;
|
|
147
|
-
if (_lodash["default"].isNil(plugin) || _lodash["default"].isFunction(plugin.changePassword) === false) {
|
|
148
|
-
debug('auth plugin does not implement changePassword, trying next one');
|
|
149
|
-
continue;
|
|
150
|
-
} else {
|
|
151
|
-
debug('updating password for %o', username);
|
|
152
|
-
plugin.changePassword(username, password, newPassword, function (err, profile) {
|
|
153
|
-
if (err) {
|
|
154
|
-
_this.logger.error({
|
|
155
|
-
username: username,
|
|
156
|
-
err: err
|
|
157
|
-
}, "An error has been produced\n updating the password for @{username}. Error: @{err.message}");
|
|
158
|
-
return cb(err);
|
|
159
|
-
}
|
|
160
|
-
debug('updated password for %o was successful', username);
|
|
161
|
-
return cb(null, profile);
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
} catch (err) {
|
|
166
|
-
_iterator.e(err);
|
|
167
|
-
} finally {
|
|
168
|
-
_iterator.f();
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}, {
|
|
172
|
-
key: "invalidateToken",
|
|
173
|
-
value: function () {
|
|
174
|
-
var _invalidateToken = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3(token) {
|
|
175
|
-
return _regenerator().w(function (_context3) {
|
|
176
|
-
while (1) switch (_context3.n) {
|
|
177
|
-
case 0:
|
|
178
|
-
// eslint-disable-next-line no-console
|
|
179
|
-
console.log('invalidate token pending to implement', token);
|
|
180
|
-
return _context3.a(2, Promise.resolve());
|
|
181
|
-
}
|
|
182
|
-
}, _callee3);
|
|
183
|
-
}));
|
|
184
|
-
function invalidateToken(_x) {
|
|
185
|
-
return _invalidateToken.apply(this, arguments);
|
|
186
|
-
}
|
|
187
|
-
return invalidateToken;
|
|
188
|
-
}()
|
|
189
|
-
}, {
|
|
190
|
-
key: "authenticate",
|
|
191
|
-
value: function authenticate(username, password, cb) {
|
|
192
|
-
var plugins = this.plugins.slice(0);
|
|
193
|
-
(function next() {
|
|
194
|
-
var plugin = plugins.shift();
|
|
195
|
-
if (typeof (plugin === null || plugin === void 0 ? void 0 : plugin.authenticate) !== 'function') {
|
|
196
|
-
return next();
|
|
197
|
-
}
|
|
198
|
-
debug('authenticating %o', username);
|
|
199
|
-
plugin.authenticate(username, password, function (err, groups) {
|
|
200
|
-
if (err) {
|
|
201
|
-
debug('authenticating for user %o failed. Error: %o', username, err === null || err === void 0 ? void 0 : err.message);
|
|
202
|
-
return cb(err);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// Expect: SKIP if groups is falsey and not an array
|
|
206
|
-
// with at least one item (truthy length)
|
|
207
|
-
// Expect: CONTINUE otherwise (will error if groups is not
|
|
208
|
-
// an array, but this is current behavior)
|
|
209
|
-
// Caveat: STRING (if valid) will pass successfully
|
|
210
|
-
// bug give unexpected results
|
|
211
|
-
// Info: Cannot use `== false to check falsey values`
|
|
212
|
-
if (!!groups && groups.length !== 0) {
|
|
213
|
-
// TODO: create a better understanding of expectations
|
|
214
|
-
if (_lodash["default"].isString(groups)) {
|
|
215
|
-
throw new TypeError('plugin group error: invalid type for function');
|
|
216
|
-
}
|
|
217
|
-
var isGroupValid = _lodash["default"].isArray(groups);
|
|
218
|
-
if (!isGroupValid) {
|
|
219
|
-
throw new TypeError(_core.API_ERROR.BAD_FORMAT_USER_GROUP);
|
|
220
|
-
}
|
|
221
|
-
debug('authentication for user %o was successfully. Groups: %o', username, groups);
|
|
222
|
-
return cb(err, (0, _config.createRemoteUser)(username, groups));
|
|
223
|
-
}
|
|
224
|
-
next();
|
|
225
|
-
});
|
|
226
|
-
})();
|
|
227
|
-
}
|
|
228
|
-
}, {
|
|
229
|
-
key: "add_user",
|
|
230
|
-
value: function add_user(user, password, cb) {
|
|
231
|
-
var self = this;
|
|
232
|
-
var plugins = this.plugins.slice(0);
|
|
233
|
-
debug('add user %o', user);
|
|
234
|
-
(function next() {
|
|
235
|
-
var method = 'adduser';
|
|
236
|
-
var plugin = plugins.shift();
|
|
237
|
-
// @ts-expect-error future major (7.x) should remove this section
|
|
238
|
-
if (typeof plugin.adduser === 'undefined' && typeof plugin.add_user === 'function') {
|
|
239
|
-
method = 'add_user';
|
|
240
|
-
_core.warningUtils.emit(_core.warningUtils.Codes.VERWAR006);
|
|
241
|
-
}
|
|
242
|
-
// @ts-ignore
|
|
243
|
-
if (typeof plugin[method] !== 'function') {
|
|
244
|
-
next();
|
|
245
|
-
} else {
|
|
246
|
-
// TODO: replace by adduser whenever add_user deprecation method has been removed
|
|
247
|
-
// @ts-ignore
|
|
248
|
-
plugin[method](user, password, function (err, ok) {
|
|
249
|
-
if (err) {
|
|
250
|
-
debug('the user %o could not be added. Error: %o', user, err === null || err === void 0 ? void 0 : err.message);
|
|
251
|
-
return cb(err);
|
|
252
|
-
}
|
|
253
|
-
if (ok) {
|
|
254
|
-
debug('the user %o has been added', user);
|
|
255
|
-
return self.authenticate(user, password, cb);
|
|
256
|
-
}
|
|
257
|
-
debug('user could not be added, skip to next auth plugin');
|
|
258
|
-
next();
|
|
259
|
-
});
|
|
260
|
-
}
|
|
261
|
-
})();
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
/**
|
|
265
|
-
* Allow user to access a package.
|
|
266
|
-
*/
|
|
267
|
-
}, {
|
|
268
|
-
key: "allow_access",
|
|
269
|
-
value: function allow_access(_ref, user, callback) {
|
|
270
|
-
var _this2 = this;
|
|
271
|
-
var packageName = _ref.packageName,
|
|
272
|
-
packageVersion = _ref.packageVersion;
|
|
273
|
-
var plugins = this.plugins.slice(0);
|
|
274
|
-
var pkg = Object.assign({
|
|
275
|
-
name: packageName,
|
|
276
|
-
version: packageVersion
|
|
277
|
-
}, _core.authUtils.getMatchedPackagesSpec(packageName, this.config.packages));
|
|
278
|
-
debug('check access permissions for user %o to package %o', user.name, packageName);
|
|
279
|
-
|
|
280
|
-
// Use const instead of function declaration so we can use this.logger
|
|
281
|
-
var _next2 = function next() {
|
|
282
|
-
var plugin = plugins.shift();
|
|
283
|
-
if (typeof (plugin === null || plugin === void 0 ? void 0 : plugin.allow_access) !== 'function') {
|
|
284
|
-
debug('plugin does not implement allow_access');
|
|
285
|
-
return _next2();
|
|
286
|
-
}
|
|
287
|
-
plugin.allow_access(user, pkg, function (err, ok) {
|
|
288
|
-
if (err) {
|
|
289
|
-
debug('forbidden access. Error: %o', err);
|
|
290
|
-
return callback(err);
|
|
291
|
-
}
|
|
292
|
-
if (ok) {
|
|
293
|
-
debug('access was granted');
|
|
294
|
-
_this2.logger.trace({
|
|
295
|
-
user: user.name,
|
|
296
|
-
name: pkg.name
|
|
297
|
-
}, "access was granted for @{name} by @{user}");
|
|
298
|
-
return callback(null, ok);
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
// cb(null, false) causes next plugin to roll
|
|
302
|
-
debug('access was denied. Rolling to next plugin');
|
|
303
|
-
_this2.logger.trace({
|
|
304
|
-
user: user.name,
|
|
305
|
-
name: pkg.name
|
|
306
|
-
}, "intermediate access denial for @{name} by @{user}, rolling to next plugin");
|
|
307
|
-
return _next2();
|
|
308
|
-
});
|
|
309
|
-
};
|
|
310
|
-
return _next2();
|
|
311
|
-
}
|
|
312
|
-
}, {
|
|
313
|
-
key: "allow_unpublish",
|
|
314
|
-
value: function allow_unpublish(_ref2, user, callback) {
|
|
315
|
-
var _this3 = this;
|
|
316
|
-
var packageName = _ref2.packageName,
|
|
317
|
-
packageVersion = _ref2.packageVersion;
|
|
318
|
-
var plugins = this.plugins.slice(0);
|
|
319
|
-
var pkg = Object.assign({
|
|
320
|
-
name: packageName,
|
|
321
|
-
version: packageVersion
|
|
322
|
-
}, _core.authUtils.getMatchedPackagesSpec(packageName, this.config.packages));
|
|
323
|
-
debug('check unpublish permissions for user %o to package %o', user.name, packageName);
|
|
324
|
-
|
|
325
|
-
// Use const instead of function declaration so we can use this.logger
|
|
326
|
-
var _next3 = function next() {
|
|
327
|
-
var plugin = plugins.shift();
|
|
328
|
-
if (typeof (plugin === null || plugin === void 0 ? void 0 : plugin.allow_unpublish) !== 'function') {
|
|
329
|
-
debug('plugin does not implement allow_unpublish');
|
|
330
|
-
return _next3();
|
|
331
|
-
}
|
|
332
|
-
plugin.allow_unpublish(user, pkg, function (err, ok) {
|
|
333
|
-
if (err) {
|
|
334
|
-
debug('forbidden unpublish. Error: %o', err);
|
|
335
|
-
return callback(err);
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
// The following is different from the allow_access and allow_publish implementations:
|
|
339
|
-
// If the packages config is missing an entry for "unpublish", the built-in default method
|
|
340
|
-
// (or a plugin) will return undefined, which will trigger the allow_publish fallback.
|
|
341
|
-
// (see utils.ts, handleSpecialUnpublish, callback(null, undefined))
|
|
342
|
-
if (_lodash["default"].isNil(ok) === true) {
|
|
343
|
-
debug('bypass unpublish for %o, publish will handle the access', packageName);
|
|
344
|
-
_this3.logger.trace({
|
|
345
|
-
user: user.name,
|
|
346
|
-
name: pkg.name
|
|
347
|
-
}, "bypass unpublish for @{name} by @{user}, publish will handle the access");
|
|
348
|
-
return _this3.allow_publish({
|
|
349
|
-
packageName: packageName,
|
|
350
|
-
packageVersion: packageVersion
|
|
351
|
-
}, user, callback);
|
|
352
|
-
}
|
|
353
|
-
if (ok) {
|
|
354
|
-
debug('unpublish was granted');
|
|
355
|
-
_this3.logger.trace({
|
|
356
|
-
user: user.name,
|
|
357
|
-
name: pkg.name
|
|
358
|
-
}, "unpublish was granted for @{name} by @{user}");
|
|
359
|
-
return callback(null, ok);
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
// cb(null, false) causes next plugin to roll
|
|
363
|
-
debug('unpublish was denied. Rolling to next plugin');
|
|
364
|
-
_this3.logger.trace({
|
|
365
|
-
user: user.name,
|
|
366
|
-
name: pkg.name
|
|
367
|
-
}, "intermediate unpublish denial for @{name} by @{user}, rolling to next plugin");
|
|
368
|
-
return _next3();
|
|
369
|
-
});
|
|
370
|
-
};
|
|
371
|
-
return _next3();
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
/**
|
|
375
|
-
* Allow user to publish a package.
|
|
376
|
-
*/
|
|
377
|
-
}, {
|
|
378
|
-
key: "allow_publish",
|
|
379
|
-
value: function allow_publish(_ref3, user, callback) {
|
|
380
|
-
var _this4 = this;
|
|
381
|
-
var packageName = _ref3.packageName,
|
|
382
|
-
packageVersion = _ref3.packageVersion;
|
|
383
|
-
var plugins = this.plugins.slice(0);
|
|
384
|
-
var pkg = Object.assign({
|
|
385
|
-
name: packageName,
|
|
386
|
-
version: packageVersion
|
|
387
|
-
}, _core.authUtils.getMatchedPackagesSpec(packageName, this.config.packages));
|
|
388
|
-
debug('check publish permissions for user %o to package %o', user.name, packageName);
|
|
389
|
-
|
|
390
|
-
// Use const instead of function declaration so we can use this.logger
|
|
391
|
-
var _next4 = function next() {
|
|
392
|
-
var plugin = plugins.shift();
|
|
393
|
-
if (typeof (plugin === null || plugin === void 0 ? void 0 : plugin.allow_publish) !== 'function') {
|
|
394
|
-
debug('plugin does not implement allow_publish');
|
|
395
|
-
return _next4();
|
|
396
|
-
}
|
|
397
|
-
plugin.allow_publish(user, pkg, function (err, ok) {
|
|
398
|
-
if (err) {
|
|
399
|
-
debug('forbidden publish. Error: %o', err);
|
|
400
|
-
return callback(err);
|
|
401
|
-
}
|
|
402
|
-
if (ok) {
|
|
403
|
-
debug('publish was granted');
|
|
404
|
-
_this4.logger.trace({
|
|
405
|
-
user: user.name,
|
|
406
|
-
name: pkg.name
|
|
407
|
-
}, "publish was granted for @{name} by @{user}");
|
|
408
|
-
return callback(null, ok);
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
// cb(null, false) causes next plugin to roll
|
|
412
|
-
debug('publish was denied. Rolling to next plugin');
|
|
413
|
-
_this4.logger.trace({
|
|
414
|
-
user: user.name,
|
|
415
|
-
name: pkg.name
|
|
416
|
-
}, "intermediate publish denial for @{name} by @{user}, rolling to next plugin");
|
|
417
|
-
return _next4();
|
|
418
|
-
});
|
|
419
|
-
};
|
|
420
|
-
return _next4();
|
|
421
|
-
}
|
|
422
|
-
}, {
|
|
423
|
-
key: "apiJWTmiddleware",
|
|
424
|
-
value: function apiJWTmiddleware() {
|
|
425
|
-
var _this5 = this;
|
|
426
|
-
debug('jwt middleware');
|
|
427
|
-
var plugins = this.plugins.slice(0);
|
|
428
|
-
var helpers = {
|
|
429
|
-
createAnonymousRemoteUser: _config.createAnonymousRemoteUser,
|
|
430
|
-
createRemoteUser: _config.createRemoteUser
|
|
431
|
-
};
|
|
432
|
-
var _iterator2 = _createForOfIteratorHelper(plugins),
|
|
433
|
-
_step2;
|
|
434
|
-
try {
|
|
435
|
-
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
436
|
-
var plugin = _step2.value;
|
|
437
|
-
if (plugin.apiJWTmiddleware) {
|
|
438
|
-
return plugin.apiJWTmiddleware(helpers);
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
} catch (err) {
|
|
442
|
-
_iterator2.e(err);
|
|
443
|
-
} finally {
|
|
444
|
-
_iterator2.f();
|
|
445
|
-
}
|
|
446
|
-
return function (req, res, _next) {
|
|
447
|
-
req.pause();
|
|
448
|
-
var next = function next(err) {
|
|
449
|
-
req.resume();
|
|
450
|
-
// uncomment this to reject users with bad auth headers
|
|
451
|
-
// return _next.apply(null, arguments)
|
|
452
|
-
// swallow error, user remains unauthorized
|
|
453
|
-
// set remoteUserError to indicate that user was attempting authentication
|
|
454
|
-
if (err) {
|
|
455
|
-
req.remote_user.error = err.message;
|
|
456
|
-
}
|
|
457
|
-
return _next();
|
|
458
|
-
};
|
|
459
|
-
|
|
460
|
-
// FUTURE: disabled, not removed yet but seems unreacable code
|
|
461
|
-
// if (this._isRemoteUserValid(req.remote_user)) {
|
|
462
|
-
// debug('jwt has a valid authentication header');
|
|
463
|
-
// return next();
|
|
464
|
-
// }
|
|
465
|
-
|
|
466
|
-
// in case auth header does not exist we return anonymous function
|
|
467
|
-
var remoteUser = (0, _config.createAnonymousRemoteUser)();
|
|
468
|
-
req.remote_user = remoteUser;
|
|
469
|
-
res.locals.remote_user = remoteUser;
|
|
470
|
-
var authorization = req.headers.authorization;
|
|
471
|
-
if (_lodash["default"].isNil(authorization)) {
|
|
472
|
-
debug('jwt, authentication header is missing');
|
|
473
|
-
return next();
|
|
474
|
-
}
|
|
475
|
-
if (!(0, _utils.isAuthHeaderValid)(authorization)) {
|
|
476
|
-
debug('api middleware authentication heather is invalid');
|
|
477
|
-
return next(_core.errorUtils.getBadRequest(_core.API_ERROR.BAD_AUTH_HEADER));
|
|
478
|
-
}
|
|
479
|
-
var _this5$config = _this5.config,
|
|
480
|
-
secret = _this5$config.secret,
|
|
481
|
-
security = _this5$config.security;
|
|
482
|
-
if ((0, _utils.isAESLegacy)(security)) {
|
|
483
|
-
debug('api middleware using legacy auth token');
|
|
484
|
-
_this5.handleAESMiddleware(req, security, secret, authorization, next);
|
|
485
|
-
} else {
|
|
486
|
-
debug('api middleware using JWT auth token');
|
|
487
|
-
_this5.handleJWTAPIMiddleware(req, security, secret, authorization, next);
|
|
488
|
-
}
|
|
489
|
-
};
|
|
490
|
-
}
|
|
491
|
-
}, {
|
|
492
|
-
key: "handleJWTAPIMiddleware",
|
|
493
|
-
value: function handleJWTAPIMiddleware(req, security, secret, authorization, next) {
|
|
494
|
-
debug('handle JWT api middleware');
|
|
495
|
-
var _parseAuthTokenHeader = (0, _utils.parseAuthTokenHeader)(authorization),
|
|
496
|
-
scheme = _parseAuthTokenHeader.scheme,
|
|
497
|
-
token = _parseAuthTokenHeader.token;
|
|
498
|
-
if (scheme.toUpperCase() === _core.TOKEN_BASIC.toUpperCase()) {
|
|
499
|
-
debug('handle basic token');
|
|
500
|
-
// this should happen when client tries to login with an existing user
|
|
501
|
-
var credentials = (0, _utils.convertPayloadToBase64)(token).toString();
|
|
502
|
-
var parsedCredentials = (0, _signature.parseBasicPayload)(credentials);
|
|
503
|
-
if (!parsedCredentials) {
|
|
504
|
-
debug('invalid basic credentials format (missing colon separator)');
|
|
505
|
-
next(_core.errorUtils.getBadRequest(_core.API_ERROR.BAD_USERNAME_PASSWORD));
|
|
506
|
-
return;
|
|
507
|
-
}
|
|
508
|
-
var _ref4 = parsedCredentials,
|
|
509
|
-
user = _ref4.user,
|
|
510
|
-
password = _ref4.password;
|
|
511
|
-
debug('authenticating %o', user);
|
|
512
|
-
this.authenticate(user, password, function (err, user) {
|
|
513
|
-
if (!err) {
|
|
514
|
-
debug('generating a remote user');
|
|
515
|
-
req.remote_user = user;
|
|
516
|
-
next();
|
|
517
|
-
} else {
|
|
518
|
-
debug('generating anonymous user');
|
|
519
|
-
req.remote_user = (0, _config.createAnonymousRemoteUser)();
|
|
520
|
-
next(err);
|
|
521
|
-
}
|
|
522
|
-
});
|
|
523
|
-
} else {
|
|
524
|
-
debug('handle jwt token');
|
|
525
|
-
var _credentials = (0, _utils.getMiddlewareCredentials)(security, secret, authorization);
|
|
526
|
-
if (_credentials) {
|
|
527
|
-
// if the signature is valid we rely on it
|
|
528
|
-
req.remote_user = _credentials;
|
|
529
|
-
debug('generating a remote user');
|
|
530
|
-
next();
|
|
531
|
-
} else {
|
|
532
|
-
// with JWT throw 401
|
|
533
|
-
debug('jwt invalid token');
|
|
534
|
-
next(_core.errorUtils.getForbidden(_core.API_ERROR.BAD_USERNAME_PASSWORD));
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
}, {
|
|
539
|
-
key: "handleAESMiddleware",
|
|
540
|
-
value: function handleAESMiddleware(req, security, secret, authorization, next) {
|
|
541
|
-
debug('handle legacy api middleware');
|
|
542
|
-
debug('api middleware has a secret? %o', typeof secret === 'string');
|
|
543
|
-
debug('api middleware authorization %o', typeof authorization === 'string');
|
|
544
|
-
var credentials = (0, _utils.getMiddlewareCredentials)(security, secret, authorization);
|
|
545
|
-
debug('api middleware credentials %o', credentials === null || credentials === void 0 ? void 0 : credentials.name);
|
|
546
|
-
if (credentials) {
|
|
547
|
-
var user = credentials.user,
|
|
548
|
-
password = credentials.password;
|
|
549
|
-
debug('authenticating %o', user);
|
|
550
|
-
this.authenticate(user, password, function (err, user) {
|
|
551
|
-
if (!err) {
|
|
552
|
-
req.remote_user = user;
|
|
553
|
-
debug('generating a remote user');
|
|
554
|
-
next();
|
|
555
|
-
} else {
|
|
556
|
-
req.remote_user = (0, _config.createAnonymousRemoteUser)();
|
|
557
|
-
debug('generating anonymous user');
|
|
558
|
-
next(err);
|
|
559
|
-
}
|
|
560
|
-
});
|
|
561
|
-
} else {
|
|
562
|
-
// we force npm client to ask again with basic authentication
|
|
563
|
-
debug('legacy invalid header');
|
|
564
|
-
return next(_core.errorUtils.getBadRequest(_core.API_ERROR.BAD_AUTH_HEADER));
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
}, {
|
|
568
|
-
key: "_isRemoteUserValid",
|
|
569
|
-
value: function _isRemoteUserValid(remote_user) {
|
|
570
|
-
return _lodash["default"].isUndefined(remote_user) === false && _lodash["default"].isUndefined(remote_user === null || remote_user === void 0 ? void 0 : remote_user.name) === false;
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
/**
|
|
574
|
-
* JWT middleware for WebUI
|
|
575
|
-
*/
|
|
576
|
-
}, {
|
|
577
|
-
key: "webUIJWTmiddleware",
|
|
578
|
-
value: function webUIJWTmiddleware() {
|
|
579
|
-
var _this6 = this;
|
|
580
|
-
return function (req, res, _next) {
|
|
581
|
-
if (_this6._isRemoteUserValid(req.remote_user)) {
|
|
582
|
-
return _next();
|
|
583
|
-
}
|
|
584
|
-
req.pause();
|
|
585
|
-
var next = function next(err) {
|
|
586
|
-
req.resume();
|
|
587
|
-
if (err) {
|
|
588
|
-
req.remote_user.error = err.message;
|
|
589
|
-
res.status(err.statusCode).send(err.message);
|
|
590
|
-
}
|
|
591
|
-
return _next();
|
|
592
|
-
};
|
|
593
|
-
var authorization = req.headers.authorization;
|
|
594
|
-
if (_lodash["default"].isNil(authorization)) {
|
|
595
|
-
return next();
|
|
596
|
-
}
|
|
597
|
-
if (!(0, _utils.isAuthHeaderValid)(authorization)) {
|
|
598
|
-
return next(_core.errorUtils.getBadRequest(_core.API_ERROR.BAD_AUTH_HEADER));
|
|
599
|
-
}
|
|
600
|
-
var token = (authorization || '').replace("".concat(_core.TOKEN_BEARER, " "), '');
|
|
601
|
-
if (!token) {
|
|
602
|
-
return next();
|
|
603
|
-
}
|
|
604
|
-
var credentials;
|
|
605
|
-
try {
|
|
606
|
-
credentials = (0, _utils.verifyJWTPayload)(token, _this6.config.secret, _this6.config.security);
|
|
607
|
-
} catch (_unused) {
|
|
608
|
-
// FIXME: intended behaviour, do we want it?
|
|
609
|
-
}
|
|
610
|
-
if (_this6._isRemoteUserValid(credentials)) {
|
|
611
|
-
var _ref5 = credentials,
|
|
612
|
-
name = _ref5.name,
|
|
613
|
-
groups = _ref5.groups;
|
|
614
|
-
req.remote_user = (0, _config.createRemoteUser)(name, groups);
|
|
615
|
-
} else {
|
|
616
|
-
req.remote_user = (0, _config.createAnonymousRemoteUser)();
|
|
617
|
-
}
|
|
618
|
-
next();
|
|
619
|
-
};
|
|
620
|
-
}
|
|
621
|
-
}, {
|
|
622
|
-
key: "jwtEncrypt",
|
|
623
|
-
value: function () {
|
|
624
|
-
var _jwtEncrypt = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4(user, signOptions) {
|
|
625
|
-
var real_groups, name, groups, realGroupsValidated, groupedGroups, payload, token;
|
|
626
|
-
return _regenerator().w(function (_context4) {
|
|
627
|
-
while (1) switch (_context4.n) {
|
|
628
|
-
case 0:
|
|
629
|
-
real_groups = user.real_groups, name = user.name, groups = user.groups;
|
|
630
|
-
debug('jwt encrypt %o', name);
|
|
631
|
-
realGroupsValidated = _lodash["default"].isNil(real_groups) ? [] : real_groups;
|
|
632
|
-
groupedGroups = _lodash["default"].isNil(groups) ? real_groups : Array.from(new Set(_toConsumableArray(groups.concat(realGroupsValidated))));
|
|
633
|
-
payload = {
|
|
634
|
-
real_groups: realGroupsValidated,
|
|
635
|
-
name: name,
|
|
636
|
-
groups: groupedGroups
|
|
637
|
-
};
|
|
638
|
-
_context4.n = 1;
|
|
639
|
-
return (0, _signature.signPayload)(payload, this.secret, signOptions);
|
|
640
|
-
case 1:
|
|
641
|
-
token = _context4.v;
|
|
642
|
-
return _context4.a(2, token);
|
|
643
|
-
}
|
|
644
|
-
}, _callee4, this);
|
|
645
|
-
}));
|
|
646
|
-
function jwtEncrypt(_x2, _x3) {
|
|
647
|
-
return _jwtEncrypt.apply(this, arguments);
|
|
648
|
-
}
|
|
649
|
-
return jwtEncrypt;
|
|
650
|
-
}()
|
|
651
|
-
/**
|
|
652
|
-
* Encrypt a string.
|
|
653
|
-
*/
|
|
654
|
-
}, {
|
|
655
|
-
key: "aesEncrypt",
|
|
656
|
-
value: function aesEncrypt(value) {
|
|
657
|
-
if (this.secret.length === _config.TOKEN_VALID_LENGTH) {
|
|
658
|
-
debug('signing with enhanced aes legacy');
|
|
659
|
-
var token = (0, _signature.aesEncrypt)(value, this.secret);
|
|
660
|
-
return token;
|
|
661
|
-
} else {
|
|
662
|
-
debug('signing with enhanced aes deprecated legacy');
|
|
663
|
-
// deprecated aes (legacy) signature, only must be used for legacy version
|
|
664
|
-
var _token = (0, _signature.aesEncryptDeprecated)(Buffer.from(value), this.secret).toString('base64');
|
|
665
|
-
return _token;
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
}]);
|
|
669
|
-
}();
|
|
670
423
|
//# sourceMappingURL=auth.js.map
|