@verdaccio/auth 6.0.0-6-next.12 → 6.0.0-6-next.16
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/CHANGELOG.md +63 -0
- package/build/auth.d.ts +4 -1
- package/build/auth.js +32 -34
- package/build/auth.js.map +1 -1
- package/build/index.js +4 -4
- package/build/jwt-token.js +7 -11
- package/build/jwt-token.js.map +1 -1
- package/build/legacy-token.js +3 -3
- package/build/legacy-token.js.map +1 -1
- package/build/utils.d.ts +3 -3
- package/build/utils.js +21 -21
- package/build/utils.js.map +1 -1
- package/package.json +11 -11
- package/src/auth.ts +40 -32
- package/src/jwt-token.ts +1 -1
- package/src/legacy-token.ts +4 -3
- package/src/utils.ts +23 -21
- package/test/auth-utils.spec.ts +22 -19
- package/test/auth.spec.ts +14 -6
- package/test/helper/plugin.ts +1 -0
- package/tsconfig.json +0 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,68 @@
|
|
|
1
1
|
# @verdaccio/auth
|
|
2
2
|
|
|
3
|
+
## 6.0.0-6-next.16
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [a828271d]
|
|
8
|
+
- Updated dependencies [24b9be02]
|
|
9
|
+
- Updated dependencies [e75c0a3b]
|
|
10
|
+
- Updated dependencies [b13a3fef]
|
|
11
|
+
- @verdaccio/utils@6.0.0-6-next.10
|
|
12
|
+
- @verdaccio/core@6.0.0-6-next.4
|
|
13
|
+
- @verdaccio/logger@6.0.0-6-next.8
|
|
14
|
+
- @verdaccio/config@6.0.0-6-next.12
|
|
15
|
+
- @verdaccio/loaders@6.0.0-6-next.8
|
|
16
|
+
- verdaccio-htpasswd@11.0.0-6-next.11
|
|
17
|
+
|
|
18
|
+
## 6.0.0-6-next.15
|
|
19
|
+
|
|
20
|
+
### Minor Changes
|
|
21
|
+
|
|
22
|
+
- 20c9e43e: dist tags Implementation on Fastify
|
|
23
|
+
|
|
24
|
+
### Patch Changes
|
|
25
|
+
|
|
26
|
+
- Updated dependencies [f86c31ed]
|
|
27
|
+
- @verdaccio/utils@6.0.0-6-next.9
|
|
28
|
+
- @verdaccio/config@6.0.0-6-next.11
|
|
29
|
+
- @verdaccio/loaders@6.0.0-6-next.7
|
|
30
|
+
|
|
31
|
+
## 6.0.0-6-next.14
|
|
32
|
+
|
|
33
|
+
### Patch Changes
|
|
34
|
+
|
|
35
|
+
- Updated dependencies [6c1eb021]
|
|
36
|
+
- @verdaccio/core@6.0.0-6-next.3
|
|
37
|
+
- @verdaccio/logger@6.0.0-6-next.7
|
|
38
|
+
- @verdaccio/config@6.0.0-6-next.10
|
|
39
|
+
- @verdaccio/loaders@6.0.0-6-next.7
|
|
40
|
+
- verdaccio-htpasswd@11.0.0-6-next.10
|
|
41
|
+
- @verdaccio/utils@6.0.0-6-next.8
|
|
42
|
+
|
|
43
|
+
## 6.0.0-6-next.13
|
|
44
|
+
|
|
45
|
+
### Major Changes
|
|
46
|
+
|
|
47
|
+
- 794af76c: Remove Node 12 support
|
|
48
|
+
|
|
49
|
+
- We need move to the new `undici` and does not support Node.js 12
|
|
50
|
+
|
|
51
|
+
### Minor Changes
|
|
52
|
+
|
|
53
|
+
- 154b2ecd: refactor: remove @verdaccio/commons-api in favor @verdaccio/core and remove duplications
|
|
54
|
+
|
|
55
|
+
### Patch Changes
|
|
56
|
+
|
|
57
|
+
- Updated dependencies [794af76c]
|
|
58
|
+
- Updated dependencies [154b2ecd]
|
|
59
|
+
- @verdaccio/config@6.0.0-6-next.9
|
|
60
|
+
- @verdaccio/core@6.0.0-6-next.2
|
|
61
|
+
- verdaccio-htpasswd@11.0.0-6-next.9
|
|
62
|
+
- @verdaccio/loaders@6.0.0-6-next.6
|
|
63
|
+
- @verdaccio/logger@6.0.0-6-next.6
|
|
64
|
+
- @verdaccio/utils@6.0.0-6-next.7
|
|
65
|
+
|
|
3
66
|
## 6.0.0-6-next.12
|
|
4
67
|
|
|
5
68
|
### Patch Changes
|
package/build/auth.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { NextFunction, Request, Response } from 'express';
|
|
2
|
-
import {
|
|
2
|
+
import { AuthPluginPackage, Callback, Config, IPluginAuth, JWTSignOptions, Logger, RemoteUser } from '@verdaccio/types';
|
|
3
3
|
export interface IBasicAuth<T> {
|
|
4
4
|
config: T & Config;
|
|
5
5
|
authenticate(user: string, password: string, cb: Callback): void;
|
|
6
|
+
invalidateToken?(token: string): Promise<void>;
|
|
6
7
|
changePassword(user: string, password: string, newPassword: string, cb: Callback): void;
|
|
7
8
|
allow_access(pkg: AuthPluginPackage, user: RemoteUser, callback: Callback): void;
|
|
8
9
|
add_user(user: string, password: string, cb: Callback): any;
|
|
@@ -33,6 +34,7 @@ export interface IAuth extends IBasicAuth<Config>, IAuthMiddleware, TokenEncrypt
|
|
|
33
34
|
secret: string;
|
|
34
35
|
plugins: any[];
|
|
35
36
|
allow_unpublish(pkg: AuthPluginPackage, user: RemoteUser, callback: Callback): void;
|
|
37
|
+
invalidateToken(token: string): Promise<void>;
|
|
36
38
|
}
|
|
37
39
|
declare class Auth implements IAuth {
|
|
38
40
|
config: Config;
|
|
@@ -44,6 +46,7 @@ declare class Auth implements IAuth {
|
|
|
44
46
|
private _loadPlugin;
|
|
45
47
|
private _applyDefaultPlugins;
|
|
46
48
|
changePassword(username: string, password: string, newPassword: string, cb: Callback): void;
|
|
49
|
+
invalidateToken(token: string): Promise<void>;
|
|
47
50
|
authenticate(username: string, password: string, cb: Callback): void;
|
|
48
51
|
add_user(user: string, password: string, cb: Callback): void;
|
|
49
52
|
/**
|
package/build/auth.js
CHANGED
|
@@ -5,21 +5,19 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.Auth = void 0;
|
|
7
7
|
|
|
8
|
-
var _lodash = _interopRequireDefault(require("lodash"));
|
|
9
|
-
|
|
10
8
|
var _debug = _interopRequireDefault(require("debug"));
|
|
11
9
|
|
|
12
|
-
var
|
|
13
|
-
|
|
14
|
-
var _loaders = require("@verdaccio/loaders");
|
|
10
|
+
var _lodash = _interopRequireDefault(require("lodash"));
|
|
15
11
|
|
|
16
12
|
var _verdaccioHtpasswd = require("verdaccio-htpasswd");
|
|
17
13
|
|
|
18
|
-
var _utils = require("@verdaccio/utils");
|
|
19
|
-
|
|
20
14
|
var _config = require("@verdaccio/config");
|
|
21
15
|
|
|
22
|
-
var
|
|
16
|
+
var _core = require("@verdaccio/core");
|
|
17
|
+
|
|
18
|
+
var _loaders = require("@verdaccio/loaders");
|
|
19
|
+
|
|
20
|
+
var _utils = require("@verdaccio/utils");
|
|
23
21
|
|
|
24
22
|
var _jwtToken = require("./jwt-token");
|
|
25
23
|
|
|
@@ -27,13 +25,9 @@ var _legacyToken = require("./legacy-token");
|
|
|
27
25
|
|
|
28
26
|
var _token = require("./token");
|
|
29
27
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
|
|
33
|
-
|
|
34
|
-
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
|
28
|
+
var _utils2 = require("./utils");
|
|
35
29
|
|
|
36
|
-
function
|
|
30
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
37
31
|
|
|
38
32
|
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
39
33
|
const LoggerApi = require('@verdaccio/logger');
|
|
@@ -42,29 +36,25 @@ const debug = (0, _debug.default)('verdaccio:auth');
|
|
|
42
36
|
|
|
43
37
|
class Auth {
|
|
44
38
|
constructor(config) {
|
|
45
|
-
_defineProperty(this, "config", void 0);
|
|
46
|
-
|
|
47
|
-
_defineProperty(this, "logger", void 0);
|
|
48
|
-
|
|
49
|
-
_defineProperty(this, "secret", void 0);
|
|
50
|
-
|
|
51
|
-
_defineProperty(this, "plugins", void 0);
|
|
52
|
-
|
|
53
39
|
this.config = config;
|
|
54
40
|
this.logger = LoggerApi.logger.child({
|
|
55
41
|
sub: 'auth'
|
|
56
42
|
});
|
|
57
43
|
this.secret = config.secret;
|
|
44
|
+
|
|
45
|
+
if (!this.secret) {
|
|
46
|
+
throw new TypeError('secret it is required value on initialize the auth class');
|
|
47
|
+
}
|
|
48
|
+
|
|
58
49
|
this.plugins = _lodash.default.isNil(config === null || config === void 0 ? void 0 : config.auth) === false ? this._loadPlugin(config) : this.loadDefaultPlugin(config);
|
|
59
50
|
|
|
60
51
|
this._applyDefaultPlugins();
|
|
61
52
|
}
|
|
62
53
|
|
|
63
54
|
loadDefaultPlugin(config) {
|
|
64
|
-
const plugingConf =
|
|
55
|
+
const plugingConf = { ...config,
|
|
65
56
|
file: './htpasswd'
|
|
66
|
-
}
|
|
67
|
-
|
|
57
|
+
};
|
|
68
58
|
const pluginOptions = {
|
|
69
59
|
config,
|
|
70
60
|
logger: this.logger
|
|
@@ -106,7 +96,7 @@ class Auth {
|
|
|
106
96
|
const validPlugins = _lodash.default.filter(this.plugins, plugin => (0, _utils.isFunction)(plugin.changePassword));
|
|
107
97
|
|
|
108
98
|
if (_lodash.default.isEmpty(validPlugins)) {
|
|
109
|
-
return cb(
|
|
99
|
+
return cb(_core.errorUtils.getInternalError(_core.SUPPORT_ERRORS.PLUGIN_MISSING_INTERFACE));
|
|
110
100
|
}
|
|
111
101
|
|
|
112
102
|
for (const plugin of validPlugins) {
|
|
@@ -132,6 +122,12 @@ class Auth {
|
|
|
132
122
|
}
|
|
133
123
|
}
|
|
134
124
|
|
|
125
|
+
async invalidateToken(token) {
|
|
126
|
+
// eslint-disable-next-line no-console
|
|
127
|
+
console.log('invalidate token pending to implement', token);
|
|
128
|
+
return Promise.resolve();
|
|
129
|
+
}
|
|
130
|
+
|
|
135
131
|
authenticate(username, password, cb) {
|
|
136
132
|
const plugins = this.plugins.slice(0);
|
|
137
133
|
|
|
@@ -165,7 +161,7 @@ class Auth {
|
|
|
165
161
|
const isGroupValid = _lodash.default.isArray(groups);
|
|
166
162
|
|
|
167
163
|
if (!isGroupValid) {
|
|
168
|
-
throw new TypeError(
|
|
164
|
+
throw new TypeError(_core.API_ERROR.BAD_FORMAT_USER_GROUP);
|
|
169
165
|
}
|
|
170
166
|
|
|
171
167
|
debug('authentication for user %o was successfully. Groups: %o', username, groups);
|
|
@@ -368,7 +364,9 @@ class Auth {
|
|
|
368
364
|
} // in case auth header does not exist we return anonymous function
|
|
369
365
|
|
|
370
366
|
|
|
371
|
-
|
|
367
|
+
const remoteUser = (0, _config.createAnonymousRemoteUser)();
|
|
368
|
+
req.remote_user = remoteUser;
|
|
369
|
+
res.locals.remote_user = remoteUser;
|
|
372
370
|
const {
|
|
373
371
|
authorization
|
|
374
372
|
} = req.headers;
|
|
@@ -380,7 +378,7 @@ class Auth {
|
|
|
380
378
|
|
|
381
379
|
if (!(0, _utils2.isAuthHeaderValid)(authorization)) {
|
|
382
380
|
debug('api middleware authentication heather is invalid');
|
|
383
|
-
return next(
|
|
381
|
+
return next(_core.errorUtils.getBadRequest(_core.API_ERROR.BAD_AUTH_HEADER));
|
|
384
382
|
}
|
|
385
383
|
|
|
386
384
|
const {
|
|
@@ -407,7 +405,7 @@ class Auth {
|
|
|
407
405
|
token
|
|
408
406
|
} = (0, _utils2.parseAuthTokenHeader)(authorization);
|
|
409
407
|
|
|
410
|
-
if (scheme.toUpperCase() ===
|
|
408
|
+
if (scheme.toUpperCase() === _core.TOKEN_BASIC.toUpperCase()) {
|
|
411
409
|
debug('handle basic token'); // this should happen when client tries to login with an existing user
|
|
412
410
|
|
|
413
411
|
const credentials = (0, _utils2.convertPayloadToBase64)(token).toString();
|
|
@@ -439,7 +437,7 @@ class Auth {
|
|
|
439
437
|
} else {
|
|
440
438
|
// with JWT throw 401
|
|
441
439
|
debug('jwt invalid token');
|
|
442
|
-
next(
|
|
440
|
+
next(_core.errorUtils.getForbidden(_core.API_ERROR.BAD_USERNAME_PASSWORD));
|
|
443
441
|
}
|
|
444
442
|
}
|
|
445
443
|
}
|
|
@@ -471,7 +469,7 @@ class Auth {
|
|
|
471
469
|
} else {
|
|
472
470
|
// we force npm client to ask again with basic authentication
|
|
473
471
|
debug('legacy invalid header');
|
|
474
|
-
return next(
|
|
472
|
+
return next(_core.errorUtils.getBadRequest(_core.API_ERROR.BAD_AUTH_HEADER));
|
|
475
473
|
}
|
|
476
474
|
}
|
|
477
475
|
|
|
@@ -511,10 +509,10 @@ class Auth {
|
|
|
511
509
|
}
|
|
512
510
|
|
|
513
511
|
if (!(0, _utils2.isAuthHeaderValid)(authorization)) {
|
|
514
|
-
return next(
|
|
512
|
+
return next(_core.errorUtils.getBadRequest(_core.API_ERROR.BAD_AUTH_HEADER));
|
|
515
513
|
}
|
|
516
514
|
|
|
517
|
-
const token = (authorization || '').replace(`${
|
|
515
|
+
const token = (authorization || '').replace(`${_core.TOKEN_BEARER} `, '');
|
|
518
516
|
|
|
519
517
|
if (!token) {
|
|
520
518
|
return next();
|
package/build/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/auth.ts"],"names":["LoggerApi","require","debug","Auth","constructor","config","logger","child","sub","secret","plugins","_","isNil","auth","_loadPlugin","loadDefaultPlugin","_applyDefaultPlugins","plugingConf","file","pluginOptions","authPlugin","HTPasswd","error","plugin","authenticate","allow_access","allow_publish","push","changePassword","username","password","newPassword","cb","validPlugins","filter","isEmpty","SUPPORT_ERRORS","PLUGIN_MISSING_INTERFACE","err","profile","slice","next","shift","groups","message","length","isString","TypeError","isGroupValid","isArray","API_ERROR","BAD_FORMAT_USER_GROUP","add_user","user","self","method","warn","ok","packageName","packageVersion","callback","pkgAllowAcces","name","version","pkg","Object","assign","packages","allow_unpublish","arguments","isError","apiJWTmiddleware","helpers","createAnonymousRemoteUser","createRemoteUser","req","res","_next","pause","resume","remote_user","_isRemoteUserValid","authorization","headers","BAD_AUTH_HEADER","security","_handleAESMiddleware","_handleJWTAPIMiddleware","scheme","token","toUpperCase","TOKEN_BASIC","credentials","toString","BAD_USERNAME_PASSWORD","isUndefined","webUIJWTmiddleware","status","statusCode","send","replace","TOKEN_BEARER","jwtEncrypt","signOptions","real_groups","realGroupsValidated","groupedGroups","concat","payload","aesEncrypt","value"],"mappings":"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","sourcesContent":["import _ from 'lodash';\nimport { NextFunction, Request, Response } from 'express';\nimport buildDebug from 'debug';\n\nimport {\n API_ERROR,\n SUPPORT_ERRORS,\n TOKEN_BASIC,\n TOKEN_BEARER,\n VerdaccioError,\n getBadRequest,\n getInternalError,\n getForbidden,\n} from '@verdaccio/commons-api';\nimport { loadPlugin } from '@verdaccio/loaders';\nimport { HTPasswd, HTPasswdConfig } from 'verdaccio-htpasswd';\n\nimport {\n Config,\n Logger,\n Callback,\n IPluginAuth,\n RemoteUser,\n JWTSignOptions,\n Security,\n AuthPluginPackage,\n AllowAccess,\n PackageAccess,\n PluginOptions,\n} from '@verdaccio/types';\n\nimport { getMatchedPackagesSpec, isNil, isFunction } from '@verdaccio/utils';\nimport { createAnonymousRemoteUser, createRemoteUser } from '@verdaccio/config';\n\nimport {\n getMiddlewareCredentials,\n getDefaultPlugins,\n verifyJWTPayload,\n parseAuthTokenHeader,\n isAuthHeaderValid,\n isAESLegacy,\n convertPayloadToBase64,\n} from './utils';\n\nimport { signPayload } from './jwt-token';\nimport { aesEncrypt } from './legacy-token';\nimport { parseBasicPayload } from './token';\n\n/* eslint-disable @typescript-eslint/no-var-requires */\nconst LoggerApi = require('@verdaccio/logger');\n\nconst debug = buildDebug('verdaccio:auth');\n\nexport interface IBasicAuth<T> {\n config: T & Config;\n authenticate(user: string, password: string, cb: Callback): void;\n changePassword(user: string, password: string, newPassword: string, cb: Callback): void;\n allow_access(pkg: AuthPluginPackage, user: RemoteUser, callback: Callback): void;\n add_user(user: string, password: string, cb: Callback): any;\n}\n\nexport interface TokenEncryption {\n jwtEncrypt(user: RemoteUser, signOptions: JWTSignOptions): Promise<string>;\n aesEncrypt(buf: string): string | void;\n}\n\nexport interface AESPayload {\n user: string;\n password: string;\n}\n\nexport type $RequestExtend = Request & { remote_user?: any; log: Logger };\nexport type $ResponseExtend = Response & { cookies?: any };\nexport type $NextFunctionVer = NextFunction & any;\n\nexport interface IAuthMiddleware {\n apiJWTmiddleware(): $NextFunctionVer;\n webUIJWTmiddleware(): $NextFunctionVer;\n}\n\nexport interface IAuth extends IBasicAuth<Config>, IAuthMiddleware, TokenEncryption {\n config: Config;\n logger: Logger;\n secret: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n plugins: any[];\n allow_unpublish(pkg: AuthPluginPackage, user: RemoteUser, callback: Callback): void;\n}\n\nclass Auth implements IAuth {\n public config: Config;\n public logger: Logger;\n public secret: string;\n public plugins: IPluginAuth<Config>[];\n\n public constructor(config: Config) {\n this.config = config;\n this.logger = LoggerApi.logger.child({ sub: 'auth' });\n this.secret = config.secret;\n\n this.plugins =\n _.isNil(config?.auth) === false ? this._loadPlugin(config) : this.loadDefaultPlugin(config);\n this._applyDefaultPlugins();\n }\n\n private loadDefaultPlugin(config: Config) {\n const plugingConf: HTPasswdConfig = { ...config, file: './htpasswd' };\n const pluginOptions: PluginOptions<{}> = {\n config,\n logger: this.logger,\n };\n let authPlugin;\n try {\n authPlugin = new HTPasswd(plugingConf, pluginOptions);\n } catch (error: any) {\n debug('error on loading auth htpasswd plugin stack: %o', error);\n return [];\n }\n\n return [authPlugin];\n }\n\n private _loadPlugin(config: Config): IPluginAuth<Config>[] {\n const pluginOptions = {\n config,\n logger: this.logger,\n };\n\n return loadPlugin<IPluginAuth<Config>>(\n config,\n config.auth,\n pluginOptions,\n (plugin: IPluginAuth<Config>): boolean => {\n const { authenticate, allow_access, allow_publish } = plugin;\n\n // @ts-ignore\n return authenticate || allow_access || allow_publish;\n }\n );\n }\n\n private _applyDefaultPlugins(): void {\n // TODO: rename to applyFallbackPluginMethods\n this.plugins.push(getDefaultPlugins(this.logger));\n }\n\n public changePassword(\n username: string,\n password: string,\n newPassword: string,\n cb: Callback\n ): void {\n const validPlugins = _.filter(this.plugins, (plugin) => isFunction(plugin.changePassword));\n\n if (_.isEmpty(validPlugins)) {\n return cb(getInternalError(SUPPORT_ERRORS.PLUGIN_MISSING_INTERFACE));\n }\n\n for (const plugin of validPlugins) {\n if (isNil(plugin) || isFunction(plugin.changePassword) === false) {\n debug('auth plugin does not implement changePassword, trying next one');\n continue;\n } else {\n debug('updating password for %o', username);\n plugin.changePassword!(username, password, newPassword, (err, profile): void => {\n if (err) {\n this.logger.error(\n { username, err },\n `An error has been produced\n updating the password for @{username}. Error: @{err.message}`\n );\n return cb(err);\n }\n\n debug('updated password for %o was successful', username);\n return cb(null, profile);\n });\n }\n }\n }\n\n public authenticate(username: string, password: string, cb: Callback): void {\n const plugins = this.plugins.slice(0);\n (function next(): void {\n const plugin = plugins.shift() as IPluginAuth<Config>;\n\n if (isFunction(plugin.authenticate) === false) {\n return next();\n }\n\n debug('authenticating %o', username);\n plugin.authenticate(username, password, function (err, groups): void {\n if (err) {\n debug('authenticating for user %o failed. Error: %o', username, err?.message);\n return cb(err);\n }\n\n // Expect: SKIP if groups is falsey and not an array\n // with at least one item (truthy length)\n // Expect: CONTINUE otherwise (will error if groups is not\n // an array, but this is current behavior)\n // Caveat: STRING (if valid) will pass successfully\n // bug give unexpected results\n // Info: Cannot use `== false to check falsey values`\n if (!!groups && groups.length !== 0) {\n // TODO: create a better understanding of expectations\n if (_.isString(groups)) {\n throw new TypeError('plugin group error: invalid type for function');\n }\n const isGroupValid: boolean = _.isArray(groups);\n if (!isGroupValid) {\n throw new TypeError(API_ERROR.BAD_FORMAT_USER_GROUP);\n }\n\n debug('authentication for user %o was successfully. Groups: %o', username, groups);\n return cb(err, createRemoteUser(username, groups));\n }\n next();\n });\n })();\n }\n\n public add_user(user: string, password: string, cb: Callback): void {\n const self = this;\n const plugins = this.plugins.slice(0);\n debug('add user %o', user);\n\n (function next(): void {\n const plugin = plugins.shift() as IPluginAuth<Config>;\n let method = 'adduser';\n if (isFunction(plugin[method]) === false) {\n method = 'add_user';\n self.logger.warn(\n 'the plugin method add_user in the auth plugin is deprecated and will' +\n ' be removed in next major release, notify to the plugin author'\n );\n }\n\n if (isFunction(plugin[method]) === false) {\n next();\n } else {\n // p.add_user() execution\n plugin[method](user, password, function (err, ok): void {\n if (err) {\n debug('the user %o could not being added. Error: %o', user, err?.message);\n return cb(err);\n }\n if (ok) {\n debug('the user %o has been added', user);\n return self.authenticate(user, password, cb);\n }\n next();\n });\n }\n })();\n }\n\n /**\n * Allow user to access a package.\n */\n public allow_access(\n { packageName, packageVersion }: AuthPluginPackage,\n user: RemoteUser,\n callback: Callback\n ): void {\n const plugins = this.plugins.slice(0);\n const pkgAllowAcces: AllowAccess = { name: packageName, version: packageVersion };\n const pkg = Object.assign(\n {},\n pkgAllowAcces,\n getMatchedPackagesSpec(packageName, this.config.packages)\n ) as AllowAccess & PackageAccess;\n debug('allow access for %o', packageName);\n\n (function next(): void {\n const plugin: IPluginAuth<Config> = plugins.shift() as IPluginAuth<Config>;\n\n if (_.isNil(plugin) || isFunction(plugin.allow_access) === false) {\n return next();\n }\n\n plugin.allow_access!(user, pkg, function (err, ok: boolean): void {\n if (err) {\n debug('forbidden access for %o. Error: %o', packageName, err?.message);\n return callback(err);\n }\n\n if (ok) {\n debug('allowed access for %o', packageName);\n return callback(null, ok);\n }\n\n next(); // cb(null, false) causes next plugin to roll\n });\n })();\n }\n\n public allow_unpublish(\n { packageName, packageVersion }: AuthPluginPackage,\n user: RemoteUser,\n callback: Callback\n ): void {\n const pkg = Object.assign(\n { name: packageName, version: packageVersion },\n getMatchedPackagesSpec(packageName, this.config.packages)\n );\n debug('allow unpublish for %o', packageName);\n\n for (const plugin of this.plugins) {\n if (_.isNil(plugin) || isFunction(plugin.allow_unpublish) === false) {\n debug('allow unpublish for %o plugin does not implement allow_unpublish', packageName);\n continue;\n } else {\n // @ts-ignore\n plugin.allow_unpublish!(user, pkg, (err, ok: boolean): void => {\n if (err) {\n debug(\n 'forbidden publish for %o, it will fallback on unpublish permissions',\n packageName\n );\n return callback(err);\n }\n\n if (_.isNil(ok) === true) {\n debug('bypass unpublish for %o, publish will handle the access', packageName);\n // @ts-ignore\n // eslint-disable-next-line\n return this.allow_publish(...arguments);\n }\n\n if (ok) {\n debug('allowed unpublish for %o', packageName);\n return callback(null, ok);\n }\n });\n }\n }\n }\n\n /**\n * Allow user to publish a package.\n */\n public allow_publish(\n { packageName, packageVersion }: AuthPluginPackage,\n user: RemoteUser,\n callback: Callback\n ): void {\n const plugins = this.plugins.slice(0);\n const pkg = Object.assign(\n { name: packageName, version: packageVersion },\n getMatchedPackagesSpec(packageName, this.config.packages)\n );\n debug('allow publish for %o init | plugins: %o', packageName, plugins.length);\n\n (function next(): void {\n const plugin = plugins.shift();\n\n if (isFunction(plugin?.allow_publish) === false) {\n debug('allow publish for %o plugin does not implement allow_publish', packageName);\n return next();\n }\n\n // @ts-ignore\n plugin.allow_publish(\n user,\n // @ts-ignore\n pkg,\n // @ts-ignore\n (err: VerdaccioError, ok: boolean): void => {\n if (_.isNil(err) === false && _.isError(err)) {\n debug('forbidden publish for %o', packageName);\n return callback(err);\n }\n\n if (ok) {\n debug('allowed publish for %o', packageName);\n return callback(null, ok);\n }\n\n debug('allow publish skip validation for %o', packageName);\n next(); // cb(null, false) causes next plugin to roll\n }\n );\n })();\n }\n\n public apiJWTmiddleware(): Function {\n debug('jwt middleware');\n const plugins = this.plugins.slice(0);\n const helpers = { createAnonymousRemoteUser, createRemoteUser };\n for (const plugin of plugins) {\n if (plugin.apiJWTmiddleware) {\n return plugin.apiJWTmiddleware(helpers);\n }\n }\n\n return (req: $RequestExtend, res: $ResponseExtend, _next: NextFunction): void => {\n req.pause();\n\n const next = function (err: VerdaccioError | void): void {\n req.resume();\n // uncomment this to reject users with bad auth headers\n // return _next.apply(null, arguments)\n // swallow error, user remains unauthorized\n // set remoteUserError to indicate that user was attempting authentication\n if (err) {\n req.remote_user.error = err.message;\n }\n return _next();\n };\n\n if (this._isRemoteUserValid(req.remote_user)) {\n debug('jwt has a valid authentication header');\n return next();\n }\n\n // in case auth header does not exist we return anonymous function\n req.remote_user = createAnonymousRemoteUser();\n\n const { authorization } = req.headers;\n if (_.isNil(authorization)) {\n debug('jwt, authentication header is missing');\n return next();\n }\n\n if (!isAuthHeaderValid(authorization)) {\n debug('api middleware authentication heather is invalid');\n return next(getBadRequest(API_ERROR.BAD_AUTH_HEADER));\n }\n const { secret, security } = this.config;\n\n if (isAESLegacy(security)) {\n debug('api middleware using legacy auth token');\n this._handleAESMiddleware(req, security, secret, authorization, next);\n } else {\n debug('api middleware using JWT auth token');\n this._handleJWTAPIMiddleware(req, security, secret, authorization, next);\n }\n };\n }\n\n private _handleJWTAPIMiddleware(\n req: $RequestExtend,\n security: Security,\n secret: string,\n authorization: string,\n next: Function\n ): void {\n debug('handle JWT api middleware');\n const { scheme, token } = parseAuthTokenHeader(authorization);\n if (scheme.toUpperCase() === TOKEN_BASIC.toUpperCase()) {\n debug('handle basic token');\n // this should happen when client tries to login with an existing user\n const credentials = convertPayloadToBase64(token).toString();\n const { user, password } = parseBasicPayload(credentials) as AESPayload;\n debug('authenticating %o', user);\n this.authenticate(user, password, (err, user): void => {\n if (!err) {\n debug('generating a remote user');\n req.remote_user = user;\n next();\n } else {\n debug('generating anonymous user');\n req.remote_user = createAnonymousRemoteUser();\n next(err);\n }\n });\n } else {\n debug('handle jwt token');\n const credentials: any = getMiddlewareCredentials(security, secret, authorization);\n if (credentials) {\n // if the signature is valid we rely on it\n req.remote_user = credentials;\n debug('generating a remote user');\n next();\n } else {\n // with JWT throw 401\n debug('jwt invalid token');\n next(getForbidden(API_ERROR.BAD_USERNAME_PASSWORD));\n }\n }\n }\n\n private _handleAESMiddleware(\n req: $RequestExtend,\n security: Security,\n secret: string,\n authorization: string,\n next: Function\n ): void {\n debug('handle legacy api middleware');\n debug('api middleware secret %o', secret);\n debug('api middleware authorization %o', authorization);\n const credentials: any = getMiddlewareCredentials(security, secret, authorization);\n debug('api middleware credentials %o', credentials);\n if (credentials) {\n const { user, password } = credentials;\n debug('authenticating %o', user);\n this.authenticate(user, password, (err, user): void => {\n if (!err) {\n req.remote_user = user;\n debug('generating a remote user');\n next();\n } else {\n req.remote_user = createAnonymousRemoteUser();\n debug('generating anonymous user');\n next(err);\n }\n });\n } else {\n // we force npm client to ask again with basic authentication\n debug('legacy invalid header');\n return next(getBadRequest(API_ERROR.BAD_AUTH_HEADER));\n }\n }\n\n private _isRemoteUserValid(remote_user: RemoteUser): boolean {\n return _.isUndefined(remote_user) === false && _.isUndefined(remote_user.name) === false;\n }\n\n /**\n * JWT middleware for WebUI\n */\n public webUIJWTmiddleware(): Function {\n return (req: $RequestExtend, res: $ResponseExtend, _next: NextFunction): void => {\n if (this._isRemoteUserValid(req.remote_user)) {\n return _next();\n }\n\n req.pause();\n const next = (err: VerdaccioError | void): void => {\n req.resume();\n if (err) {\n // req.remote_user.error = err.message;\n res.status(err.statusCode).send(err.message);\n }\n\n return _next();\n };\n\n const { authorization } = req.headers;\n if (_.isNil(authorization)) {\n return next();\n }\n\n if (!isAuthHeaderValid(authorization)) {\n return next(getBadRequest(API_ERROR.BAD_AUTH_HEADER));\n }\n\n const token = (authorization || '').replace(`${TOKEN_BEARER} `, '');\n if (!token) {\n return next();\n }\n\n let credentials;\n try {\n credentials = verifyJWTPayload(token, this.config.secret);\n } catch (err: any) {\n // FIXME: intended behaviour, do we want it?\n }\n\n if (this._isRemoteUserValid(credentials)) {\n const { name, groups } = credentials;\n // $FlowFixMe\n req.remote_user = createRemoteUser(name, groups);\n } else {\n req.remote_user = createAnonymousRemoteUser();\n }\n\n next();\n };\n }\n\n public async jwtEncrypt(user: RemoteUser, signOptions: JWTSignOptions): Promise<string> {\n const { real_groups, name, groups } = user;\n debug('jwt encrypt %o', name);\n const realGroupsValidated = _.isNil(real_groups) ? [] : real_groups;\n const groupedGroups = _.isNil(groups) ? real_groups : groups.concat(realGroupsValidated);\n const payload: RemoteUser = {\n real_groups: realGroupsValidated,\n name,\n groups: groupedGroups,\n };\n\n const token: string = await signPayload(payload, this.secret, signOptions);\n\n return token;\n }\n\n /**\n * Encrypt a string.\n */\n public aesEncrypt(value: string): string | void {\n return aesEncrypt(value, this.secret);\n }\n}\n\nexport { Auth };\n"],"file":"auth.js"}
|
|
1
|
+
{"version":3,"sources":["../src/auth.ts"],"names":["LoggerApi","require","debug","Auth","constructor","config","logger","child","sub","secret","TypeError","plugins","_","isNil","auth","_loadPlugin","loadDefaultPlugin","_applyDefaultPlugins","plugingConf","file","pluginOptions","authPlugin","HTPasswd","error","plugin","authenticate","allow_access","allow_publish","push","changePassword","username","password","newPassword","cb","validPlugins","filter","isEmpty","errorUtils","getInternalError","SUPPORT_ERRORS","PLUGIN_MISSING_INTERFACE","err","profile","invalidateToken","token","console","log","Promise","resolve","slice","next","shift","groups","message","length","isString","isGroupValid","isArray","API_ERROR","BAD_FORMAT_USER_GROUP","add_user","user","self","method","warn","ok","packageName","packageVersion","callback","pkgAllowAcces","name","version","pkg","Object","assign","packages","allow_unpublish","arguments","isError","apiJWTmiddleware","helpers","createAnonymousRemoteUser","createRemoteUser","req","res","_next","pause","resume","remote_user","_isRemoteUserValid","remoteUser","locals","authorization","headers","getBadRequest","BAD_AUTH_HEADER","security","_handleAESMiddleware","_handleJWTAPIMiddleware","scheme","toUpperCase","TOKEN_BASIC","credentials","toString","getForbidden","BAD_USERNAME_PASSWORD","isUndefined","webUIJWTmiddleware","status","statusCode","send","replace","TOKEN_BEARER","jwtEncrypt","signOptions","real_groups","realGroupsValidated","groupedGroups","concat","payload","aesEncrypt","value"],"mappings":"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","sourcesContent":["import buildDebug from 'debug';\nimport { NextFunction, Request, Response } from 'express';\nimport _ from 'lodash';\nimport { HTPasswd, HTPasswdConfig } from 'verdaccio-htpasswd';\n\nimport { createAnonymousRemoteUser, createRemoteUser } from '@verdaccio/config';\nimport {\n API_ERROR,\n SUPPORT_ERRORS,\n TOKEN_BASIC,\n TOKEN_BEARER,\n VerdaccioError,\n errorUtils,\n} from '@verdaccio/core';\nimport { loadPlugin } from '@verdaccio/loaders';\nimport {\n AllowAccess,\n AuthPluginPackage,\n Callback,\n Config,\n IPluginAuth,\n JWTSignOptions,\n Logger,\n PackageAccess,\n PluginOptions,\n RemoteUser,\n Security,\n} from '@verdaccio/types';\nimport { getMatchedPackagesSpec, isFunction, isNil } from '@verdaccio/utils';\n\nimport { signPayload } from './jwt-token';\nimport { aesEncrypt } from './legacy-token';\nimport { parseBasicPayload } from './token';\nimport {\n convertPayloadToBase64,\n getDefaultPlugins,\n getMiddlewareCredentials,\n isAESLegacy,\n isAuthHeaderValid,\n parseAuthTokenHeader,\n verifyJWTPayload,\n} from './utils';\n\n/* eslint-disable @typescript-eslint/no-var-requires */\nconst LoggerApi = require('@verdaccio/logger');\n\nconst debug = buildDebug('verdaccio:auth');\n\nexport interface IBasicAuth<T> {\n config: T & Config;\n authenticate(user: string, password: string, cb: Callback): void;\n invalidateToken?(token: string): Promise<void>;\n changePassword(user: string, password: string, newPassword: string, cb: Callback): void;\n allow_access(pkg: AuthPluginPackage, user: RemoteUser, callback: Callback): void;\n add_user(user: string, password: string, cb: Callback): any;\n}\n\nexport interface TokenEncryption {\n jwtEncrypt(user: RemoteUser, signOptions: JWTSignOptions): Promise<string>;\n aesEncrypt(buf: string): string | void;\n}\n\nexport interface AESPayload {\n user: string;\n password: string;\n}\n\nexport type $RequestExtend = Request & { remote_user?: any; log: Logger };\nexport type $ResponseExtend = Response & { cookies?: any };\nexport type $NextFunctionVer = NextFunction & any;\n\nexport interface IAuthMiddleware {\n apiJWTmiddleware(): $NextFunctionVer;\n webUIJWTmiddleware(): $NextFunctionVer;\n}\n\nexport interface IAuth extends IBasicAuth<Config>, IAuthMiddleware, TokenEncryption {\n config: Config;\n logger: Logger;\n secret: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n plugins: any[];\n allow_unpublish(pkg: AuthPluginPackage, user: RemoteUser, callback: Callback): void;\n invalidateToken(token: string): Promise<void>;\n}\n\nclass Auth implements IAuth {\n public config: Config;\n public logger: Logger;\n public secret: string;\n public plugins: IPluginAuth<Config>[];\n\n public constructor(config: Config) {\n this.config = config;\n this.logger = LoggerApi.logger.child({ sub: 'auth' });\n this.secret = config.secret;\n if (!this.secret) {\n throw new TypeError('secret it is required value on initialize the auth class');\n }\n\n this.plugins =\n _.isNil(config?.auth) === false ? this._loadPlugin(config) : this.loadDefaultPlugin(config);\n this._applyDefaultPlugins();\n }\n\n private loadDefaultPlugin(config: Config) {\n const plugingConf: HTPasswdConfig = { ...config, file: './htpasswd' };\n const pluginOptions: PluginOptions<{}> = {\n config,\n logger: this.logger,\n };\n let authPlugin;\n try {\n authPlugin = new HTPasswd(plugingConf, pluginOptions);\n } catch (error: any) {\n debug('error on loading auth htpasswd plugin stack: %o', error);\n return [];\n }\n\n return [authPlugin];\n }\n\n private _loadPlugin(config: Config): IPluginAuth<Config>[] {\n const pluginOptions = {\n config,\n logger: this.logger,\n };\n\n return loadPlugin<IPluginAuth<Config>>(\n config,\n config.auth,\n pluginOptions,\n (plugin: IPluginAuth<Config>): boolean => {\n const { authenticate, allow_access, allow_publish } = plugin;\n\n // @ts-ignore\n return authenticate || allow_access || allow_publish;\n }\n );\n }\n\n private _applyDefaultPlugins(): void {\n // TODO: rename to applyFallbackPluginMethods\n this.plugins.push(getDefaultPlugins(this.logger));\n }\n\n public changePassword(\n username: string,\n password: string,\n newPassword: string,\n cb: Callback\n ): void {\n const validPlugins = _.filter(this.plugins, (plugin) => isFunction(plugin.changePassword));\n\n if (_.isEmpty(validPlugins)) {\n return cb(errorUtils.getInternalError(SUPPORT_ERRORS.PLUGIN_MISSING_INTERFACE));\n }\n\n for (const plugin of validPlugins) {\n if (isNil(plugin) || isFunction(plugin.changePassword) === false) {\n debug('auth plugin does not implement changePassword, trying next one');\n continue;\n } else {\n debug('updating password for %o', username);\n plugin.changePassword!(username, password, newPassword, (err, profile): void => {\n if (err) {\n this.logger.error(\n { username, err },\n `An error has been produced\n updating the password for @{username}. Error: @{err.message}`\n );\n return cb(err);\n }\n\n debug('updated password for %o was successful', username);\n return cb(null, profile);\n });\n }\n }\n }\n\n public async invalidateToken(token: string) {\n // eslint-disable-next-line no-console\n console.log('invalidate token pending to implement', token);\n return Promise.resolve();\n }\n\n public authenticate(username: string, password: string, cb: Callback): void {\n const plugins = this.plugins.slice(0);\n (function next(): void {\n const plugin = plugins.shift() as IPluginAuth<Config>;\n\n if (isFunction(plugin.authenticate) === false) {\n return next();\n }\n\n debug('authenticating %o', username);\n plugin.authenticate(username, password, function (err, groups): void {\n if (err) {\n debug('authenticating for user %o failed. Error: %o', username, err?.message);\n return cb(err);\n }\n\n // Expect: SKIP if groups is falsey and not an array\n // with at least one item (truthy length)\n // Expect: CONTINUE otherwise (will error if groups is not\n // an array, but this is current behavior)\n // Caveat: STRING (if valid) will pass successfully\n // bug give unexpected results\n // Info: Cannot use `== false to check falsey values`\n if (!!groups && groups.length !== 0) {\n // TODO: create a better understanding of expectations\n if (_.isString(groups)) {\n throw new TypeError('plugin group error: invalid type for function');\n }\n const isGroupValid: boolean = _.isArray(groups);\n if (!isGroupValid) {\n throw new TypeError(API_ERROR.BAD_FORMAT_USER_GROUP);\n }\n\n debug('authentication for user %o was successfully. Groups: %o', username, groups);\n return cb(err, createRemoteUser(username, groups));\n }\n next();\n });\n })();\n }\n\n public add_user(user: string, password: string, cb: Callback): void {\n const self = this;\n const plugins = this.plugins.slice(0);\n debug('add user %o', user);\n\n (function next(): void {\n const plugin = plugins.shift() as IPluginAuth<Config>;\n let method = 'adduser';\n if (isFunction(plugin[method]) === false) {\n method = 'add_user';\n self.logger.warn(\n 'the plugin method add_user in the auth plugin is deprecated and will' +\n ' be removed in next major release, notify to the plugin author'\n );\n }\n\n if (isFunction(plugin[method]) === false) {\n next();\n } else {\n // p.add_user() execution\n plugin[method](user, password, function (err, ok): void {\n if (err) {\n debug('the user %o could not being added. Error: %o', user, err?.message);\n return cb(err);\n }\n if (ok) {\n debug('the user %o has been added', user);\n return self.authenticate(user, password, cb);\n }\n next();\n });\n }\n })();\n }\n\n /**\n * Allow user to access a package.\n */\n public allow_access(\n { packageName, packageVersion }: AuthPluginPackage,\n user: RemoteUser,\n callback: Callback\n ): void {\n const plugins = this.plugins.slice(0);\n const pkgAllowAcces: AllowAccess = { name: packageName, version: packageVersion };\n const pkg = Object.assign(\n {},\n pkgAllowAcces,\n getMatchedPackagesSpec(packageName, this.config.packages)\n ) as AllowAccess & PackageAccess;\n debug('allow access for %o', packageName);\n\n (function next(): void {\n const plugin: IPluginAuth<Config> = plugins.shift() as IPluginAuth<Config>;\n\n if (_.isNil(plugin) || isFunction(plugin.allow_access) === false) {\n return next();\n }\n\n plugin.allow_access!(user, pkg, function (err, ok: boolean): void {\n if (err) {\n debug('forbidden access for %o. Error: %o', packageName, err?.message);\n return callback(err);\n }\n\n if (ok) {\n debug('allowed access for %o', packageName);\n return callback(null, ok);\n }\n\n next(); // cb(null, false) causes next plugin to roll\n });\n })();\n }\n\n public allow_unpublish(\n { packageName, packageVersion }: AuthPluginPackage,\n user: RemoteUser,\n callback: Callback\n ): void {\n const pkg = Object.assign(\n { name: packageName, version: packageVersion },\n getMatchedPackagesSpec(packageName, this.config.packages)\n );\n debug('allow unpublish for %o', packageName);\n\n for (const plugin of this.plugins) {\n if (_.isNil(plugin) || isFunction(plugin.allow_unpublish) === false) {\n debug('allow unpublish for %o plugin does not implement allow_unpublish', packageName);\n continue;\n } else {\n // @ts-ignore\n plugin.allow_unpublish!(user, pkg, (err, ok: boolean): void => {\n if (err) {\n debug(\n 'forbidden publish for %o, it will fallback on unpublish permissions',\n packageName\n );\n return callback(err);\n }\n\n if (_.isNil(ok) === true) {\n debug('bypass unpublish for %o, publish will handle the access', packageName);\n // @ts-ignore\n // eslint-disable-next-line\n return this.allow_publish(...arguments);\n }\n\n if (ok) {\n debug('allowed unpublish for %o', packageName);\n return callback(null, ok);\n }\n });\n }\n }\n }\n\n /**\n * Allow user to publish a package.\n */\n public allow_publish(\n { packageName, packageVersion }: AuthPluginPackage,\n user: RemoteUser,\n callback: Callback\n ): void {\n const plugins = this.plugins.slice(0);\n const pkg = Object.assign(\n { name: packageName, version: packageVersion },\n getMatchedPackagesSpec(packageName, this.config.packages)\n );\n debug('allow publish for %o init | plugins: %o', packageName, plugins.length);\n\n (function next(): void {\n const plugin = plugins.shift();\n\n if (isFunction(plugin?.allow_publish) === false) {\n debug('allow publish for %o plugin does not implement allow_publish', packageName);\n return next();\n }\n\n // @ts-ignore\n plugin.allow_publish(\n user,\n // @ts-ignore\n pkg,\n // @ts-ignore\n (err: VerdaccioError, ok: boolean): void => {\n if (_.isNil(err) === false && _.isError(err)) {\n debug('forbidden publish for %o', packageName);\n return callback(err);\n }\n\n if (ok) {\n debug('allowed publish for %o', packageName);\n return callback(null, ok);\n }\n\n debug('allow publish skip validation for %o', packageName);\n next(); // cb(null, false) causes next plugin to roll\n }\n );\n })();\n }\n\n public apiJWTmiddleware(): Function {\n debug('jwt middleware');\n const plugins = this.plugins.slice(0);\n const helpers = { createAnonymousRemoteUser, createRemoteUser };\n for (const plugin of plugins) {\n if (plugin.apiJWTmiddleware) {\n return plugin.apiJWTmiddleware(helpers);\n }\n }\n\n return (req: $RequestExtend, res: $ResponseExtend, _next: NextFunction): void => {\n req.pause();\n\n const next = function (err: VerdaccioError | void): void {\n req.resume();\n // uncomment this to reject users with bad auth headers\n // return _next.apply(null, arguments)\n // swallow error, user remains unauthorized\n // set remoteUserError to indicate that user was attempting authentication\n if (err) {\n req.remote_user.error = err.message;\n }\n return _next();\n };\n\n if (this._isRemoteUserValid(req.remote_user)) {\n debug('jwt has a valid authentication header');\n return next();\n }\n\n // in case auth header does not exist we return anonymous function\n const remoteUser = createAnonymousRemoteUser();\n req.remote_user = remoteUser;\n res.locals.remote_user = remoteUser;\n\n const { authorization } = req.headers;\n if (_.isNil(authorization)) {\n debug('jwt, authentication header is missing');\n return next();\n }\n\n if (!isAuthHeaderValid(authorization)) {\n debug('api middleware authentication heather is invalid');\n return next(errorUtils.getBadRequest(API_ERROR.BAD_AUTH_HEADER));\n }\n const { secret, security } = this.config;\n\n if (isAESLegacy(security)) {\n debug('api middleware using legacy auth token');\n this._handleAESMiddleware(req, security, secret, authorization, next);\n } else {\n debug('api middleware using JWT auth token');\n this._handleJWTAPIMiddleware(req, security, secret, authorization, next);\n }\n };\n }\n\n private _handleJWTAPIMiddleware(\n req: $RequestExtend,\n security: Security,\n secret: string,\n authorization: string,\n next: Function\n ): void {\n debug('handle JWT api middleware');\n const { scheme, token } = parseAuthTokenHeader(authorization);\n if (scheme.toUpperCase() === TOKEN_BASIC.toUpperCase()) {\n debug('handle basic token');\n // this should happen when client tries to login with an existing user\n const credentials = convertPayloadToBase64(token).toString();\n const { user, password } = parseBasicPayload(credentials) as AESPayload;\n debug('authenticating %o', user);\n this.authenticate(user, password, (err, user): void => {\n if (!err) {\n debug('generating a remote user');\n req.remote_user = user;\n next();\n } else {\n debug('generating anonymous user');\n req.remote_user = createAnonymousRemoteUser();\n next(err);\n }\n });\n } else {\n debug('handle jwt token');\n const credentials: any = getMiddlewareCredentials(security, secret, authorization);\n if (credentials) {\n // if the signature is valid we rely on it\n req.remote_user = credentials;\n debug('generating a remote user');\n next();\n } else {\n // with JWT throw 401\n debug('jwt invalid token');\n next(errorUtils.getForbidden(API_ERROR.BAD_USERNAME_PASSWORD));\n }\n }\n }\n\n private _handleAESMiddleware(\n req: $RequestExtend,\n security: Security,\n secret: string,\n authorization: string,\n next: Function\n ): void {\n debug('handle legacy api middleware');\n debug('api middleware secret %o', secret);\n debug('api middleware authorization %o', authorization);\n const credentials: any = getMiddlewareCredentials(security, secret, authorization);\n debug('api middleware credentials %o', credentials);\n if (credentials) {\n const { user, password } = credentials;\n debug('authenticating %o', user);\n this.authenticate(user, password, (err, user): void => {\n if (!err) {\n req.remote_user = user;\n debug('generating a remote user');\n next();\n } else {\n req.remote_user = createAnonymousRemoteUser();\n debug('generating anonymous user');\n next(err);\n }\n });\n } else {\n // we force npm client to ask again with basic authentication\n debug('legacy invalid header');\n return next(errorUtils.getBadRequest(API_ERROR.BAD_AUTH_HEADER));\n }\n }\n\n private _isRemoteUserValid(remote_user: RemoteUser): boolean {\n return _.isUndefined(remote_user) === false && _.isUndefined(remote_user.name) === false;\n }\n\n /**\n * JWT middleware for WebUI\n */\n public webUIJWTmiddleware(): Function {\n return (req: $RequestExtend, res: $ResponseExtend, _next: NextFunction): void => {\n if (this._isRemoteUserValid(req.remote_user)) {\n return _next();\n }\n\n req.pause();\n const next = (err: VerdaccioError | void): void => {\n req.resume();\n if (err) {\n // req.remote_user.error = err.message;\n res.status(err.statusCode).send(err.message);\n }\n\n return _next();\n };\n\n const { authorization } = req.headers;\n if (_.isNil(authorization)) {\n return next();\n }\n\n if (!isAuthHeaderValid(authorization)) {\n return next(errorUtils.getBadRequest(API_ERROR.BAD_AUTH_HEADER));\n }\n\n const token = (authorization || '').replace(`${TOKEN_BEARER} `, '');\n if (!token) {\n return next();\n }\n\n let credentials;\n try {\n credentials = verifyJWTPayload(token, this.config.secret);\n } catch (err: any) {\n // FIXME: intended behaviour, do we want it?\n }\n\n if (this._isRemoteUserValid(credentials)) {\n const { name, groups } = credentials;\n // $FlowFixMe\n req.remote_user = createRemoteUser(name, groups);\n } else {\n req.remote_user = createAnonymousRemoteUser();\n }\n\n next();\n };\n }\n\n public async jwtEncrypt(user: RemoteUser, signOptions: JWTSignOptions): Promise<string> {\n const { real_groups, name, groups } = user;\n debug('jwt encrypt %o', name);\n const realGroupsValidated = _.isNil(real_groups) ? [] : real_groups;\n const groupedGroups = _.isNil(groups) ? real_groups : groups.concat(realGroupsValidated);\n const payload: RemoteUser = {\n real_groups: realGroupsValidated,\n name,\n groups: groupedGroups,\n };\n\n const token: string = await signPayload(payload, this.secret, signOptions);\n\n return token;\n }\n\n /**\n * Encrypt a string.\n */\n public aesEncrypt(value: string): string | void {\n return aesEncrypt(value, this.secret);\n }\n}\n\nexport { Auth };\n"],"file":"auth.js"}
|
package/build/index.js
CHANGED
|
@@ -21,16 +21,16 @@ Object.defineProperty(exports, "IAuth", {
|
|
|
21
21
|
return _auth.IAuth;
|
|
22
22
|
}
|
|
23
23
|
});
|
|
24
|
-
Object.defineProperty(exports, "
|
|
24
|
+
Object.defineProperty(exports, "IBasicAuth", {
|
|
25
25
|
enumerable: true,
|
|
26
26
|
get: function () {
|
|
27
|
-
return _auth.
|
|
27
|
+
return _auth.IBasicAuth;
|
|
28
28
|
}
|
|
29
29
|
});
|
|
30
|
-
Object.defineProperty(exports, "
|
|
30
|
+
Object.defineProperty(exports, "TokenEncryption", {
|
|
31
31
|
enumerable: true,
|
|
32
32
|
get: function () {
|
|
33
|
-
return _auth.
|
|
33
|
+
return _auth.TokenEncryption;
|
|
34
34
|
}
|
|
35
35
|
});
|
|
36
36
|
|
package/build/jwt-token.js
CHANGED
|
@@ -6,17 +6,11 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.signPayload = signPayload;
|
|
7
7
|
exports.verifyPayload = verifyPayload;
|
|
8
8
|
|
|
9
|
-
var _jsonwebtoken = _interopRequireDefault(require("jsonwebtoken"));
|
|
10
|
-
|
|
11
9
|
var _debug = _interopRequireDefault(require("debug"));
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
|
|
16
|
-
|
|
17
|
-
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
|
11
|
+
var _jsonwebtoken = _interopRequireDefault(require("jsonwebtoken"));
|
|
18
12
|
|
|
19
|
-
function
|
|
13
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
20
14
|
|
|
21
15
|
const debug = (0, _debug.default)('verdaccio:auth:token:jwt');
|
|
22
16
|
/**
|
|
@@ -30,10 +24,12 @@ const debug = (0, _debug.default)('verdaccio:auth:token:jwt');
|
|
|
30
24
|
async function signPayload(payload, secretOrPrivateKey, options = {}) {
|
|
31
25
|
return new Promise(function (resolve, reject) {
|
|
32
26
|
debug('sign jwt token');
|
|
33
|
-
return _jsonwebtoken.default.sign(payload, secretOrPrivateKey,
|
|
27
|
+
return _jsonwebtoken.default.sign(payload, secretOrPrivateKey, {
|
|
34
28
|
// 1 === 1ms (one millisecond)
|
|
35
|
-
notBefore: '1'
|
|
36
|
-
|
|
29
|
+
notBefore: '1',
|
|
30
|
+
// Make sure the time will not rollback :)
|
|
31
|
+
...options
|
|
32
|
+
}, (error, token) => {
|
|
37
33
|
debug('error on sign jwt token');
|
|
38
34
|
return error ? reject(error) : resolve(token);
|
|
39
35
|
});
|
package/build/jwt-token.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/jwt-token.ts"],"names":["debug","signPayload","payload","secretOrPrivateKey","options","Promise","resolve","reject","jwt","sign","notBefore","error","token","verifyPayload","verify"],"mappings":";;;;;;;;AAAA;;AACA
|
|
1
|
+
{"version":3,"sources":["../src/jwt-token.ts"],"names":["debug","signPayload","payload","secretOrPrivateKey","options","Promise","resolve","reject","jwt","sign","notBefore","error","token","verifyPayload","verify"],"mappings":";;;;;;;;AAAA;;AACA;;;;AAIA,MAAMA,KAAK,GAAG,oBAAW,0BAAX,CAAd;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACO,eAAeC,WAAf,CACLC,OADK,EAELC,kBAFK,EAGLC,OAAuB,GAAG,EAHrB,EAIY;AACjB,SAAO,IAAIC,OAAJ,CAAY,UAAUC,OAAV,EAAmBC,MAAnB,EAA4C;AAC7DP,IAAAA,KAAK,CAAC,gBAAD,CAAL;AACA,WAAOQ,sBAAIC,IAAJ,CACLP,OADK,EAELC,kBAFK,EAGL;AACE;AACAO,MAAAA,SAAS,EAAE,GAFb;AAEkB;AAChB,SAAGN;AAHL,KAHK,EAQL,CAACO,KAAD,EAAQC,KAAR,KAAkB;AAChBZ,MAAAA,KAAK,CAAC,yBAAD,CAAL;AACA,aAAOW,KAAK,GAAGJ,MAAM,CAACI,KAAD,CAAT,GAAmBL,OAAO,CAACM,KAAD,CAAtC;AACD,KAXI,CAAP;AAaD,GAfM,CAAP;AAgBD;;AAEM,SAASC,aAAT,CAAuBD,KAAvB,EAAsCT,kBAAtC,EAA8E;AACnFH,EAAAA,KAAK,CAAC,kBAAD,CAAL;AACA,SAAOQ,sBAAIM,MAAJ,CAAWF,KAAX,EAAkBT,kBAAlB,CAAP;AACD","sourcesContent":["import buildDebug from 'debug';\nimport jwt from 'jsonwebtoken';\n\nimport { JWTSignOptions, RemoteUser } from '@verdaccio/types';\n\nconst debug = buildDebug('verdaccio:auth:token:jwt');\n/**\n * Sign the payload and return JWT\n * https://github.com/auth0/node-jsonwebtoken#jwtsignpayload-secretorprivatekey-options-callback\n * @param payload\n * @param secretOrPrivateKey\n * @param options\n */\nexport async function signPayload(\n payload: RemoteUser,\n secretOrPrivateKey: string,\n options: JWTSignOptions = {}\n): Promise<string> {\n return new Promise(function (resolve, reject): Promise<string> {\n debug('sign jwt token');\n return jwt.sign(\n payload,\n secretOrPrivateKey,\n {\n // 1 === 1ms (one millisecond)\n notBefore: '1', // Make sure the time will not rollback :)\n ...options,\n },\n (error, token) => {\n debug('error on sign jwt token');\n return error ? reject(error) : resolve(token);\n }\n );\n });\n}\n\nexport function verifyPayload(token: string, secretOrPrivateKey: string): RemoteUser {\n debug('verify jwt token');\n return jwt.verify(token, secretOrPrivateKey);\n}\n"],"file":"jwt-token.js"}
|
package/build/legacy-token.js
CHANGED
|
@@ -3,16 +3,16 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.aesEncrypt = aesEncrypt;
|
|
7
6
|
exports.aesDecrypt = aesDecrypt;
|
|
7
|
+
exports.aesEncrypt = aesEncrypt;
|
|
8
8
|
exports.defaultAlgorithm = void 0;
|
|
9
9
|
|
|
10
10
|
var _crypto = require("crypto");
|
|
11
11
|
|
|
12
|
-
var _config = require("@verdaccio/config");
|
|
13
|
-
|
|
14
12
|
var _debug = _interopRequireDefault(require("debug"));
|
|
15
13
|
|
|
14
|
+
var _config = require("@verdaccio/config");
|
|
15
|
+
|
|
16
16
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
17
17
|
|
|
18
18
|
const debug = (0, _debug.default)('verdaccio:auth:token:legacy');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/legacy-token.ts"],"names":["debug","defaultAlgorithm","process","env","VERDACCIO_LEGACY_ALGORITHM","inputEncoding","outputEncoding","IV_LENGTH","VERDACCIO_LEGACY_ENCRYPTION_KEY","aesEncrypt","value","key","iv","Buffer","from","secretKey","isKeyValid","length","TOKEN_VALID_LENGTH","cipher","encrypted","update","final","token","toString","aesDecrypt","buff","textParts","split","IV","shift","encryptedText","join","decipher","decrypted","_"],"mappings":";;;;;;;;;AAAA;;AAOA;;
|
|
1
|
+
{"version":3,"sources":["../src/legacy-token.ts"],"names":["debug","defaultAlgorithm","process","env","VERDACCIO_LEGACY_ALGORITHM","inputEncoding","outputEncoding","IV_LENGTH","VERDACCIO_LEGACY_ENCRYPTION_KEY","aesEncrypt","value","key","iv","Buffer","from","secretKey","isKeyValid","length","TOKEN_VALID_LENGTH","cipher","encrypted","update","final","token","toString","aesDecrypt","buff","textParts","split","IV","shift","encryptedText","join","decipher","decrypted","_"],"mappings":"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","sourcesContent":["import {\n HexBase64BinaryEncoding,\n Utf8AsciiBinaryEncoding,\n createCipheriv,\n createDecipheriv,\n randomBytes,\n} from 'crypto';\nimport buildDebug from 'debug';\n\nimport { TOKEN_VALID_LENGTH } from '@verdaccio/config';\n\nconst debug = buildDebug('verdaccio:auth:token:legacy');\n\nexport const defaultAlgorithm = process.env.VERDACCIO_LEGACY_ALGORITHM || 'aes-256-ctr';\nconst inputEncoding: Utf8AsciiBinaryEncoding = 'utf8';\nconst outputEncoding: HexBase64BinaryEncoding = 'hex';\n// For AES, this is always 16\nconst IV_LENGTH = 16;\n// Must be 256 bits (32 characters)\n// https://stackoverflow.com/questions/50963160/invalid-key-length-in-crypto-createcipheriv#50963356\nconst VERDACCIO_LEGACY_ENCRYPTION_KEY = process.env.VERDACCIO_LEGACY_ENCRYPTION_KEY;\n\nexport function aesEncrypt(value: string, key: string): string | void {\n // https://nodejs.org/api/crypto.html#crypto_crypto_createcipher_algorithm_password_options\n // https://www.grainger.xyz/changing-from-cipher-to-cipheriv/\n debug('encrypt %o', value);\n debug('algorithm %o', defaultAlgorithm);\n const iv = Buffer.from(randomBytes(IV_LENGTH));\n const secretKey = VERDACCIO_LEGACY_ENCRYPTION_KEY || key;\n const isKeyValid = secretKey?.length === TOKEN_VALID_LENGTH;\n debug('length secret key %o', secretKey?.length);\n debug('is valid secret %o', isKeyValid);\n if (!value || !secretKey || !isKeyValid) {\n return;\n }\n\n const cipher = createCipheriv(defaultAlgorithm, secretKey, iv);\n let encrypted = cipher.update(value, inputEncoding, outputEncoding);\n // @ts-ignore\n encrypted += cipher.final(outputEncoding);\n const token = `${iv.toString('hex')}:${encrypted.toString()}`;\n debug('token generated successfully');\n return Buffer.from(token).toString('base64');\n}\n\nexport function aesDecrypt(value: string, key: string): string | void {\n try {\n const buff = Buffer.from(value, 'base64');\n const textParts = buff.toString().split(':');\n\n // extract the IV from the first half of the value\n // @ts-ignore\n const IV = Buffer.from(textParts.shift(), outputEncoding);\n // extract the encrypted text without the IV\n const encryptedText = Buffer.from(textParts.join(':'), outputEncoding);\n const secretKey = VERDACCIO_LEGACY_ENCRYPTION_KEY || key;\n // decipher the string\n const decipher = createDecipheriv(defaultAlgorithm, secretKey, IV);\n let decrypted = decipher.update(encryptedText, outputEncoding, inputEncoding);\n decrypted += decipher.final(inputEncoding);\n debug('token decrypted successfully');\n return decrypted.toString();\n } catch (_: any) {\n return;\n }\n}\n"],"file":"legacy-token.js"}
|
package/build/utils.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { VerdaccioError } from '@verdaccio/core';
|
|
3
|
+
import { AuthPackageAllow, Config, IPluginAuth, RemoteUser, Security } from '@verdaccio/types';
|
|
4
|
+
import { AESPayload, TokenEncryption } from './auth';
|
|
5
5
|
export declare type BasicPayload = AESPayload | void;
|
|
6
6
|
export declare type AuthMiddlewarePayload = RemoteUser | BasicPayload;
|
|
7
7
|
export interface AuthTokenHeader {
|
package/build/utils.js
CHANGED
|
@@ -3,32 +3,32 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.parseAuthTokenHeader = parseAuthTokenHeader;
|
|
7
|
-
exports.parseAESCredentials = parseAESCredentials;
|
|
8
|
-
exports.getMiddlewareCredentials = getMiddlewareCredentials;
|
|
9
|
-
exports.isAESLegacy = isAESLegacy;
|
|
10
|
-
exports.getApiToken = getApiToken;
|
|
11
|
-
exports.verifyJWTPayload = verifyJWTPayload;
|
|
12
|
-
exports.isAuthHeaderValid = isAuthHeaderValid;
|
|
13
|
-
exports.getDefaultPlugins = getDefaultPlugins;
|
|
14
6
|
exports.allow_action = allow_action;
|
|
15
|
-
exports.handleSpecialUnpublish = handleSpecialUnpublish;
|
|
16
7
|
exports.buildUser = buildUser;
|
|
17
8
|
exports.convertPayloadToBase64 = convertPayloadToBase64;
|
|
18
9
|
exports.expireReasons = void 0;
|
|
19
|
-
|
|
20
|
-
|
|
10
|
+
exports.getApiToken = getApiToken;
|
|
11
|
+
exports.getDefaultPlugins = getDefaultPlugins;
|
|
12
|
+
exports.getMiddlewareCredentials = getMiddlewareCredentials;
|
|
13
|
+
exports.handleSpecialUnpublish = handleSpecialUnpublish;
|
|
14
|
+
exports.isAESLegacy = isAESLegacy;
|
|
15
|
+
exports.isAuthHeaderValid = isAuthHeaderValid;
|
|
16
|
+
exports.parseAESCredentials = parseAESCredentials;
|
|
17
|
+
exports.parseAuthTokenHeader = parseAuthTokenHeader;
|
|
18
|
+
exports.verifyJWTPayload = verifyJWTPayload;
|
|
21
19
|
|
|
22
20
|
var _debug = _interopRequireDefault(require("debug"));
|
|
23
21
|
|
|
24
|
-
var
|
|
22
|
+
var _lodash = _interopRequireDefault(require("lodash"));
|
|
25
23
|
|
|
26
24
|
var _config = require("@verdaccio/config");
|
|
27
25
|
|
|
28
|
-
var
|
|
26
|
+
var _core = require("@verdaccio/core");
|
|
29
27
|
|
|
30
28
|
var _jwtToken = require("./jwt-token");
|
|
31
29
|
|
|
30
|
+
var _legacyToken = require("./legacy-token");
|
|
31
|
+
|
|
32
32
|
var _token = require("./token");
|
|
33
33
|
|
|
34
34
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
@@ -56,11 +56,11 @@ function parseAESCredentials(authorizationHeader, secret) {
|
|
|
56
56
|
} = parseAuthTokenHeader(authorizationHeader); // basic is deprecated and should not be enforced
|
|
57
57
|
// basic is currently being used for functional test
|
|
58
58
|
|
|
59
|
-
if (scheme.toUpperCase() ===
|
|
59
|
+
if (scheme.toUpperCase() === _core.TOKEN_BASIC.toUpperCase()) {
|
|
60
60
|
debug('legacy header basic');
|
|
61
61
|
const credentials = convertPayloadToBase64(token).toString();
|
|
62
62
|
return credentials;
|
|
63
|
-
} else if (scheme.toUpperCase() ===
|
|
63
|
+
} else if (scheme.toUpperCase() === _core.TOKEN_BEARER.toUpperCase()) {
|
|
64
64
|
debug('legacy header bearer');
|
|
65
65
|
const credentials = (0, _legacyToken.aesDecrypt)(token, secret);
|
|
66
66
|
return credentials;
|
|
@@ -95,7 +95,7 @@ function getMiddlewareCredentials(security, secretKey, authorizationHeader) {
|
|
|
95
95
|
} = parseAuthTokenHeader(authorizationHeader);
|
|
96
96
|
debug('is jwt');
|
|
97
97
|
|
|
98
|
-
if (_lodash.default.isString(token) && scheme.toUpperCase() ===
|
|
98
|
+
if (_lodash.default.isString(token) && scheme.toUpperCase() === _core.TOKEN_BEARER.toUpperCase()) {
|
|
99
99
|
return verifyJWTPayload(token, secretKey);
|
|
100
100
|
}
|
|
101
101
|
}
|
|
@@ -151,7 +151,7 @@ function verifyJWTPayload(token, secret) {
|
|
|
151
151
|
return (0, _config.createAnonymousRemoteUser)();
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
-
throw
|
|
154
|
+
throw _core.errorUtils.getCode(_core.HTTP_STATUS.UNAUTHORIZED, error.message);
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
157
|
|
|
@@ -162,11 +162,11 @@ function isAuthHeaderValid(authorization) {
|
|
|
162
162
|
function getDefaultPlugins(logger) {
|
|
163
163
|
return {
|
|
164
164
|
authenticate(user, password, cb) {
|
|
165
|
-
cb(
|
|
165
|
+
cb(_core.errorUtils.getForbidden(_core.API_ERROR.BAD_USERNAME_PASSWORD));
|
|
166
166
|
},
|
|
167
167
|
|
|
168
168
|
adduser(user, password, cb) {
|
|
169
|
-
return cb(
|
|
169
|
+
return cb(_core.errorUtils.getConflict(_core.API_ERROR.BAD_USERNAME_PASSWORD));
|
|
170
170
|
},
|
|
171
171
|
|
|
172
172
|
// FIXME: allow_action and allow_publish should be in the @verdaccio/types
|
|
@@ -204,9 +204,9 @@ function allow_action(action, logger) {
|
|
|
204
204
|
}
|
|
205
205
|
|
|
206
206
|
if (name) {
|
|
207
|
-
callback(
|
|
207
|
+
callback(_core.errorUtils.getForbidden(`user ${name} is not allowed to ${action} package ${pkg.name}`));
|
|
208
208
|
} else {
|
|
209
|
-
callback(
|
|
209
|
+
callback(_core.errorUtils.getUnauthorized(`authorization required to ${action} package ${pkg.name}`));
|
|
210
210
|
}
|
|
211
211
|
};
|
|
212
212
|
}
|
package/build/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils.ts"],"names":["debug","parseAuthTokenHeader","authorizationHeader","parts","split","scheme","token","parseAESCredentials","secret","toUpperCase","TOKEN_BASIC","credentials","convertPayloadToBase64","toString","TOKEN_BEARER","getMiddlewareCredentials","security","secretKey","isAESLegacy","parsedCredentials","_","isString","verifyJWTPayload","legacy","jwt","api","isNil","getApiToken","auth","config","remoteUser","aesPassword","Promise","resolve","aesEncrypt","buildUser","name","sign","jwtEncrypt","expireReasons","payload","error","includes","HTTP_STATUS","UNAUTHORIZED","message","isAuthHeaderValid","authorization","length","getDefaultPlugins","logger","authenticate","user","password","cb","API_ERROR","BAD_USERNAME_PASSWORD","adduser","allow_access","allow_action","allow_publish","allow_unpublish","handleSpecialUnpublish","action","allowActionCallback","pkg","callback","trace","remote","groups","groupAccess","hasPermission","some","group","pkgName","isUnpublishMissing","hasGroups","undefined","String","Buffer","from"],"mappings":"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","sourcesContent":["import _ from 'lodash';\nimport buildDebug from 'debug';\nimport {\n Callback,\n Config,\n IPluginAuth,\n RemoteUser,\n Security,\n AuthPackageAllow,\n} from '@verdaccio/types';\nimport {\n HTTP_STATUS,\n TOKEN_BASIC,\n TOKEN_BEARER,\n API_ERROR,\n getForbidden,\n getUnauthorized,\n getConflict,\n getCode,\n} from '@verdaccio/commons-api';\nimport { VerdaccioError } from '@verdaccio/commons-api';\n\nimport { createAnonymousRemoteUser } from '@verdaccio/config';\nimport { TokenEncryption, AESPayload } from './auth';\nimport { aesDecrypt } from './legacy-token';\nimport { verifyPayload } from './jwt-token';\nimport { parseBasicPayload } from './token';\n\nconst debug = buildDebug('verdaccio:auth:utils');\n\nexport type BasicPayload = AESPayload | void;\nexport type AuthMiddlewarePayload = RemoteUser | BasicPayload;\n\nexport interface AuthTokenHeader {\n scheme: string;\n token: string;\n}\nexport type AllowActionCallbackResponse = boolean | undefined;\nexport type AllowActionCallback = (\n error: VerdaccioError | null,\n allowed?: AllowActionCallbackResponse\n) => void;\n\nexport type AllowAction = (\n user: RemoteUser,\n pkg: AuthPackageAllow,\n callback: AllowActionCallback\n) => void;\n\n/**\n * Split authentication header eg: Bearer [secret_token]\n * @param authorizationHeader auth token\n */\nexport function parseAuthTokenHeader(authorizationHeader: string): AuthTokenHeader {\n const parts = authorizationHeader.split(' ');\n const [scheme, token] = parts;\n\n return { scheme, token };\n}\n\nexport function parseAESCredentials(authorizationHeader: string, secret: string) {\n debug('parseAESCredentials');\n const { scheme, token } = parseAuthTokenHeader(authorizationHeader);\n\n // basic is deprecated and should not be enforced\n // basic is currently being used for functional test\n if (scheme.toUpperCase() === TOKEN_BASIC.toUpperCase()) {\n debug('legacy header basic');\n const credentials = convertPayloadToBase64(token).toString();\n\n return credentials;\n } else if (scheme.toUpperCase() === TOKEN_BEARER.toUpperCase()) {\n debug('legacy header bearer');\n const credentials = aesDecrypt(token, secret);\n\n return credentials;\n }\n}\n\nexport function getMiddlewareCredentials(\n security: Security,\n secretKey: string,\n authorizationHeader: string\n): AuthMiddlewarePayload {\n debug('getMiddlewareCredentials');\n // comment out for debugging purposes\n if (isAESLegacy(security)) {\n debug('is legacy');\n const credentials = parseAESCredentials(authorizationHeader, secretKey);\n if (!credentials) {\n debug('parse legacy credentials failed');\n return;\n }\n\n const parsedCredentials = parseBasicPayload(credentials);\n if (!parsedCredentials) {\n debug('parse legacy basic payload credentials failed');\n return;\n }\n\n return parsedCredentials;\n }\n const { scheme, token } = parseAuthTokenHeader(authorizationHeader);\n\n debug('is jwt');\n if (_.isString(token) && scheme.toUpperCase() === TOKEN_BEARER.toUpperCase()) {\n return verifyJWTPayload(token, secretKey);\n }\n}\n\nexport function isAESLegacy(security: Security): boolean {\n const { legacy, jwt } = security.api;\n\n return _.isNil(legacy) === false && _.isNil(jwt) && legacy === true;\n}\n\nexport async function getApiToken(\n auth: TokenEncryption,\n config: Config,\n remoteUser: RemoteUser,\n aesPassword: string\n): Promise<string | void> {\n debug('get api token');\n const { security } = config;\n\n if (isAESLegacy(security)) {\n debug('security legacy enabled');\n // fallback all goes to AES encryption\n return await new Promise((resolve): void => {\n resolve(auth.aesEncrypt(buildUser(remoteUser.name as string, aesPassword)));\n });\n }\n const { jwt } = security.api;\n\n if (jwt?.sign) {\n return await auth.jwtEncrypt(remoteUser, jwt.sign);\n }\n return await new Promise((resolve): void => {\n resolve(auth.aesEncrypt(buildUser(remoteUser.name as string, aesPassword)));\n });\n}\n\nexport const expireReasons: string[] = ['JsonWebTokenError', 'TokenExpiredError'];\n\nexport function verifyJWTPayload(token: string, secret: string): RemoteUser {\n try {\n const payload: RemoteUser = verifyPayload(token, secret);\n\n return payload;\n } catch (error: any) {\n // #168 this check should be removed as soon AES encrypt is removed.\n if (expireReasons.includes(error.name)) {\n // it might be possible the jwt configuration is enabled and\n // old tokens fails still remains in usage, thus\n // we return an anonymous user to force log in.\n return createAnonymousRemoteUser();\n }\n throw getCode(HTTP_STATUS.UNAUTHORIZED, error.message);\n }\n}\n\nexport function isAuthHeaderValid(authorization: string): boolean {\n return authorization.split(' ').length === 2;\n}\n\nexport function getDefaultPlugins(logger: any): IPluginAuth<Config> {\n return {\n authenticate(user: string, password: string, cb: Callback): void {\n cb(getForbidden(API_ERROR.BAD_USERNAME_PASSWORD));\n },\n\n adduser(user: string, password: string, cb: Callback): void {\n return cb(getConflict(API_ERROR.BAD_USERNAME_PASSWORD));\n },\n\n // FIXME: allow_action and allow_publish should be in the @verdaccio/types\n // @ts-ignore\n allow_access: allow_action('access', logger),\n // @ts-ignore\n allow_publish: allow_action('publish', logger),\n allow_unpublish: handleSpecialUnpublish(logger),\n };\n}\n\nexport type ActionsAllowed = 'publish' | 'unpublish' | 'access';\n\nexport function allow_action(action: ActionsAllowed, logger): AllowAction {\n return function allowActionCallback(\n user: RemoteUser,\n pkg: AuthPackageAllow,\n callback: AllowActionCallback\n ): void {\n logger.trace({ remote: user.name }, `[auth/allow_action]: user: @{user.name}`);\n const { name, groups } = user;\n const groupAccess = pkg[action] as string[];\n const hasPermission = groupAccess.some((group) => name === group || groups.includes(group));\n logger.trace(\n { pkgName: pkg.name, hasPermission, remote: user.name, groupAccess },\n `[auth/allow_action]: hasPermission? @{hasPermission} for user: @{user}`\n );\n\n if (hasPermission) {\n logger.trace({ remote: user.name }, `auth/allow_action: access granted to: @{user}`);\n return callback(null, true);\n }\n\n if (name) {\n callback(getForbidden(`user ${name} is not allowed to ${action} package ${pkg.name}`));\n } else {\n callback(getUnauthorized(`authorization required to ${action} package ${pkg.name}`));\n }\n };\n}\n\n/**\n *\n */\nexport function handleSpecialUnpublish(logger): any {\n return function (user: RemoteUser, pkg: AuthPackageAllow, callback: AllowActionCallback): void {\n const action = 'unpublish';\n // verify whether the unpublish prop has been defined\n const isUnpublishMissing: boolean = _.isNil(pkg[action]);\n const hasGroups: boolean = isUnpublishMissing ? false : (pkg[action] as string[]).length > 0;\n logger.trace(\n { user: user.name, name: pkg.name, hasGroups },\n `fallback unpublish for @{name} has groups: @{hasGroups} for @{user}`\n );\n\n if (isUnpublishMissing || hasGroups === false) {\n return callback(null, undefined);\n }\n\n logger.trace(\n { user: user.name, name: pkg.name, action, hasGroups },\n `allow_action for @{action} for @{name} has groups: @{hasGroups} for @{user}`\n );\n return allow_action(action, logger)(user, pkg, callback);\n };\n}\n\nexport function buildUser(name: string, password: string): string {\n return String(`${name}:${password}`);\n}\n\nexport function convertPayloadToBase64(payload: string): Buffer {\n return Buffer.from(payload, 'base64');\n}\n"],"file":"utils.js"}
|
|
1
|
+
{"version":3,"sources":["../src/utils.ts"],"names":["debug","parseAuthTokenHeader","authorizationHeader","parts","split","scheme","token","parseAESCredentials","secret","toUpperCase","TOKEN_BASIC","credentials","convertPayloadToBase64","toString","TOKEN_BEARER","getMiddlewareCredentials","security","secretKey","isAESLegacy","parsedCredentials","_","isString","verifyJWTPayload","legacy","jwt","api","isNil","getApiToken","auth","config","remoteUser","aesPassword","Promise","resolve","aesEncrypt","buildUser","name","sign","jwtEncrypt","expireReasons","payload","error","includes","errorUtils","getCode","HTTP_STATUS","UNAUTHORIZED","message","isAuthHeaderValid","authorization","length","getDefaultPlugins","logger","authenticate","user","password","cb","getForbidden","API_ERROR","BAD_USERNAME_PASSWORD","adduser","getConflict","allow_access","allow_action","allow_publish","allow_unpublish","handleSpecialUnpublish","action","allowActionCallback","pkg","callback","trace","remote","groups","groupAccess","hasPermission","some","group","pkgName","getUnauthorized","isUnpublishMissing","hasGroups","undefined","String","Buffer","from"],"mappings":"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","sourcesContent":["import buildDebug from 'debug';\nimport _ from 'lodash';\n\nimport { createAnonymousRemoteUser } from '@verdaccio/config';\nimport {\n API_ERROR,\n HTTP_STATUS,\n TOKEN_BASIC,\n TOKEN_BEARER,\n VerdaccioError,\n errorUtils,\n} from '@verdaccio/core';\nimport {\n AuthPackageAllow,\n Callback,\n Config,\n IPluginAuth,\n RemoteUser,\n Security,\n} from '@verdaccio/types';\n\nimport { AESPayload, TokenEncryption } from './auth';\nimport { verifyPayload } from './jwt-token';\nimport { aesDecrypt } from './legacy-token';\nimport { parseBasicPayload } from './token';\n\nconst debug = buildDebug('verdaccio:auth:utils');\n\nexport type BasicPayload = AESPayload | void;\nexport type AuthMiddlewarePayload = RemoteUser | BasicPayload;\n\nexport interface AuthTokenHeader {\n scheme: string;\n token: string;\n}\nexport type AllowActionCallbackResponse = boolean | undefined;\nexport type AllowActionCallback = (\n error: VerdaccioError | null,\n allowed?: AllowActionCallbackResponse\n) => void;\n\nexport type AllowAction = (\n user: RemoteUser,\n pkg: AuthPackageAllow,\n callback: AllowActionCallback\n) => void;\n\n/**\n * Split authentication header eg: Bearer [secret_token]\n * @param authorizationHeader auth token\n */\nexport function parseAuthTokenHeader(authorizationHeader: string): AuthTokenHeader {\n const parts = authorizationHeader.split(' ');\n const [scheme, token] = parts;\n\n return { scheme, token };\n}\n\nexport function parseAESCredentials(authorizationHeader: string, secret: string) {\n debug('parseAESCredentials');\n const { scheme, token } = parseAuthTokenHeader(authorizationHeader);\n\n // basic is deprecated and should not be enforced\n // basic is currently being used for functional test\n if (scheme.toUpperCase() === TOKEN_BASIC.toUpperCase()) {\n debug('legacy header basic');\n const credentials = convertPayloadToBase64(token).toString();\n\n return credentials;\n } else if (scheme.toUpperCase() === TOKEN_BEARER.toUpperCase()) {\n debug('legacy header bearer');\n const credentials = aesDecrypt(token, secret);\n\n return credentials;\n }\n}\n\nexport function getMiddlewareCredentials(\n security: Security,\n secretKey: string,\n authorizationHeader: string\n): AuthMiddlewarePayload {\n debug('getMiddlewareCredentials');\n // comment out for debugging purposes\n if (isAESLegacy(security)) {\n debug('is legacy');\n const credentials = parseAESCredentials(authorizationHeader, secretKey);\n if (!credentials) {\n debug('parse legacy credentials failed');\n return;\n }\n\n const parsedCredentials = parseBasicPayload(credentials);\n if (!parsedCredentials) {\n debug('parse legacy basic payload credentials failed');\n return;\n }\n\n return parsedCredentials;\n }\n const { scheme, token } = parseAuthTokenHeader(authorizationHeader);\n\n debug('is jwt');\n if (_.isString(token) && scheme.toUpperCase() === TOKEN_BEARER.toUpperCase()) {\n return verifyJWTPayload(token, secretKey);\n }\n}\n\nexport function isAESLegacy(security: Security): boolean {\n const { legacy, jwt } = security.api;\n\n return _.isNil(legacy) === false && _.isNil(jwt) && legacy === true;\n}\n\nexport async function getApiToken(\n auth: TokenEncryption,\n config: Config,\n remoteUser: RemoteUser,\n aesPassword: string\n): Promise<string | void> {\n debug('get api token');\n const { security } = config;\n\n if (isAESLegacy(security)) {\n debug('security legacy enabled');\n // fallback all goes to AES encryption\n return await new Promise((resolve): void => {\n resolve(auth.aesEncrypt(buildUser(remoteUser.name as string, aesPassword)));\n });\n }\n const { jwt } = security.api;\n\n if (jwt?.sign) {\n return await auth.jwtEncrypt(remoteUser, jwt.sign);\n }\n return await new Promise((resolve): void => {\n resolve(auth.aesEncrypt(buildUser(remoteUser.name as string, aesPassword)));\n });\n}\n\nexport const expireReasons: string[] = ['JsonWebTokenError', 'TokenExpiredError'];\n\nexport function verifyJWTPayload(token: string, secret: string): RemoteUser {\n try {\n const payload: RemoteUser = verifyPayload(token, secret);\n\n return payload;\n } catch (error: any) {\n // #168 this check should be removed as soon AES encrypt is removed.\n if (expireReasons.includes(error.name)) {\n // it might be possible the jwt configuration is enabled and\n // old tokens fails still remains in usage, thus\n // we return an anonymous user to force log in.\n return createAnonymousRemoteUser();\n }\n throw errorUtils.getCode(HTTP_STATUS.UNAUTHORIZED, error.message);\n }\n}\n\nexport function isAuthHeaderValid(authorization: string): boolean {\n return authorization.split(' ').length === 2;\n}\n\nexport function getDefaultPlugins(logger: any): IPluginAuth<Config> {\n return {\n authenticate(user: string, password: string, cb: Callback): void {\n cb(errorUtils.getForbidden(API_ERROR.BAD_USERNAME_PASSWORD));\n },\n\n adduser(user: string, password: string, cb: Callback): void {\n return cb(errorUtils.getConflict(API_ERROR.BAD_USERNAME_PASSWORD));\n },\n\n // FIXME: allow_action and allow_publish should be in the @verdaccio/types\n // @ts-ignore\n allow_access: allow_action('access', logger),\n // @ts-ignore\n allow_publish: allow_action('publish', logger),\n allow_unpublish: handleSpecialUnpublish(logger),\n };\n}\n\nexport type ActionsAllowed = 'publish' | 'unpublish' | 'access';\n\nexport function allow_action(action: ActionsAllowed, logger): AllowAction {\n return function allowActionCallback(\n user: RemoteUser,\n pkg: AuthPackageAllow,\n callback: AllowActionCallback\n ): void {\n logger.trace({ remote: user.name }, `[auth/allow_action]: user: @{user.name}`);\n const { name, groups } = user;\n const groupAccess = pkg[action] as string[];\n const hasPermission = groupAccess.some((group) => name === group || groups.includes(group));\n logger.trace(\n { pkgName: pkg.name, hasPermission, remote: user.name, groupAccess },\n `[auth/allow_action]: hasPermission? @{hasPermission} for user: @{user}`\n );\n\n if (hasPermission) {\n logger.trace({ remote: user.name }, `auth/allow_action: access granted to: @{user}`);\n return callback(null, true);\n }\n\n if (name) {\n callback(\n errorUtils.getForbidden(`user ${name} is not allowed to ${action} package ${pkg.name}`)\n );\n } else {\n callback(\n errorUtils.getUnauthorized(`authorization required to ${action} package ${pkg.name}`)\n );\n }\n };\n}\n\n/**\n *\n */\nexport function handleSpecialUnpublish(logger): any {\n return function (user: RemoteUser, pkg: AuthPackageAllow, callback: AllowActionCallback): void {\n const action = 'unpublish';\n // verify whether the unpublish prop has been defined\n const isUnpublishMissing: boolean = _.isNil(pkg[action]);\n const hasGroups: boolean = isUnpublishMissing ? false : (pkg[action] as string[]).length > 0;\n logger.trace(\n { user: user.name, name: pkg.name, hasGroups },\n `fallback unpublish for @{name} has groups: @{hasGroups} for @{user}`\n );\n\n if (isUnpublishMissing || hasGroups === false) {\n return callback(null, undefined);\n }\n\n logger.trace(\n { user: user.name, name: pkg.name, action, hasGroups },\n `allow_action for @{action} for @{name} has groups: @{hasGroups} for @{user}`\n );\n return allow_action(action, logger)(user, pkg, callback);\n };\n}\n\nexport function buildUser(name: string, password: string): string {\n return String(`${name}:${password}`);\n}\n\nexport function convertPayloadToBase64(payload: string): Buffer {\n return Buffer.from(payload, 'base64');\n}\n"],"file":"utils.js"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@verdaccio/auth",
|
|
3
|
-
"version": "6.0.0-6-next.
|
|
3
|
+
"version": "6.0.0-6-next.16",
|
|
4
4
|
"description": "logger",
|
|
5
5
|
"main": "./build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -25,25 +25,25 @@
|
|
|
25
25
|
"verdaccio"
|
|
26
26
|
],
|
|
27
27
|
"engines": {
|
|
28
|
-
"node": ">=
|
|
28
|
+
"node": ">=14",
|
|
29
29
|
"npm": ">=6"
|
|
30
30
|
},
|
|
31
31
|
"license": "MIT",
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@verdaccio/
|
|
34
|
-
"@verdaccio/config": "6.0.0-6-next.
|
|
35
|
-
"@verdaccio/loaders": "6.0.0-6-next.
|
|
36
|
-
"@verdaccio/logger": "6.0.0-6-next.
|
|
37
|
-
"@verdaccio/utils": "6.0.0-6-next.
|
|
38
|
-
"debug": "4.3.
|
|
33
|
+
"@verdaccio/core": "6.0.0-6-next.4",
|
|
34
|
+
"@verdaccio/config": "6.0.0-6-next.12",
|
|
35
|
+
"@verdaccio/loaders": "6.0.0-6-next.8",
|
|
36
|
+
"@verdaccio/logger": "6.0.0-6-next.8",
|
|
37
|
+
"@verdaccio/utils": "6.0.0-6-next.10",
|
|
38
|
+
"debug": "4.3.3",
|
|
39
39
|
"express": "4.17.1",
|
|
40
40
|
"jsonwebtoken": "8.5.1",
|
|
41
41
|
"lodash": "4.17.21",
|
|
42
|
-
"verdaccio-htpasswd": "11.0.0-6-next.
|
|
42
|
+
"verdaccio-htpasswd": "11.0.0-6-next.11"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@verdaccio/mock": "6.0.0-6-next.
|
|
46
|
-
"@verdaccio/types": "11.0.0-6-next.
|
|
45
|
+
"@verdaccio/mock": "6.0.0-6-next.13",
|
|
46
|
+
"@verdaccio/types": "11.0.0-6-next.10"
|
|
47
47
|
},
|
|
48
48
|
"funding": {
|
|
49
49
|
"type": "opencollective",
|
package/src/auth.ts
CHANGED
|
@@ -1,51 +1,46 @@
|
|
|
1
|
-
import _ from 'lodash';
|
|
2
|
-
import { NextFunction, Request, Response } from 'express';
|
|
3
1
|
import buildDebug from 'debug';
|
|
2
|
+
import { NextFunction, Request, Response } from 'express';
|
|
3
|
+
import _ from 'lodash';
|
|
4
|
+
import { HTPasswd, HTPasswdConfig } from 'verdaccio-htpasswd';
|
|
4
5
|
|
|
6
|
+
import { createAnonymousRemoteUser, createRemoteUser } from '@verdaccio/config';
|
|
5
7
|
import {
|
|
6
8
|
API_ERROR,
|
|
7
9
|
SUPPORT_ERRORS,
|
|
8
10
|
TOKEN_BASIC,
|
|
9
11
|
TOKEN_BEARER,
|
|
10
12
|
VerdaccioError,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
getForbidden,
|
|
14
|
-
} from '@verdaccio/commons-api';
|
|
13
|
+
errorUtils,
|
|
14
|
+
} from '@verdaccio/core';
|
|
15
15
|
import { loadPlugin } from '@verdaccio/loaders';
|
|
16
|
-
import { HTPasswd, HTPasswdConfig } from 'verdaccio-htpasswd';
|
|
17
|
-
|
|
18
16
|
import {
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
AllowAccess,
|
|
18
|
+
AuthPluginPackage,
|
|
21
19
|
Callback,
|
|
20
|
+
Config,
|
|
22
21
|
IPluginAuth,
|
|
23
|
-
RemoteUser,
|
|
24
22
|
JWTSignOptions,
|
|
25
|
-
|
|
26
|
-
AuthPluginPackage,
|
|
27
|
-
AllowAccess,
|
|
23
|
+
Logger,
|
|
28
24
|
PackageAccess,
|
|
29
25
|
PluginOptions,
|
|
26
|
+
RemoteUser,
|
|
27
|
+
Security,
|
|
30
28
|
} from '@verdaccio/types';
|
|
29
|
+
import { getMatchedPackagesSpec, isFunction, isNil } from '@verdaccio/utils';
|
|
31
30
|
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
34
|
-
|
|
31
|
+
import { signPayload } from './jwt-token';
|
|
32
|
+
import { aesEncrypt } from './legacy-token';
|
|
33
|
+
import { parseBasicPayload } from './token';
|
|
35
34
|
import {
|
|
36
|
-
|
|
35
|
+
convertPayloadToBase64,
|
|
37
36
|
getDefaultPlugins,
|
|
38
|
-
|
|
39
|
-
parseAuthTokenHeader,
|
|
40
|
-
isAuthHeaderValid,
|
|
37
|
+
getMiddlewareCredentials,
|
|
41
38
|
isAESLegacy,
|
|
42
|
-
|
|
39
|
+
isAuthHeaderValid,
|
|
40
|
+
parseAuthTokenHeader,
|
|
41
|
+
verifyJWTPayload,
|
|
43
42
|
} from './utils';
|
|
44
43
|
|
|
45
|
-
import { signPayload } from './jwt-token';
|
|
46
|
-
import { aesEncrypt } from './legacy-token';
|
|
47
|
-
import { parseBasicPayload } from './token';
|
|
48
|
-
|
|
49
44
|
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
50
45
|
const LoggerApi = require('@verdaccio/logger');
|
|
51
46
|
|
|
@@ -54,6 +49,7 @@ const debug = buildDebug('verdaccio:auth');
|
|
|
54
49
|
export interface IBasicAuth<T> {
|
|
55
50
|
config: T & Config;
|
|
56
51
|
authenticate(user: string, password: string, cb: Callback): void;
|
|
52
|
+
invalidateToken?(token: string): Promise<void>;
|
|
57
53
|
changePassword(user: string, password: string, newPassword: string, cb: Callback): void;
|
|
58
54
|
allow_access(pkg: AuthPluginPackage, user: RemoteUser, callback: Callback): void;
|
|
59
55
|
add_user(user: string, password: string, cb: Callback): any;
|
|
@@ -85,6 +81,7 @@ export interface IAuth extends IBasicAuth<Config>, IAuthMiddleware, TokenEncrypt
|
|
|
85
81
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
86
82
|
plugins: any[];
|
|
87
83
|
allow_unpublish(pkg: AuthPluginPackage, user: RemoteUser, callback: Callback): void;
|
|
84
|
+
invalidateToken(token: string): Promise<void>;
|
|
88
85
|
}
|
|
89
86
|
|
|
90
87
|
class Auth implements IAuth {
|
|
@@ -97,6 +94,9 @@ class Auth implements IAuth {
|
|
|
97
94
|
this.config = config;
|
|
98
95
|
this.logger = LoggerApi.logger.child({ sub: 'auth' });
|
|
99
96
|
this.secret = config.secret;
|
|
97
|
+
if (!this.secret) {
|
|
98
|
+
throw new TypeError('secret it is required value on initialize the auth class');
|
|
99
|
+
}
|
|
100
100
|
|
|
101
101
|
this.plugins =
|
|
102
102
|
_.isNil(config?.auth) === false ? this._loadPlugin(config) : this.loadDefaultPlugin(config);
|
|
@@ -153,7 +153,7 @@ class Auth implements IAuth {
|
|
|
153
153
|
const validPlugins = _.filter(this.plugins, (plugin) => isFunction(plugin.changePassword));
|
|
154
154
|
|
|
155
155
|
if (_.isEmpty(validPlugins)) {
|
|
156
|
-
return cb(getInternalError(SUPPORT_ERRORS.PLUGIN_MISSING_INTERFACE));
|
|
156
|
+
return cb(errorUtils.getInternalError(SUPPORT_ERRORS.PLUGIN_MISSING_INTERFACE));
|
|
157
157
|
}
|
|
158
158
|
|
|
159
159
|
for (const plugin of validPlugins) {
|
|
@@ -179,6 +179,12 @@ class Auth implements IAuth {
|
|
|
179
179
|
}
|
|
180
180
|
}
|
|
181
181
|
|
|
182
|
+
public async invalidateToken(token: string) {
|
|
183
|
+
// eslint-disable-next-line no-console
|
|
184
|
+
console.log('invalidate token pending to implement', token);
|
|
185
|
+
return Promise.resolve();
|
|
186
|
+
}
|
|
187
|
+
|
|
182
188
|
public authenticate(username: string, password: string, cb: Callback): void {
|
|
183
189
|
const plugins = this.plugins.slice(0);
|
|
184
190
|
(function next(): void {
|
|
@@ -415,7 +421,9 @@ class Auth implements IAuth {
|
|
|
415
421
|
}
|
|
416
422
|
|
|
417
423
|
// in case auth header does not exist we return anonymous function
|
|
418
|
-
|
|
424
|
+
const remoteUser = createAnonymousRemoteUser();
|
|
425
|
+
req.remote_user = remoteUser;
|
|
426
|
+
res.locals.remote_user = remoteUser;
|
|
419
427
|
|
|
420
428
|
const { authorization } = req.headers;
|
|
421
429
|
if (_.isNil(authorization)) {
|
|
@@ -425,7 +433,7 @@ class Auth implements IAuth {
|
|
|
425
433
|
|
|
426
434
|
if (!isAuthHeaderValid(authorization)) {
|
|
427
435
|
debug('api middleware authentication heather is invalid');
|
|
428
|
-
return next(getBadRequest(API_ERROR.BAD_AUTH_HEADER));
|
|
436
|
+
return next(errorUtils.getBadRequest(API_ERROR.BAD_AUTH_HEADER));
|
|
429
437
|
}
|
|
430
438
|
const { secret, security } = this.config;
|
|
431
439
|
|
|
@@ -476,7 +484,7 @@ class Auth implements IAuth {
|
|
|
476
484
|
} else {
|
|
477
485
|
// with JWT throw 401
|
|
478
486
|
debug('jwt invalid token');
|
|
479
|
-
next(getForbidden(API_ERROR.BAD_USERNAME_PASSWORD));
|
|
487
|
+
next(errorUtils.getForbidden(API_ERROR.BAD_USERNAME_PASSWORD));
|
|
480
488
|
}
|
|
481
489
|
}
|
|
482
490
|
}
|
|
@@ -510,7 +518,7 @@ class Auth implements IAuth {
|
|
|
510
518
|
} else {
|
|
511
519
|
// we force npm client to ask again with basic authentication
|
|
512
520
|
debug('legacy invalid header');
|
|
513
|
-
return next(getBadRequest(API_ERROR.BAD_AUTH_HEADER));
|
|
521
|
+
return next(errorUtils.getBadRequest(API_ERROR.BAD_AUTH_HEADER));
|
|
514
522
|
}
|
|
515
523
|
}
|
|
516
524
|
|
|
@@ -544,7 +552,7 @@ class Auth implements IAuth {
|
|
|
544
552
|
}
|
|
545
553
|
|
|
546
554
|
if (!isAuthHeaderValid(authorization)) {
|
|
547
|
-
return next(getBadRequest(API_ERROR.BAD_AUTH_HEADER));
|
|
555
|
+
return next(errorUtils.getBadRequest(API_ERROR.BAD_AUTH_HEADER));
|
|
548
556
|
}
|
|
549
557
|
|
|
550
558
|
const token = (authorization || '').replace(`${TOKEN_BEARER} `, '');
|
package/src/jwt-token.ts
CHANGED
package/src/legacy-token.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
|
+
HexBase64BinaryEncoding,
|
|
3
|
+
Utf8AsciiBinaryEncoding,
|
|
2
4
|
createCipheriv,
|
|
3
5
|
createDecipheriv,
|
|
4
|
-
HexBase64BinaryEncoding,
|
|
5
6
|
randomBytes,
|
|
6
|
-
Utf8AsciiBinaryEncoding,
|
|
7
7
|
} from 'crypto';
|
|
8
|
-
import { TOKEN_VALID_LENGTH } from '@verdaccio/config';
|
|
9
8
|
import buildDebug from 'debug';
|
|
10
9
|
|
|
10
|
+
import { TOKEN_VALID_LENGTH } from '@verdaccio/config';
|
|
11
|
+
|
|
11
12
|
const debug = buildDebug('verdaccio:auth:token:legacy');
|
|
12
13
|
|
|
13
14
|
export const defaultAlgorithm = process.env.VERDACCIO_LEGACY_ALGORITHM || 'aes-256-ctr';
|
package/src/utils.ts
CHANGED
|
@@ -1,29 +1,27 @@
|
|
|
1
|
-
import _ from 'lodash';
|
|
2
1
|
import buildDebug from 'debug';
|
|
2
|
+
import _ from 'lodash';
|
|
3
|
+
|
|
4
|
+
import { createAnonymousRemoteUser } from '@verdaccio/config';
|
|
5
|
+
import {
|
|
6
|
+
API_ERROR,
|
|
7
|
+
HTTP_STATUS,
|
|
8
|
+
TOKEN_BASIC,
|
|
9
|
+
TOKEN_BEARER,
|
|
10
|
+
VerdaccioError,
|
|
11
|
+
errorUtils,
|
|
12
|
+
} from '@verdaccio/core';
|
|
3
13
|
import {
|
|
14
|
+
AuthPackageAllow,
|
|
4
15
|
Callback,
|
|
5
16
|
Config,
|
|
6
17
|
IPluginAuth,
|
|
7
18
|
RemoteUser,
|
|
8
19
|
Security,
|
|
9
|
-
AuthPackageAllow,
|
|
10
20
|
} from '@verdaccio/types';
|
|
11
|
-
import {
|
|
12
|
-
HTTP_STATUS,
|
|
13
|
-
TOKEN_BASIC,
|
|
14
|
-
TOKEN_BEARER,
|
|
15
|
-
API_ERROR,
|
|
16
|
-
getForbidden,
|
|
17
|
-
getUnauthorized,
|
|
18
|
-
getConflict,
|
|
19
|
-
getCode,
|
|
20
|
-
} from '@verdaccio/commons-api';
|
|
21
|
-
import { VerdaccioError } from '@verdaccio/commons-api';
|
|
22
21
|
|
|
23
|
-
import {
|
|
24
|
-
import { TokenEncryption, AESPayload } from './auth';
|
|
25
|
-
import { aesDecrypt } from './legacy-token';
|
|
22
|
+
import { AESPayload, TokenEncryption } from './auth';
|
|
26
23
|
import { verifyPayload } from './jwt-token';
|
|
24
|
+
import { aesDecrypt } from './legacy-token';
|
|
27
25
|
import { parseBasicPayload } from './token';
|
|
28
26
|
|
|
29
27
|
const debug = buildDebug('verdaccio:auth:utils');
|
|
@@ -155,7 +153,7 @@ export function verifyJWTPayload(token: string, secret: string): RemoteUser {
|
|
|
155
153
|
// we return an anonymous user to force log in.
|
|
156
154
|
return createAnonymousRemoteUser();
|
|
157
155
|
}
|
|
158
|
-
throw getCode(HTTP_STATUS.UNAUTHORIZED, error.message);
|
|
156
|
+
throw errorUtils.getCode(HTTP_STATUS.UNAUTHORIZED, error.message);
|
|
159
157
|
}
|
|
160
158
|
}
|
|
161
159
|
|
|
@@ -166,11 +164,11 @@ export function isAuthHeaderValid(authorization: string): boolean {
|
|
|
166
164
|
export function getDefaultPlugins(logger: any): IPluginAuth<Config> {
|
|
167
165
|
return {
|
|
168
166
|
authenticate(user: string, password: string, cb: Callback): void {
|
|
169
|
-
cb(getForbidden(API_ERROR.BAD_USERNAME_PASSWORD));
|
|
167
|
+
cb(errorUtils.getForbidden(API_ERROR.BAD_USERNAME_PASSWORD));
|
|
170
168
|
},
|
|
171
169
|
|
|
172
170
|
adduser(user: string, password: string, cb: Callback): void {
|
|
173
|
-
return cb(getConflict(API_ERROR.BAD_USERNAME_PASSWORD));
|
|
171
|
+
return cb(errorUtils.getConflict(API_ERROR.BAD_USERNAME_PASSWORD));
|
|
174
172
|
},
|
|
175
173
|
|
|
176
174
|
// FIXME: allow_action and allow_publish should be in the @verdaccio/types
|
|
@@ -205,9 +203,13 @@ export function allow_action(action: ActionsAllowed, logger): AllowAction {
|
|
|
205
203
|
}
|
|
206
204
|
|
|
207
205
|
if (name) {
|
|
208
|
-
callback(
|
|
206
|
+
callback(
|
|
207
|
+
errorUtils.getForbidden(`user ${name} is not allowed to ${action} package ${pkg.name}`)
|
|
208
|
+
);
|
|
209
209
|
} else {
|
|
210
|
-
callback(
|
|
210
|
+
callback(
|
|
211
|
+
errorUtils.getUnauthorized(`authorization required to ${action} package ${pkg.name}`)
|
|
212
|
+
);
|
|
211
213
|
}
|
|
212
214
|
};
|
|
213
215
|
}
|
package/test/auth-utils.spec.ts
CHANGED
|
@@ -1,39 +1,42 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
1
|
import _ from 'lodash';
|
|
2
|
+
import path from 'path';
|
|
3
3
|
|
|
4
|
-
import { CHARACTER_ENCODING, TOKEN_BEARER, API_ERROR } from '@verdaccio/commons-api';
|
|
5
|
-
|
|
6
|
-
import { configExample } from '@verdaccio/mock';
|
|
7
4
|
import {
|
|
8
5
|
Config as AppConfig,
|
|
9
|
-
parseConfigFile,
|
|
10
6
|
ROLES,
|
|
11
|
-
createRemoteUser,
|
|
12
7
|
createAnonymousRemoteUser,
|
|
8
|
+
createRemoteUser,
|
|
9
|
+
parseConfigFile,
|
|
13
10
|
} from '@verdaccio/config';
|
|
14
|
-
|
|
15
11
|
import {
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
API_ERROR,
|
|
13
|
+
CHARACTER_ENCODING,
|
|
14
|
+
TOKEN_BEARER,
|
|
15
|
+
VerdaccioError,
|
|
16
|
+
errorUtils,
|
|
17
|
+
} from '@verdaccio/core';
|
|
18
|
+
import { setup } from '@verdaccio/logger';
|
|
19
|
+
import { configExample } from '@verdaccio/mock';
|
|
20
|
+
import { Config, RemoteUser, Security } from '@verdaccio/types';
|
|
21
|
+
import {
|
|
18
22
|
AllowActionCallbackResponse,
|
|
23
|
+
buildToken,
|
|
19
24
|
buildUserBuffer,
|
|
25
|
+
getAuthenticatedMessage,
|
|
20
26
|
} from '@verdaccio/utils';
|
|
21
27
|
|
|
22
|
-
import { Config, Security, RemoteUser } from '@verdaccio/types';
|
|
23
|
-
import { VerdaccioError, getForbidden } from '@verdaccio/commons-api';
|
|
24
|
-
import { setup } from '@verdaccio/logger';
|
|
25
28
|
import {
|
|
26
|
-
IAuth,
|
|
27
|
-
Auth,
|
|
28
29
|
ActionsAllowed,
|
|
30
|
+
Auth,
|
|
31
|
+
IAuth,
|
|
32
|
+
aesDecrypt,
|
|
29
33
|
allow_action,
|
|
34
|
+
getApiToken,
|
|
30
35
|
getDefaultPlugins,
|
|
31
36
|
getMiddlewareCredentials,
|
|
32
|
-
|
|
37
|
+
signPayload,
|
|
33
38
|
verifyJWTPayload,
|
|
34
|
-
aesDecrypt,
|
|
35
39
|
verifyPayload,
|
|
36
|
-
signPayload,
|
|
37
40
|
} from '../src';
|
|
38
41
|
|
|
39
42
|
setup([]);
|
|
@@ -110,7 +113,7 @@ describe('Auth utilities', () => {
|
|
|
110
113
|
test('authentication should fail by default (default)', () => {
|
|
111
114
|
const plugin = getDefaultPlugins({ trace: jest.fn() });
|
|
112
115
|
plugin.authenticate('foo', 'bar', (error: any) => {
|
|
113
|
-
expect(error).toEqual(getForbidden(API_ERROR.BAD_USERNAME_PASSWORD));
|
|
116
|
+
expect(error).toEqual(errorUtils.getForbidden(API_ERROR.BAD_USERNAME_PASSWORD));
|
|
114
117
|
});
|
|
115
118
|
});
|
|
116
119
|
|
|
@@ -118,7 +121,7 @@ describe('Auth utilities', () => {
|
|
|
118
121
|
const plugin = getDefaultPlugins({ trace: jest.fn() });
|
|
119
122
|
// @ts-ignore
|
|
120
123
|
plugin.adduser('foo', 'bar', (error: any) => {
|
|
121
|
-
expect(error).toEqual(getForbidden(API_ERROR.BAD_USERNAME_PASSWORD));
|
|
124
|
+
expect(error).toEqual(errorUtils.getForbidden(API_ERROR.BAD_USERNAME_PASSWORD));
|
|
122
125
|
});
|
|
123
126
|
});
|
|
124
127
|
});
|
package/test/auth.spec.ts
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
|
-
|
|
3
|
-
import { setup } from '@verdaccio/logger';
|
|
2
|
+
|
|
4
3
|
import { IAuth } from '@verdaccio/auth';
|
|
4
|
+
import { Config as AppConfig, ROLES } from '@verdaccio/config';
|
|
5
|
+
import { errorUtils } from '@verdaccio/core';
|
|
6
|
+
import { setup } from '@verdaccio/logger';
|
|
5
7
|
import { Config } from '@verdaccio/types';
|
|
6
|
-
import { getInternalError } from '@verdaccio/commons-api';
|
|
7
8
|
|
|
8
9
|
import { Auth } from '../src';
|
|
9
|
-
|
|
10
|
-
import { authProfileConf, authPluginFailureConf, authPluginPassThrougConf } from './helper/plugin';
|
|
10
|
+
import { authPluginFailureConf, authPluginPassThrougConf, authProfileConf } from './helper/plugin';
|
|
11
11
|
|
|
12
12
|
setup([]);
|
|
13
13
|
|
|
14
14
|
describe('AuthTest', () => {
|
|
15
15
|
test('should be defined', () => {
|
|
16
16
|
const config: Config = new AppConfig(_.cloneDeep(authProfileConf));
|
|
17
|
+
config.checkSecretKey('12345');
|
|
18
|
+
|
|
17
19
|
const auth: IAuth = new Auth(config);
|
|
18
20
|
|
|
19
21
|
expect(auth).toBeDefined();
|
|
@@ -23,6 +25,7 @@ describe('AuthTest', () => {
|
|
|
23
25
|
describe('test authenticate states', () => {
|
|
24
26
|
test('should be a success login', () => {
|
|
25
27
|
const config: Config = new AppConfig(_.cloneDeep(authProfileConf));
|
|
28
|
+
config.checkSecretKey('12345');
|
|
26
29
|
const auth: IAuth = new Auth(config);
|
|
27
30
|
|
|
28
31
|
expect(auth).toBeDefined();
|
|
@@ -49,6 +52,7 @@ describe('AuthTest', () => {
|
|
|
49
52
|
|
|
50
53
|
test('should be a fail on login', () => {
|
|
51
54
|
const config: Config = new AppConfig(_.cloneDeep(authPluginFailureConf));
|
|
55
|
+
config.checkSecretKey('12345');
|
|
52
56
|
const auth: IAuth = new Auth(config);
|
|
53
57
|
|
|
54
58
|
expect(auth).toBeDefined();
|
|
@@ -57,7 +61,7 @@ describe('AuthTest', () => {
|
|
|
57
61
|
|
|
58
62
|
auth.authenticate('foo', 'bar', callback);
|
|
59
63
|
expect(callback).toHaveBeenCalledTimes(1);
|
|
60
|
-
expect(callback).toHaveBeenCalledWith(getInternalError());
|
|
64
|
+
expect(callback).toHaveBeenCalledWith(errorUtils.getInternalError());
|
|
61
65
|
});
|
|
62
66
|
});
|
|
63
67
|
|
|
@@ -67,6 +71,7 @@ describe('AuthTest', () => {
|
|
|
67
71
|
describe('test authenticate out of control inputs from plugins', () => {
|
|
68
72
|
test('should skip falsy values', () => {
|
|
69
73
|
const config: Config = new AppConfig(_.cloneDeep(authPluginPassThrougConf));
|
|
74
|
+
config.checkSecretKey('12345');
|
|
70
75
|
const auth: IAuth = new Auth(config);
|
|
71
76
|
|
|
72
77
|
expect(auth).toBeDefined();
|
|
@@ -86,6 +91,7 @@ describe('AuthTest', () => {
|
|
|
86
91
|
|
|
87
92
|
test('should error truthy non-array', () => {
|
|
88
93
|
const config: Config = new AppConfig(_.cloneDeep(authPluginPassThrougConf));
|
|
94
|
+
config.checkSecretKey('12345');
|
|
89
95
|
const auth: IAuth = new Auth(config);
|
|
90
96
|
|
|
91
97
|
expect(auth).toBeDefined();
|
|
@@ -103,6 +109,7 @@ describe('AuthTest', () => {
|
|
|
103
109
|
|
|
104
110
|
test('should skip empty array', () => {
|
|
105
111
|
const config: Config = new AppConfig(_.cloneDeep(authPluginPassThrougConf));
|
|
112
|
+
config.checkSecretKey('12345');
|
|
106
113
|
const auth: IAuth = new Auth(config);
|
|
107
114
|
|
|
108
115
|
expect(auth).toBeDefined();
|
|
@@ -119,6 +126,7 @@ describe('AuthTest', () => {
|
|
|
119
126
|
|
|
120
127
|
test('should accept valid array', () => {
|
|
121
128
|
const config: Config = new AppConfig(_.cloneDeep(authPluginPassThrougConf));
|
|
129
|
+
config.checkSecretKey('12345');
|
|
122
130
|
const auth: IAuth = new Auth(config);
|
|
123
131
|
|
|
124
132
|
expect(auth).toBeDefined();
|
package/test/helper/plugin.ts
CHANGED