@verdaccio/auth 8.0.0-next-8.1 → 8.0.0-next-8.3
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 +31 -0
- package/build/auth.js +8 -9
- package/build/auth.js.map +1 -1
- package/build/utils.js +1 -1
- package/build/utils.js.map +1 -1
- package/package.json +11 -11
- package/test/auth-utils-middleware.spec.ts +260 -0
- package/test/auth-utils.spec.ts +16 -208
- package/test/auth.spec.ts +24 -23
- package/jest.config.js +0 -10
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# @verdaccio/auth
|
|
2
2
|
|
|
3
|
+
## 8.0.0-next-8.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [124e5f2]
|
|
8
|
+
- Updated dependencies [4afca90]
|
|
9
|
+
- verdaccio-htpasswd@13.0.0-next-8.3
|
|
10
|
+
- @verdaccio/loaders@8.0.0-next-8.3
|
|
11
|
+
- @verdaccio/core@8.0.0-next-8.3
|
|
12
|
+
- @verdaccio/config@8.0.0-next-8.3
|
|
13
|
+
- @verdaccio/utils@8.1.0-next-8.3
|
|
14
|
+
- @verdaccio/signature@8.0.0-next-8.1
|
|
15
|
+
- @verdaccio/logger@8.0.0-next-8.3
|
|
16
|
+
|
|
17
|
+
## 8.0.0-next-8.2
|
|
18
|
+
|
|
19
|
+
### Minor Changes
|
|
20
|
+
|
|
21
|
+
- 6a8154c: feat: update logger pino to latest
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- Updated dependencies [6a8154c]
|
|
26
|
+
- @verdaccio/config@8.0.0-next-8.2
|
|
27
|
+
- @verdaccio/core@8.0.0-next-8.2
|
|
28
|
+
- @verdaccio/loaders@8.0.0-next-8.2
|
|
29
|
+
- @verdaccio/logger@8.0.0-next-8.2
|
|
30
|
+
- verdaccio-htpasswd@13.0.0-next-8.2
|
|
31
|
+
- @verdaccio/signature@8.0.0-next-8.1
|
|
32
|
+
- @verdaccio/utils@7.1.0-next-8.2
|
|
33
|
+
|
|
3
34
|
## 8.0.0-next-8.1
|
|
4
35
|
|
|
5
36
|
### Major Changes
|
package/build/auth.js
CHANGED
|
@@ -53,7 +53,6 @@ class Auth {
|
|
|
53
53
|
return [authPlugin];
|
|
54
54
|
}
|
|
55
55
|
async loadPlugin() {
|
|
56
|
-
var _this$config;
|
|
57
56
|
return (0, _loaders.asyncLoadPlugin)(this.config.auth, {
|
|
58
57
|
config: this.config,
|
|
59
58
|
logger: _logger.logger
|
|
@@ -64,7 +63,7 @@ class Auth {
|
|
|
64
63
|
allow_publish
|
|
65
64
|
} = plugin;
|
|
66
65
|
return typeof authenticate !== 'undefined' || typeof allow_access !== 'undefined' || typeof allow_publish !== 'undefined';
|
|
67
|
-
},
|
|
66
|
+
}, this.config?.serverSettings?.pluginPrefix, _core.PLUGIN_CATEGORY.AUTHENTICATION);
|
|
68
67
|
}
|
|
69
68
|
_applyDefaultPlugins() {
|
|
70
69
|
// TODO: rename to applyFallbackPluginMethods
|
|
@@ -111,7 +110,7 @@ class Auth {
|
|
|
111
110
|
debug('authenticating %o', username);
|
|
112
111
|
plugin.authenticate(username, password, function (err, groups) {
|
|
113
112
|
if (err) {
|
|
114
|
-
debug('authenticating for user %o failed. Error: %o', username, err
|
|
113
|
+
debug('authenticating for user %o failed. Error: %o', username, err?.message);
|
|
115
114
|
return cb(err);
|
|
116
115
|
}
|
|
117
116
|
|
|
@@ -158,7 +157,7 @@ class Auth {
|
|
|
158
157
|
// @ts-ignore
|
|
159
158
|
plugin[method](user, password, function (err, ok) {
|
|
160
159
|
if (err) {
|
|
161
|
-
debug('the user %o could not be added. Error: %o', user, err
|
|
160
|
+
debug('the user %o could not be added. Error: %o', user, err?.message);
|
|
162
161
|
return cb(err);
|
|
163
162
|
}
|
|
164
163
|
if (ok) {
|
|
@@ -193,7 +192,7 @@ class Auth {
|
|
|
193
192
|
}
|
|
194
193
|
plugin.allow_access(user, pkg, function (err, ok) {
|
|
195
194
|
if (err) {
|
|
196
|
-
debug('forbidden access for %o. Error: %o', packageName, err
|
|
195
|
+
debug('forbidden access for %o. Error: %o', packageName, err?.message);
|
|
197
196
|
return callback(err);
|
|
198
197
|
}
|
|
199
198
|
if (ok) {
|
|
@@ -214,7 +213,7 @@ class Auth {
|
|
|
214
213
|
}, (0, _utils.getMatchedPackagesSpec)(packageName, this.config.packages));
|
|
215
214
|
debug('allow unpublish for %o', packageName);
|
|
216
215
|
for (const plugin of this.plugins) {
|
|
217
|
-
if (typeof
|
|
216
|
+
if (typeof plugin?.allow_unpublish !== 'function') {
|
|
218
217
|
debug('allow unpublish for %o plugin does not implement allow_unpublish', packageName);
|
|
219
218
|
continue;
|
|
220
219
|
} else {
|
|
@@ -254,7 +253,7 @@ class Auth {
|
|
|
254
253
|
debug('allow publish for %o init | plugins: %o', packageName, plugins.length);
|
|
255
254
|
(function next() {
|
|
256
255
|
const plugin = plugins.shift();
|
|
257
|
-
if (typeof
|
|
256
|
+
if (typeof plugin?.allow_publish !== 'function') {
|
|
258
257
|
debug('allow publish for %o plugin does not implement allow_publish', packageName);
|
|
259
258
|
return next();
|
|
260
259
|
}
|
|
@@ -378,7 +377,7 @@ class Auth {
|
|
|
378
377
|
debug('api middleware has a secret? %o', typeof secret === 'string');
|
|
379
378
|
debug('api middleware authorization %o', typeof authorization === 'string');
|
|
380
379
|
const credentials = (0, _utils2.getMiddlewareCredentials)(security, secret, authorization);
|
|
381
|
-
debug('api middleware credentials %o', credentials
|
|
380
|
+
debug('api middleware credentials %o', credentials?.name);
|
|
382
381
|
if (credentials) {
|
|
383
382
|
const {
|
|
384
383
|
user,
|
|
@@ -403,7 +402,7 @@ class Auth {
|
|
|
403
402
|
}
|
|
404
403
|
}
|
|
405
404
|
_isRemoteUserValid(remote_user) {
|
|
406
|
-
return _lodash.default.isUndefined(remote_user) === false && _lodash.default.isUndefined(remote_user
|
|
405
|
+
return _lodash.default.isUndefined(remote_user) === false && _lodash.default.isUndefined(remote_user?.name) === false;
|
|
407
406
|
}
|
|
408
407
|
|
|
409
408
|
/**
|
package/build/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","names":["_debug","_interopRequireDefault","require","_lodash","_verdaccioHtpasswd","_config","_core","_loaders","_logger","_signature","_utils","_utils2","e","__esModule","default","debug","buildDebug","Auth","constructor","config","secret","plugins","TypeError","init","loadPlugin","length","loadDefaultPlugin","_applyDefaultPlugins","pluginOptions","logger","authPlugin","HTPasswd","file","error","info","_this$config","asyncLoadPlugin","auth","plugin","authenticate","allow_access","allow_publish","serverSettings","pluginPrefix","PLUGIN_CATEGORY","AUTHENTICATION","push","getDefaultPlugins","changePassword","username","password","newPassword","cb","validPlugins","_","filter","isFunction","isEmpty","errorUtils","getInternalError","SUPPORT_ERRORS","PLUGIN_MISSING_INTERFACE","isNil","err","profile","invalidateToken","token","console","log","Promise","resolve","slice","next","shift","groups","message","isString","isGroupValid","isArray","API_ERROR","BAD_FORMAT_USER_GROUP","createRemoteUser","add_user","user","self","method","adduser","warningUtils","emit","Codes","VERWAR006","ok","packageName","packageVersion","callback","pkgAllowAccess","name","version","pkg","Object","assign","getMatchedPackagesSpec","packages","allow_unpublish","isError","apiJWTmiddleware","helpers","createAnonymousRemoteUser","req","res","_next","pause","resume","remote_user","remoteUser","locals","authorization","headers","isAuthHeaderValid","getBadRequest","BAD_AUTH_HEADER","security","isAESLegacy","handleAESMiddleware","handleJWTAPIMiddleware","scheme","parseAuthTokenHeader","toUpperCase","TOKEN_BASIC","credentials","convertPayloadToBase64","toString","parseBasicPayload","getMiddlewareCredentials","getForbidden","BAD_USERNAME_PASSWORD","_isRemoteUserValid","isUndefined","webUIJWTmiddleware","status","statusCode","send","replace","TOKEN_BEARER","verifyJWTPayload","jwtEncrypt","signOptions","real_groups","realGroupsValidated","groupedGroups","Array","from","Set","concat","payload","signPayload","aesEncrypt","value","signatureUtils","TOKEN_VALID_LENGTH","aesEncryptDeprecated","Buffer","exports"],"sources":["../src/auth.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport _ from 'lodash';\nimport { HTPasswd } from 'verdaccio-htpasswd';\n\nimport { createAnonymousRemoteUser, createRemoteUser } from '@verdaccio/config';\nimport {\n API_ERROR,\n PLUGIN_CATEGORY,\n SUPPORT_ERRORS,\n TOKEN_BASIC,\n TOKEN_BEARER,\n VerdaccioError,\n errorUtils,\n pluginUtils,\n warningUtils,\n} from '@verdaccio/core';\nimport { asyncLoadPlugin } from '@verdaccio/loaders';\nimport { logger } from '@verdaccio/logger';\nimport {\n aesEncrypt,\n aesEncryptDeprecated,\n parseBasicPayload,\n signPayload,\n utils as signatureUtils,\n} from '@verdaccio/signature';\nimport {\n AllowAccess,\n Callback,\n Config,\n JWTSignOptions,\n PackageAccess,\n RemoteUser,\n Security,\n} from '@verdaccio/types';\nimport { getMatchedPackagesSpec, isFunction, isNil } from '@verdaccio/utils';\n\nimport {\n $RequestExtend,\n $ResponseExtend,\n AESPayload,\n IAuthMiddleware,\n NextFunction,\n TokenEncryption,\n} from './types';\nimport {\n convertPayloadToBase64,\n getDefaultPlugins,\n getMiddlewareCredentials,\n isAESLegacy,\n isAuthHeaderValid,\n parseAuthTokenHeader,\n verifyJWTPayload,\n} from './utils';\n\nconst debug = buildDebug('verdaccio:auth');\n\nclass Auth implements IAuthMiddleware, TokenEncryption, pluginUtils.IBasicAuth {\n public config: Config;\n public secret: string;\n public plugins: pluginUtils.Auth<Config>[];\n\n public constructor(config: Config) {\n this.config = config;\n this.secret = config.secret;\n this.plugins = [];\n if (!this.secret) {\n throw new TypeError('secret it is required value on initialize the auth class');\n }\n }\n\n public async init() {\n let plugins = (await this.loadPlugin()) as pluginUtils.Auth<unknown>[];\n\n debug('auth plugins found %s', plugins.length);\n if (!plugins || plugins.length === 0) {\n plugins = this.loadDefaultPlugin();\n }\n this.plugins = plugins;\n\n this._applyDefaultPlugins();\n }\n\n private loadDefaultPlugin() {\n debug('load default auth plugin');\n const pluginOptions: pluginUtils.PluginOptions = {\n config: this.config,\n logger,\n };\n let authPlugin;\n try {\n authPlugin = new HTPasswd(\n { file: './htpasswd' },\n pluginOptions as any as pluginUtils.PluginOptions\n );\n } catch (error: any) {\n debug('error on loading auth htpasswd plugin stack: %o', error);\n logger.info({}, 'no auth plugin has been found');\n return [];\n }\n\n return [authPlugin];\n }\n\n private async loadPlugin() {\n return asyncLoadPlugin<pluginUtils.Auth<unknown>>(\n this.config.auth,\n {\n config: this.config,\n logger,\n },\n (plugin): boolean => {\n const { authenticate, allow_access, allow_publish } = plugin;\n\n return (\n typeof authenticate !== 'undefined' ||\n typeof allow_access !== 'undefined' ||\n typeof allow_publish !== 'undefined'\n );\n },\n this.config?.serverSettings?.pluginPrefix,\n PLUGIN_CATEGORY.AUTHENTICATION\n );\n }\n\n private _applyDefaultPlugins(): void {\n // TODO: rename to applyFallbackPluginMethods\n this.plugins.push(getDefaultPlugins(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 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(\n username: string,\n password: string,\n cb: (error: VerdaccioError | null, user?: RemoteUser) => void\n ): void {\n const plugins = this.plugins.slice(0);\n (function next(): void {\n const plugin = plugins.shift() as pluginUtils.Auth<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: VerdaccioError | null, 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(\n user: string,\n password: string,\n cb: (error: VerdaccioError | null, user?: RemoteUser) => void\n ): void {\n const self = this;\n const plugins = this.plugins.slice(0);\n debug('add user %o', user);\n\n (function next(): void {\n let method = 'adduser';\n const plugin = plugins.shift() as pluginUtils.Auth<Config>;\n // @ts-expect-error future major (7.x) should remove this section\n if (typeof plugin.adduser === 'undefined' && typeof plugin.add_user === 'function') {\n method = 'add_user';\n warningUtils.emit(warningUtils.Codes.VERWAR006);\n }\n // @ts-ignore\n if (typeof plugin[method] !== 'function') {\n next();\n } else {\n // TODO: replace by adduser whenever add_user deprecation method has been removed\n // @ts-ignore\n plugin[method](\n user,\n password,\n function (err: VerdaccioError | null, ok?: boolean | string): void {\n if (err) {\n debug('the user %o could not be 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 debug('user could not be added, skip to next auth plugin');\n next();\n }\n );\n }\n })();\n }\n\n /**\n * Allow user to access a package.\n */\n public allow_access(\n { packageName, packageVersion }: pluginUtils.AuthPluginPackage,\n user: RemoteUser,\n callback: pluginUtils.AccessCallback\n ): void {\n const plugins = this.plugins.slice(0);\n const pkgAllowAccess: AllowAccess = { name: packageName, version: packageVersion };\n const pkg = Object.assign(\n {},\n pkgAllowAccess,\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: pluginUtils.Auth<unknown> = plugins.shift() as pluginUtils.Auth<unknown>;\n\n if (_.isNil(plugin) || isFunction(plugin.allow_access) === false) {\n return next();\n }\n\n plugin.allow_access!(user, pkg, function (err: VerdaccioError | null, 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 }: pluginUtils.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 (typeof plugin?.allow_unpublish !== 'function') {\n debug('allow unpublish for %o plugin does not implement allow_unpublish', packageName);\n continue;\n } else {\n plugin.allow_unpublish(user, pkg, (err, ok): 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 return this.allow_publish({ packageName, packageVersion }, user, callback);\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 }: pluginUtils.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 (typeof plugin?.allow_publish !== 'function') {\n debug('allow publish for %o plugin does not implement allow_publish', packageName);\n return next();\n }\n\n plugin.allow_publish(user, pkg, (err: VerdaccioError | null, 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 public apiJWTmiddleware(): any {\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) => {\n req.pause();\n const next = function (err?: VerdaccioError): NextFunction {\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\n return _next() as unknown as NextFunction;\n };\n\n // FUTURE: disabled, not removed yet but seems unreacable code\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: any\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: VerdaccioError | null, 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 has a secret? %o', typeof secret === 'string');\n debug('api middleware authorization %o', typeof authorization === 'string');\n const credentials: any = getMiddlewareCredentials(security, secret, authorization);\n debug('api middleware credentials %o', credentials?.name);\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() {\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: RemoteUser | undefined;\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 as RemoteUser;\n req.remote_user = createRemoteUser(name as string, 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)\n ? real_groups\n : Array.from(new Set([...groups.concat(realGroupsValidated)]));\n const payload: RemoteUser = {\n real_groups: realGroupsValidated,\n name,\n groups: groupedGroups,\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 if (this.secret.length === signatureUtils.TOKEN_VALID_LENGTH) {\n debug('signing with enhanced aes legacy');\n const token = aesEncrypt(value, this.secret);\n return token;\n } else {\n debug('signing with enhanced aes deprecated legacy');\n // deprecated aes (legacy) signature, only must be used for legacy version\n const token = aesEncryptDeprecated(Buffer.from(value), this.secret).toString('base64');\n return token;\n }\n }\n}\n\nexport { Auth };\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"auth.js","names":["_debug","_interopRequireDefault","require","_lodash","_verdaccioHtpasswd","_config","_core","_loaders","_logger","_signature","_utils","_utils2","e","__esModule","default","debug","buildDebug","Auth","constructor","config","secret","plugins","TypeError","init","loadPlugin","length","loadDefaultPlugin","_applyDefaultPlugins","pluginOptions","logger","authPlugin","HTPasswd","file","error","info","asyncLoadPlugin","auth","plugin","authenticate","allow_access","allow_publish","serverSettings","pluginPrefix","PLUGIN_CATEGORY","AUTHENTICATION","push","getDefaultPlugins","changePassword","username","password","newPassword","cb","validPlugins","_","filter","isFunction","isEmpty","errorUtils","getInternalError","SUPPORT_ERRORS","PLUGIN_MISSING_INTERFACE","isNil","err","profile","invalidateToken","token","console","log","Promise","resolve","slice","next","shift","groups","message","isString","isGroupValid","isArray","API_ERROR","BAD_FORMAT_USER_GROUP","createRemoteUser","add_user","user","self","method","adduser","warningUtils","emit","Codes","VERWAR006","ok","packageName","packageVersion","callback","pkgAllowAccess","name","version","pkg","Object","assign","getMatchedPackagesSpec","packages","allow_unpublish","isError","apiJWTmiddleware","helpers","createAnonymousRemoteUser","req","res","_next","pause","resume","remote_user","remoteUser","locals","authorization","headers","isAuthHeaderValid","getBadRequest","BAD_AUTH_HEADER","security","isAESLegacy","handleAESMiddleware","handleJWTAPIMiddleware","scheme","parseAuthTokenHeader","toUpperCase","TOKEN_BASIC","credentials","convertPayloadToBase64","toString","parseBasicPayload","getMiddlewareCredentials","getForbidden","BAD_USERNAME_PASSWORD","_isRemoteUserValid","isUndefined","webUIJWTmiddleware","status","statusCode","send","replace","TOKEN_BEARER","verifyJWTPayload","jwtEncrypt","signOptions","real_groups","realGroupsValidated","groupedGroups","Array","from","Set","concat","payload","signPayload","aesEncrypt","value","signatureUtils","TOKEN_VALID_LENGTH","aesEncryptDeprecated","Buffer","exports"],"sources":["../src/auth.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport _ from 'lodash';\nimport { HTPasswd } from 'verdaccio-htpasswd';\n\nimport { createAnonymousRemoteUser, createRemoteUser } from '@verdaccio/config';\nimport {\n API_ERROR,\n PLUGIN_CATEGORY,\n SUPPORT_ERRORS,\n TOKEN_BASIC,\n TOKEN_BEARER,\n VerdaccioError,\n errorUtils,\n pluginUtils,\n warningUtils,\n} from '@verdaccio/core';\nimport { asyncLoadPlugin } from '@verdaccio/loaders';\nimport { logger } from '@verdaccio/logger';\nimport {\n aesEncrypt,\n aesEncryptDeprecated,\n parseBasicPayload,\n signPayload,\n utils as signatureUtils,\n} from '@verdaccio/signature';\nimport {\n AllowAccess,\n Callback,\n Config,\n JWTSignOptions,\n PackageAccess,\n RemoteUser,\n Security,\n} from '@verdaccio/types';\nimport { getMatchedPackagesSpec, isFunction, isNil } from '@verdaccio/utils';\n\nimport {\n $RequestExtend,\n $ResponseExtend,\n AESPayload,\n IAuthMiddleware,\n NextFunction,\n TokenEncryption,\n} from './types';\nimport {\n convertPayloadToBase64,\n getDefaultPlugins,\n getMiddlewareCredentials,\n isAESLegacy,\n isAuthHeaderValid,\n parseAuthTokenHeader,\n verifyJWTPayload,\n} from './utils';\n\nconst debug = buildDebug('verdaccio:auth');\n\nclass Auth implements IAuthMiddleware, TokenEncryption, pluginUtils.IBasicAuth {\n public config: Config;\n public secret: string;\n public plugins: pluginUtils.Auth<Config>[];\n\n public constructor(config: Config) {\n this.config = config;\n this.secret = config.secret;\n this.plugins = [];\n if (!this.secret) {\n throw new TypeError('secret it is required value on initialize the auth class');\n }\n }\n\n public async init() {\n let plugins = (await this.loadPlugin()) as pluginUtils.Auth<unknown>[];\n\n debug('auth plugins found %s', plugins.length);\n if (!plugins || plugins.length === 0) {\n plugins = this.loadDefaultPlugin();\n }\n this.plugins = plugins;\n\n this._applyDefaultPlugins();\n }\n\n private loadDefaultPlugin() {\n debug('load default auth plugin');\n const pluginOptions: pluginUtils.PluginOptions = {\n config: this.config,\n logger,\n };\n let authPlugin;\n try {\n authPlugin = new HTPasswd(\n { file: './htpasswd' },\n pluginOptions as any as pluginUtils.PluginOptions\n );\n } catch (error: any) {\n debug('error on loading auth htpasswd plugin stack: %o', error);\n logger.info({}, 'no auth plugin has been found');\n return [];\n }\n\n return [authPlugin];\n }\n\n private async loadPlugin() {\n return asyncLoadPlugin<pluginUtils.Auth<unknown>>(\n this.config.auth,\n {\n config: this.config,\n logger,\n },\n (plugin): boolean => {\n const { authenticate, allow_access, allow_publish } = plugin;\n\n return (\n typeof authenticate !== 'undefined' ||\n typeof allow_access !== 'undefined' ||\n typeof allow_publish !== 'undefined'\n );\n },\n this.config?.serverSettings?.pluginPrefix,\n PLUGIN_CATEGORY.AUTHENTICATION\n );\n }\n\n private _applyDefaultPlugins(): void {\n // TODO: rename to applyFallbackPluginMethods\n this.plugins.push(getDefaultPlugins(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 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(\n username: string,\n password: string,\n cb: (error: VerdaccioError | null, user?: RemoteUser) => void\n ): void {\n const plugins = this.plugins.slice(0);\n (function next(): void {\n const plugin = plugins.shift() as pluginUtils.Auth<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: VerdaccioError | null, 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(\n user: string,\n password: string,\n cb: (error: VerdaccioError | null, user?: RemoteUser) => void\n ): void {\n const self = this;\n const plugins = this.plugins.slice(0);\n debug('add user %o', user);\n\n (function next(): void {\n let method = 'adduser';\n const plugin = plugins.shift() as pluginUtils.Auth<Config>;\n // @ts-expect-error future major (7.x) should remove this section\n if (typeof plugin.adduser === 'undefined' && typeof plugin.add_user === 'function') {\n method = 'add_user';\n warningUtils.emit(warningUtils.Codes.VERWAR006);\n }\n // @ts-ignore\n if (typeof plugin[method] !== 'function') {\n next();\n } else {\n // TODO: replace by adduser whenever add_user deprecation method has been removed\n // @ts-ignore\n plugin[method](\n user,\n password,\n function (err: VerdaccioError | null, ok?: boolean | string): void {\n if (err) {\n debug('the user %o could not be 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 debug('user could not be added, skip to next auth plugin');\n next();\n }\n );\n }\n })();\n }\n\n /**\n * Allow user to access a package.\n */\n public allow_access(\n { packageName, packageVersion }: pluginUtils.AuthPluginPackage,\n user: RemoteUser,\n callback: pluginUtils.AccessCallback\n ): void {\n const plugins = this.plugins.slice(0);\n const pkgAllowAccess: AllowAccess = { name: packageName, version: packageVersion };\n const pkg = Object.assign(\n {},\n pkgAllowAccess,\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: pluginUtils.Auth<unknown> = plugins.shift() as pluginUtils.Auth<unknown>;\n\n if (_.isNil(plugin) || isFunction(plugin.allow_access) === false) {\n return next();\n }\n\n plugin.allow_access!(user, pkg, function (err: VerdaccioError | null, 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 }: pluginUtils.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 (typeof plugin?.allow_unpublish !== 'function') {\n debug('allow unpublish for %o plugin does not implement allow_unpublish', packageName);\n continue;\n } else {\n plugin.allow_unpublish(user, pkg, (err, ok): 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 return this.allow_publish({ packageName, packageVersion }, user, callback);\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 }: pluginUtils.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 (typeof plugin?.allow_publish !== 'function') {\n debug('allow publish for %o plugin does not implement allow_publish', packageName);\n return next();\n }\n\n plugin.allow_publish(user, pkg, (err: VerdaccioError | null, 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 public apiJWTmiddleware(): any {\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) => {\n req.pause();\n const next = function (err?: VerdaccioError): NextFunction {\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\n return _next() as unknown as NextFunction;\n };\n\n // FUTURE: disabled, not removed yet but seems unreacable code\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: any\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: VerdaccioError | null, 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 has a secret? %o', typeof secret === 'string');\n debug('api middleware authorization %o', typeof authorization === 'string');\n const credentials: any = getMiddlewareCredentials(security, secret, authorization);\n debug('api middleware credentials %o', credentials?.name);\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() {\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: RemoteUser | undefined;\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 as RemoteUser;\n req.remote_user = createRemoteUser(name as string, 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)\n ? real_groups\n : Array.from(new Set([...groups.concat(realGroupsValidated)]));\n const payload: RemoteUser = {\n real_groups: realGroupsValidated,\n name,\n groups: groupedGroups,\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 if (this.secret.length === signatureUtils.TOKEN_VALID_LENGTH) {\n debug('signing with enhanced aes legacy');\n const token = aesEncrypt(value, this.secret);\n return token;\n } else {\n debug('signing with enhanced aes deprecated legacy');\n // deprecated aes (legacy) signature, only must be used for legacy version\n const token = aesEncryptDeprecated(Buffer.from(value), this.secret).toString('base64');\n return token;\n }\n }\n}\n\nexport { Auth };\n"],"mappings":"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","ignoreList":[]}
|
package/build/utils.js
CHANGED
|
@@ -111,7 +111,7 @@ async function getApiToken(auth, config, remoteUser, aesPassword) {
|
|
|
111
111
|
const {
|
|
112
112
|
jwt
|
|
113
113
|
} = security.api;
|
|
114
|
-
if (jwt
|
|
114
|
+
if (jwt?.sign) {
|
|
115
115
|
return await auth.jwtEncrypt(remoteUser, jwt.sign);
|
|
116
116
|
}
|
|
117
117
|
return await new Promise(resolve => {
|
package/build/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","names":["_debug","_interopRequireDefault","require","_lodash","_config","_core","_signature","e","__esModule","default","debug","buildDebug","parseAuthTokenHeader","authorizationHeader","parts","split","scheme","token","parseAESCredentials","secret","toUpperCase","TOKEN_BASIC","credentials","convertPayloadToBase64","toString","TOKEN_BEARER","length","isLegacyUnsecure","aesDecryptDeprecated","aesDecrypt","getMiddlewareCredentials","security","secretKey","isAESLegacy","parsedCredentials","parseBasicPayload","_","isString","verifyJWTPayload","legacy","jwt","api","isNil","getApiToken","auth","config","remoteUser","aesPassword","Promise","resolve","aesEncrypt","buildUser","name","sign","jwtEncrypt","expireReasons","exports","payload","verifyPayload","error","includes","createAnonymousRemoteUser","errorUtils","getCode","HTTP_STATUS","UNAUTHORIZED","message","isAuthHeaderValid","authorization","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","user","pkg","callback","trace","remote","groups","groupAccess","hasPermission","some","group","pkgName","getUnauthorized","isUnpublishMissing","hasGroups","undefined","password","String","Buffer","from"],"sources":["../src/utils.ts"],"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 errorUtils,\n pluginUtils,\n} from '@verdaccio/core';\nimport {\n aesDecrypt,\n aesDecryptDeprecated,\n parseBasicPayload,\n verifyPayload,\n} from '@verdaccio/signature';\nimport { AuthPackageAllow, Config, Logger, RemoteUser, Security } from '@verdaccio/types';\n\nimport {\n ActionsAllowed,\n AllowAction,\n AllowActionCallback,\n AuthMiddlewarePayload,\n AuthTokenHeader,\n TokenEncryption,\n} from './types';\n\nconst debug = buildDebug('verdaccio:auth:utils');\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 init');\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 debug('secret length %o', secret.length);\n const isLegacyUnsecure = secret.length > 32;\n debug('is legacy unsecure %o', isLegacyUnsecure);\n if (isLegacyUnsecure) {\n debug('legacy unsecure enabled');\n return aesDecryptDeprecated(convertPayloadToBase64(token), secret).toString('utf-8');\n } else {\n debug('legacy secure enabled');\n return aesDecrypt(token.toString(), secret);\n }\n }\n}\n\nexport function getMiddlewareCredentials(\n security: Security,\n secretKey: string,\n authorizationHeader: string\n): AuthMiddlewarePayload {\n debug('getMiddlewareCredentials init');\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\n/**\n * Return a default configuration for authentication if none is provided.\n * @param logger {Logger}\n * @returns object of default implementations.\n */\nexport function getDefaultPlugins(logger: Logger): pluginUtils.Auth<Config> {\n return {\n authenticate(_user: string, _password: string, cb: pluginUtils.AuthCallback): void {\n debug('triggered default authenticate method');\n cb(errorUtils.getForbidden(API_ERROR.BAD_USERNAME_PASSWORD));\n },\n\n adduser(_user: string, _password: string, cb: pluginUtils.AuthUserCallback): void {\n debug('triggered default adduser method');\n return cb(errorUtils.getConflict(API_ERROR.BAD_USERNAME_PASSWORD));\n },\n\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 function allow_action(action: ActionsAllowed, logger: 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: @{remote}`);\n const { name, groups } = user;\n debug('allow_action \"%s\": groups %s', action, groups);\n const groupAccess = pkg[action] as string[];\n debug('allow_action \"%s\": groupAccess %s', action, groupAccess);\n const hasPermission = groupAccess.some((group) => {\n return name === group || groups.includes(group);\n });\n debug('package \"%s\" has permission \"%s\"', name, hasPermission);\n logger.trace(\n { pkgName: pkg.name, hasPermission, remote: user.name, groupAccess },\n `[auth/allow_action]: hasPermission? @{hasPermission} for user: @{remote}, package: @{pkgName}`\n );\n\n if (hasPermission) {\n logger.trace({ remote: user.name }, `auth/allow_action: access granted to: @{remote}`);\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: 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 = !pkg[action];\n debug('is unpublish method missing ? %s', isUnpublishMissing);\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"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"utils.js","names":["_debug","_interopRequireDefault","require","_lodash","_config","_core","_signature","e","__esModule","default","debug","buildDebug","parseAuthTokenHeader","authorizationHeader","parts","split","scheme","token","parseAESCredentials","secret","toUpperCase","TOKEN_BASIC","credentials","convertPayloadToBase64","toString","TOKEN_BEARER","length","isLegacyUnsecure","aesDecryptDeprecated","aesDecrypt","getMiddlewareCredentials","security","secretKey","isAESLegacy","parsedCredentials","parseBasicPayload","_","isString","verifyJWTPayload","legacy","jwt","api","isNil","getApiToken","auth","config","remoteUser","aesPassword","Promise","resolve","aesEncrypt","buildUser","name","sign","jwtEncrypt","expireReasons","exports","payload","verifyPayload","error","includes","createAnonymousRemoteUser","errorUtils","getCode","HTTP_STATUS","UNAUTHORIZED","message","isAuthHeaderValid","authorization","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","user","pkg","callback","trace","remote","groups","groupAccess","hasPermission","some","group","pkgName","getUnauthorized","isUnpublishMissing","hasGroups","undefined","password","String","Buffer","from"],"sources":["../src/utils.ts"],"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 errorUtils,\n pluginUtils,\n} from '@verdaccio/core';\nimport {\n aesDecrypt,\n aesDecryptDeprecated,\n parseBasicPayload,\n verifyPayload,\n} from '@verdaccio/signature';\nimport { AuthPackageAllow, Config, Logger, RemoteUser, Security } from '@verdaccio/types';\n\nimport {\n ActionsAllowed,\n AllowAction,\n AllowActionCallback,\n AuthMiddlewarePayload,\n AuthTokenHeader,\n TokenEncryption,\n} from './types';\n\nconst debug = buildDebug('verdaccio:auth:utils');\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 init');\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 debug('secret length %o', secret.length);\n const isLegacyUnsecure = secret.length > 32;\n debug('is legacy unsecure %o', isLegacyUnsecure);\n if (isLegacyUnsecure) {\n debug('legacy unsecure enabled');\n return aesDecryptDeprecated(convertPayloadToBase64(token), secret).toString('utf-8');\n } else {\n debug('legacy secure enabled');\n return aesDecrypt(token.toString(), secret);\n }\n }\n}\n\nexport function getMiddlewareCredentials(\n security: Security,\n secretKey: string,\n authorizationHeader: string\n): AuthMiddlewarePayload {\n debug('getMiddlewareCredentials init');\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\n/**\n * Return a default configuration for authentication if none is provided.\n * @param logger {Logger}\n * @returns object of default implementations.\n */\nexport function getDefaultPlugins(logger: Logger): pluginUtils.Auth<Config> {\n return {\n authenticate(_user: string, _password: string, cb: pluginUtils.AuthCallback): void {\n debug('triggered default authenticate method');\n cb(errorUtils.getForbidden(API_ERROR.BAD_USERNAME_PASSWORD));\n },\n\n adduser(_user: string, _password: string, cb: pluginUtils.AuthUserCallback): void {\n debug('triggered default adduser method');\n return cb(errorUtils.getConflict(API_ERROR.BAD_USERNAME_PASSWORD));\n },\n\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 function allow_action(action: ActionsAllowed, logger: 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: @{remote}`);\n const { name, groups } = user;\n debug('allow_action \"%s\": groups %s', action, groups);\n const groupAccess = pkg[action] as string[];\n debug('allow_action \"%s\": groupAccess %s', action, groupAccess);\n const hasPermission = groupAccess.some((group) => {\n return name === group || groups.includes(group);\n });\n debug('package \"%s\" has permission \"%s\"', name, hasPermission);\n logger.trace(\n { pkgName: pkg.name, hasPermission, remote: user.name, groupAccess },\n `[auth/allow_action]: hasPermission? @{hasPermission} for user: @{remote}, package: @{pkgName}`\n );\n\n if (hasPermission) {\n logger.trace({ remote: user.name }, `auth/allow_action: access granted to: @{remote}`);\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: 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 = !pkg[action];\n debug('is unpublish method missing ? %s', isUnpublishMissing);\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"],"mappings":"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","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@verdaccio/auth",
|
|
3
|
-
"version": "8.0.0-next-8.
|
|
3
|
+
"version": "8.0.0-next-8.3",
|
|
4
4
|
"description": "logger",
|
|
5
5
|
"main": "./build/index.js",
|
|
6
6
|
"types": "./build/index.d.ts",
|
|
@@ -29,19 +29,19 @@
|
|
|
29
29
|
},
|
|
30
30
|
"license": "MIT",
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@verdaccio/config": "8.0.0-next-8.
|
|
33
|
-
"@verdaccio/core": "8.0.0-next-8.
|
|
34
|
-
"@verdaccio/loaders": "8.0.0-next-8.
|
|
35
|
-
"@verdaccio/logger": "8.0.0-next-8.
|
|
36
|
-
"@verdaccio/signature": "8.0.0-next-8.
|
|
37
|
-
"@verdaccio/utils": "
|
|
32
|
+
"@verdaccio/config": "8.0.0-next-8.3",
|
|
33
|
+
"@verdaccio/core": "8.0.0-next-8.3",
|
|
34
|
+
"@verdaccio/loaders": "8.0.0-next-8.3",
|
|
35
|
+
"@verdaccio/logger": "8.0.0-next-8.3",
|
|
36
|
+
"@verdaccio/signature": "8.0.0-next-8.1",
|
|
37
|
+
"@verdaccio/utils": "8.1.0-next-8.3",
|
|
38
38
|
"debug": "4.3.7",
|
|
39
39
|
"lodash": "4.17.21",
|
|
40
|
-
"verdaccio-htpasswd": "13.0.0-next-8.
|
|
40
|
+
"verdaccio-htpasswd": "13.0.0-next-8.3"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@verdaccio/middleware": "8.0.0-next-8.
|
|
44
|
-
"@verdaccio/types": "13.0.0-next-8.
|
|
43
|
+
"@verdaccio/middleware": "8.0.0-next-8.3",
|
|
44
|
+
"@verdaccio/types": "13.0.0-next-8.1",
|
|
45
45
|
"express": "4.21.0",
|
|
46
46
|
"supertest": "7.0.0"
|
|
47
47
|
},
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
},
|
|
52
52
|
"scripts": {
|
|
53
53
|
"clean": "rimraf ./build",
|
|
54
|
-
"test": "
|
|
54
|
+
"test": "vitest run",
|
|
55
55
|
"type-check": "tsc --noEmit -p tsconfig.build.json",
|
|
56
56
|
"build:types": "tsc --emitDeclarationOnly -p tsconfig.build.json",
|
|
57
57
|
"build:js": "babel src/ --out-dir build/ --copy-files --extensions \".ts,.tsx\" --source-maps",
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import _ from 'lodash';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { describe, expect, test, vi } from 'vitest';
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
Config as AppConfig,
|
|
7
|
+
createAnonymousRemoteUser,
|
|
8
|
+
createRemoteUser,
|
|
9
|
+
parseConfigFile,
|
|
10
|
+
} from '@verdaccio/config';
|
|
11
|
+
import { getDefaultConfig } from '@verdaccio/config';
|
|
12
|
+
import { TOKEN_BEARER } from '@verdaccio/core';
|
|
13
|
+
import { setup } from '@verdaccio/logger';
|
|
14
|
+
import { signPayload } from '@verdaccio/signature';
|
|
15
|
+
import { Config, RemoteUser, Security } from '@verdaccio/types';
|
|
16
|
+
import { buildToken, buildUserBuffer } from '@verdaccio/utils';
|
|
17
|
+
|
|
18
|
+
import { Auth, getApiToken, getMiddlewareCredentials, verifyJWTPayload } from '../src';
|
|
19
|
+
|
|
20
|
+
setup({});
|
|
21
|
+
|
|
22
|
+
const parseConfigurationFile = (conf) => {
|
|
23
|
+
const { name, ext } = path.parse(conf);
|
|
24
|
+
const format = ext.startsWith('.') ? ext.substring(1) : 'yaml';
|
|
25
|
+
|
|
26
|
+
return path.join(__dirname, `./partials/config/${format}/security/${name}.${format}`);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
describe('Auth utilities', () => {
|
|
30
|
+
vi.setConfig({ testTimeout: 20000 });
|
|
31
|
+
|
|
32
|
+
const parseConfigurationSecurityFile = (name) => {
|
|
33
|
+
return parseConfigurationFile(`security/${name}`);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
function getConfig(configFileName: string, secret: string) {
|
|
37
|
+
const conf = parseConfigFile(parseConfigurationSecurityFile(configFileName));
|
|
38
|
+
// @ts-ignore
|
|
39
|
+
const secConf = _.merge(getDefaultConfig(), conf);
|
|
40
|
+
secConf.secret = secret;
|
|
41
|
+
const config: Config = new AppConfig(secConf);
|
|
42
|
+
|
|
43
|
+
return config;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function getTokenByConfiguration(
|
|
47
|
+
configFileName: string,
|
|
48
|
+
username: string,
|
|
49
|
+
password: string,
|
|
50
|
+
secret = '12345',
|
|
51
|
+
methodToSpy: string,
|
|
52
|
+
methodNotBeenCalled: string
|
|
53
|
+
): Promise<string> {
|
|
54
|
+
const config: Config = getConfig(configFileName, secret);
|
|
55
|
+
const auth: Auth = new Auth(config);
|
|
56
|
+
await auth.init();
|
|
57
|
+
// @ts-ignore
|
|
58
|
+
const spy = vi.spyOn(auth, methodToSpy);
|
|
59
|
+
// @ts-ignore
|
|
60
|
+
const spyNotCalled = vi.spyOn(auth, methodNotBeenCalled);
|
|
61
|
+
const user: RemoteUser = {
|
|
62
|
+
name: username,
|
|
63
|
+
real_groups: ['test', '$all', '$authenticated', '@all', '@authenticated', 'all'],
|
|
64
|
+
groups: ['company-role1', 'company-role2'],
|
|
65
|
+
};
|
|
66
|
+
const token = await getApiToken(auth, config, user, password);
|
|
67
|
+
expect(spy).toHaveBeenCalled();
|
|
68
|
+
expect(spy).toHaveBeenCalledTimes(1);
|
|
69
|
+
expect(spyNotCalled).not.toHaveBeenCalled();
|
|
70
|
+
expect(token).toBeDefined();
|
|
71
|
+
|
|
72
|
+
return token as string;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
describe('getMiddlewareCredentials test', () => {
|
|
76
|
+
describe('should get AES credentials', () => {
|
|
77
|
+
test.concurrent('should unpack aes token and credentials bearer auth', async () => {
|
|
78
|
+
const secret = 'b2df428b9929d3ace7c598bbf4e496b2';
|
|
79
|
+
const user = 'test';
|
|
80
|
+
const pass = 'test';
|
|
81
|
+
const token = await getTokenByConfiguration(
|
|
82
|
+
'security-legacy',
|
|
83
|
+
user,
|
|
84
|
+
pass,
|
|
85
|
+
secret,
|
|
86
|
+
'aesEncrypt',
|
|
87
|
+
'jwtEncrypt'
|
|
88
|
+
);
|
|
89
|
+
const config: Config = getConfig('security-legacy', secret);
|
|
90
|
+
const security: Security = config.security;
|
|
91
|
+
const credentials = getMiddlewareCredentials(security, secret, `Bearer ${token}`);
|
|
92
|
+
expect(credentials).toBeDefined();
|
|
93
|
+
// @ts-ignore
|
|
94
|
+
expect(credentials.user).toEqual(user);
|
|
95
|
+
// @ts-ignore
|
|
96
|
+
expect(credentials.password).toEqual(pass);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test.concurrent('should unpack aes token and credentials basic auth', async () => {
|
|
100
|
+
const secret = 'b2df428b9929d3ace7c598bbf4e496b2';
|
|
101
|
+
const user = 'test';
|
|
102
|
+
const pass = 'test';
|
|
103
|
+
// basic authentication need send user as base64
|
|
104
|
+
const token = buildUserBuffer(user, pass).toString('base64');
|
|
105
|
+
const config: Config = getConfig('security-legacy', secret);
|
|
106
|
+
const security: Security = config.security;
|
|
107
|
+
const credentials = getMiddlewareCredentials(security, secret, `Basic ${token}`);
|
|
108
|
+
expect(credentials).toBeDefined();
|
|
109
|
+
// @ts-ignore
|
|
110
|
+
expect(credentials.user).toEqual(user);
|
|
111
|
+
// @ts-ignore
|
|
112
|
+
expect(credentials.password).toEqual(pass);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test.concurrent('should return empty credential wrong secret key', async () => {
|
|
116
|
+
const secret = 'b2df428b9929d3ace7c598bbf4e496b2';
|
|
117
|
+
const token = await getTokenByConfiguration(
|
|
118
|
+
'security-legacy',
|
|
119
|
+
'test',
|
|
120
|
+
'test',
|
|
121
|
+
secret,
|
|
122
|
+
'aesEncrypt',
|
|
123
|
+
'jwtEncrypt'
|
|
124
|
+
);
|
|
125
|
+
const config: Config = getConfig('security-legacy', secret);
|
|
126
|
+
const security: Security = config.security;
|
|
127
|
+
const credentials = getMiddlewareCredentials(
|
|
128
|
+
security,
|
|
129
|
+
'b2df428b9929d3ace7c598bbf4e496_BAD_TOKEN',
|
|
130
|
+
buildToken(TOKEN_BEARER, token)
|
|
131
|
+
);
|
|
132
|
+
expect(credentials).not.toBeDefined();
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test.concurrent('should return empty credential wrong scheme', async () => {
|
|
136
|
+
const secret = 'b2df428b9929d3ace7c598bbf4e496b2';
|
|
137
|
+
const token = await getTokenByConfiguration(
|
|
138
|
+
'security-legacy',
|
|
139
|
+
'test',
|
|
140
|
+
'test',
|
|
141
|
+
secret,
|
|
142
|
+
'aesEncrypt',
|
|
143
|
+
'jwtEncrypt'
|
|
144
|
+
);
|
|
145
|
+
const config: Config = getConfig('security-legacy', secret);
|
|
146
|
+
const security: Security = config.security;
|
|
147
|
+
const credentials = getMiddlewareCredentials(
|
|
148
|
+
security,
|
|
149
|
+
secret,
|
|
150
|
+
buildToken('BAD_SCHEME', token)
|
|
151
|
+
);
|
|
152
|
+
expect(credentials).not.toBeDefined();
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
test.concurrent('should return empty credential corrupted payload', async () => {
|
|
156
|
+
const secret = 'b2df428b9929d3ace7c598bbf4e496b2';
|
|
157
|
+
const config: Config = getConfig('security-legacy', secret);
|
|
158
|
+
const auth: Auth = new Auth(config);
|
|
159
|
+
await auth.init();
|
|
160
|
+
// @ts-expect-error
|
|
161
|
+
const token = auth.aesEncrypt(null);
|
|
162
|
+
const security: Security = config.security;
|
|
163
|
+
const credentials = getMiddlewareCredentials(
|
|
164
|
+
security,
|
|
165
|
+
secret,
|
|
166
|
+
buildToken(TOKEN_BEARER, token as string)
|
|
167
|
+
);
|
|
168
|
+
expect(credentials).not.toBeDefined();
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
describe('verifyJWTPayload', () => {
|
|
173
|
+
test('should fail on verify the token and return anonymous users', () => {
|
|
174
|
+
expect(verifyJWTPayload('fakeToken', 'b2df428b9929d3ace7c598bbf4e496b2')).toEqual(
|
|
175
|
+
createAnonymousRemoteUser()
|
|
176
|
+
);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
test('should verify the token and return a remote user', async () => {
|
|
180
|
+
const remoteUser = createRemoteUser('foo', []);
|
|
181
|
+
const token = await signPayload(remoteUser, '12345');
|
|
182
|
+
const verifiedToken = verifyJWTPayload(token, '12345');
|
|
183
|
+
expect(verifiedToken.groups).toEqual(remoteUser.groups);
|
|
184
|
+
expect(verifiedToken.name).toEqual(remoteUser.name);
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
describe('should get JWT credentials', () => {
|
|
189
|
+
test('should return anonymous whether token is corrupted', () => {
|
|
190
|
+
const config: Config = getConfig('security-jwt', '12345');
|
|
191
|
+
const security: Security = config.security;
|
|
192
|
+
const credentials = getMiddlewareCredentials(
|
|
193
|
+
security,
|
|
194
|
+
'12345',
|
|
195
|
+
buildToken(TOKEN_BEARER, 'fakeToken')
|
|
196
|
+
) as RemoteUser;
|
|
197
|
+
|
|
198
|
+
expect(credentials).toBeDefined();
|
|
199
|
+
expect(credentials.name).not.toBeDefined();
|
|
200
|
+
expect(credentials.real_groups).toBeDefined();
|
|
201
|
+
|
|
202
|
+
expect(credentials.groups).toEqual(['$all', '$anonymous', '@all', '@anonymous']);
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
test('should return anonymous whether token and scheme are corrupted', () => {
|
|
206
|
+
const config: Config = getConfig('security-jwt', '12345');
|
|
207
|
+
const security: Security = config.security;
|
|
208
|
+
const credentials = getMiddlewareCredentials(
|
|
209
|
+
security,
|
|
210
|
+
'12345',
|
|
211
|
+
buildToken('FakeScheme', 'fakeToken')
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
expect(credentials).not.toBeDefined();
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
test('should verify successfully a JWT token', async () => {
|
|
218
|
+
const secret = 'b2df428b9929d3ace7c598bbf4e496b2';
|
|
219
|
+
const user = 'test';
|
|
220
|
+
const config: Config = getConfig('security-jwt', secret);
|
|
221
|
+
const token = await getTokenByConfiguration(
|
|
222
|
+
'security-jwt',
|
|
223
|
+
user,
|
|
224
|
+
'secretTest',
|
|
225
|
+
secret,
|
|
226
|
+
'jwtEncrypt',
|
|
227
|
+
'aesEncrypt'
|
|
228
|
+
);
|
|
229
|
+
const security: Security = config.security;
|
|
230
|
+
const credentials = getMiddlewareCredentials(
|
|
231
|
+
security,
|
|
232
|
+
secret,
|
|
233
|
+
buildToken(TOKEN_BEARER, token)
|
|
234
|
+
) as RemoteUser;
|
|
235
|
+
expect(credentials).toBeDefined();
|
|
236
|
+
|
|
237
|
+
expect(credentials.name).toEqual(user);
|
|
238
|
+
expect(credentials.real_groups).toBeDefined();
|
|
239
|
+
expect(credentials.real_groups).toEqual([
|
|
240
|
+
'test',
|
|
241
|
+
'$all',
|
|
242
|
+
'$authenticated',
|
|
243
|
+
'@all',
|
|
244
|
+
'@authenticated',
|
|
245
|
+
'all',
|
|
246
|
+
]);
|
|
247
|
+
expect(credentials.groups).toEqual([
|
|
248
|
+
'company-role1',
|
|
249
|
+
'company-role2',
|
|
250
|
+
'test',
|
|
251
|
+
'$all',
|
|
252
|
+
'$authenticated',
|
|
253
|
+
'@all',
|
|
254
|
+
'@authenticated',
|
|
255
|
+
'all',
|
|
256
|
+
]);
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
});
|
package/test/auth-utils.spec.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
2
|
import path from 'path';
|
|
3
|
+
import { describe, expect, test, vi } from 'vitest';
|
|
3
4
|
|
|
4
5
|
import {
|
|
5
6
|
Config as AppConfig,
|
|
@@ -9,17 +10,11 @@ import {
|
|
|
9
10
|
parseConfigFile,
|
|
10
11
|
} from '@verdaccio/config';
|
|
11
12
|
import { getDefaultConfig } from '@verdaccio/config';
|
|
12
|
-
import {
|
|
13
|
-
API_ERROR,
|
|
14
|
-
CHARACTER_ENCODING,
|
|
15
|
-
TOKEN_BEARER,
|
|
16
|
-
VerdaccioError,
|
|
17
|
-
errorUtils,
|
|
18
|
-
} from '@verdaccio/core';
|
|
13
|
+
import { API_ERROR, CHARACTER_ENCODING, VerdaccioError, errorUtils } from '@verdaccio/core';
|
|
19
14
|
import { setup } from '@verdaccio/logger';
|
|
20
|
-
import { aesDecrypt,
|
|
21
|
-
import { Config, RemoteUser
|
|
22
|
-
import {
|
|
15
|
+
import { aesDecrypt, verifyPayload } from '@verdaccio/signature';
|
|
16
|
+
import { Config, RemoteUser } from '@verdaccio/types';
|
|
17
|
+
import { getAuthenticatedMessage } from '@verdaccio/utils';
|
|
23
18
|
|
|
24
19
|
import {
|
|
25
20
|
ActionsAllowed,
|
|
@@ -28,8 +23,6 @@ import {
|
|
|
28
23
|
allow_action,
|
|
29
24
|
getApiToken,
|
|
30
25
|
getDefaultPlugins,
|
|
31
|
-
getMiddlewareCredentials,
|
|
32
|
-
verifyJWTPayload,
|
|
33
26
|
} from '../src';
|
|
34
27
|
|
|
35
28
|
setup({});
|
|
@@ -42,7 +35,7 @@ const parseConfigurationFile = (conf) => {
|
|
|
42
35
|
};
|
|
43
36
|
|
|
44
37
|
describe('Auth utilities', () => {
|
|
45
|
-
|
|
38
|
+
vi.setConfig({ testTimeout: 20000 });
|
|
46
39
|
|
|
47
40
|
const parseConfigurationSecurityFile = (name) => {
|
|
48
41
|
return parseConfigurationFile(`security/${name}`);
|
|
@@ -52,6 +45,7 @@ describe('Auth utilities', () => {
|
|
|
52
45
|
const conf = parseConfigFile(parseConfigurationSecurityFile(configFileName));
|
|
53
46
|
// @ts-ignore
|
|
54
47
|
const secConf = _.merge(getDefaultConfig(), conf);
|
|
48
|
+
// @ts-expect-error
|
|
55
49
|
secConf.secret = secret;
|
|
56
50
|
const config: Config = new AppConfig(secConf);
|
|
57
51
|
|
|
@@ -70,9 +64,9 @@ describe('Auth utilities', () => {
|
|
|
70
64
|
const auth: Auth = new Auth(config);
|
|
71
65
|
await auth.init();
|
|
72
66
|
// @ts-ignore
|
|
73
|
-
const spy =
|
|
67
|
+
const spy = vi.spyOn(auth, methodToSpy);
|
|
74
68
|
// @ts-ignore
|
|
75
|
-
const spyNotCalled =
|
|
69
|
+
const spyNotCalled = vi.spyOn(auth, methodNotBeenCalled);
|
|
76
70
|
const user: RemoteUser = {
|
|
77
71
|
name: username,
|
|
78
72
|
real_groups: ['test', '$all', '$authenticated', '@all', '@authenticated', 'all'],
|
|
@@ -123,14 +117,14 @@ describe('Auth utilities', () => {
|
|
|
123
117
|
|
|
124
118
|
describe('getDefaultPlugins', () => {
|
|
125
119
|
test('authentication should fail by default (default)', () => {
|
|
126
|
-
const plugin = getDefaultPlugins({ trace:
|
|
120
|
+
const plugin = getDefaultPlugins({ trace: vi.fn() });
|
|
127
121
|
plugin.authenticate('foo', 'bar', (error: any) => {
|
|
128
122
|
expect(error).toEqual(errorUtils.getForbidden(API_ERROR.BAD_USERNAME_PASSWORD));
|
|
129
123
|
});
|
|
130
124
|
});
|
|
131
125
|
|
|
132
126
|
test('add user should fail by default (default)', () => {
|
|
133
|
-
const plugin = getDefaultPlugins({ trace:
|
|
127
|
+
const plugin = getDefaultPlugins({ trace: vi.fn() });
|
|
134
128
|
// @ts-ignore
|
|
135
129
|
plugin.adduser('foo', 'bar', (error: any) => {
|
|
136
130
|
expect(error).toEqual(errorUtils.getForbidden(API_ERROR.BAD_USERNAME_PASSWORD));
|
|
@@ -151,7 +145,7 @@ describe('Auth utilities', () => {
|
|
|
151
145
|
test.each(['access', 'publish', 'unpublish'])(
|
|
152
146
|
'should restrict %s to anonymous users',
|
|
153
147
|
(type) => {
|
|
154
|
-
allow_action(type as ActionsAllowed, { trace:
|
|
148
|
+
allow_action(type as ActionsAllowed, { trace: vi.fn() })(
|
|
155
149
|
createAnonymousRemoteUser(),
|
|
156
150
|
{
|
|
157
151
|
...packageAccess,
|
|
@@ -168,7 +162,7 @@ describe('Auth utilities', () => {
|
|
|
168
162
|
test.each(['access', 'publish', 'unpublish'])(
|
|
169
163
|
'should allow %s to anonymous users',
|
|
170
164
|
(type) => {
|
|
171
|
-
allow_action(type as ActionsAllowed, { trace:
|
|
165
|
+
allow_action(type as ActionsAllowed, { trace: vi.fn() })(
|
|
172
166
|
createAnonymousRemoteUser(),
|
|
173
167
|
{
|
|
174
168
|
...packageAccess,
|
|
@@ -185,7 +179,7 @@ describe('Auth utilities', () => {
|
|
|
185
179
|
test.each(['access', 'publish', 'unpublish'])(
|
|
186
180
|
'should allow %s only if user is anonymous if the logged user has groups',
|
|
187
181
|
(type) => {
|
|
188
|
-
allow_action(type as ActionsAllowed, { trace:
|
|
182
|
+
allow_action(type as ActionsAllowed, { trace: vi.fn() })(
|
|
189
183
|
createRemoteUser('juan', ['maintainer', 'admin']),
|
|
190
184
|
{
|
|
191
185
|
...packageAccess,
|
|
@@ -202,7 +196,7 @@ describe('Auth utilities', () => {
|
|
|
202
196
|
test.each(['access', 'publish', 'unpublish'])(
|
|
203
197
|
'should allow %s only if user is anonymous match any other groups',
|
|
204
198
|
(type) => {
|
|
205
|
-
allow_action(type as ActionsAllowed, { trace:
|
|
199
|
+
allow_action(type as ActionsAllowed, { trace: vi.fn() })(
|
|
206
200
|
createRemoteUser('juan', ['maintainer', 'admin']),
|
|
207
201
|
{
|
|
208
202
|
...packageAccess,
|
|
@@ -219,7 +213,7 @@ describe('Auth utilities', () => {
|
|
|
219
213
|
test.each(['access', 'publish', 'unpublish'])(
|
|
220
214
|
'should not allow %s anonymous if other groups are defined and does not match',
|
|
221
215
|
(type) => {
|
|
222
|
-
allow_action(type as ActionsAllowed, { trace:
|
|
216
|
+
allow_action(type as ActionsAllowed, { trace: vi.fn() })(
|
|
223
217
|
createRemoteUser('juan', ['maintainer', 'admin']),
|
|
224
218
|
{
|
|
225
219
|
...packageAccess,
|
|
@@ -364,190 +358,4 @@ describe('Auth utilities', () => {
|
|
|
364
358
|
expect(getAuthenticatedMessage('test')).toBe("you are authenticated as 'test'");
|
|
365
359
|
});
|
|
366
360
|
});
|
|
367
|
-
|
|
368
|
-
describe('getMiddlewareCredentials test', () => {
|
|
369
|
-
describe('should get AES credentials', () => {
|
|
370
|
-
test.concurrent('should unpack aes token and credentials bearer auth', async () => {
|
|
371
|
-
const secret = 'b2df428b9929d3ace7c598bbf4e496b2';
|
|
372
|
-
const user = 'test';
|
|
373
|
-
const pass = 'test';
|
|
374
|
-
const token = await getTokenByConfiguration(
|
|
375
|
-
'security-legacy',
|
|
376
|
-
user,
|
|
377
|
-
pass,
|
|
378
|
-
secret,
|
|
379
|
-
'aesEncrypt',
|
|
380
|
-
'jwtEncrypt'
|
|
381
|
-
);
|
|
382
|
-
const config: Config = getConfig('security-legacy', secret);
|
|
383
|
-
const security: Security = config.security;
|
|
384
|
-
const credentials = getMiddlewareCredentials(security, secret, `Bearer ${token}`);
|
|
385
|
-
expect(credentials).toBeDefined();
|
|
386
|
-
// @ts-ignore
|
|
387
|
-
expect(credentials.user).toEqual(user);
|
|
388
|
-
// @ts-ignore
|
|
389
|
-
expect(credentials.password).toEqual(pass);
|
|
390
|
-
});
|
|
391
|
-
|
|
392
|
-
test.concurrent('should unpack aes token and credentials basic auth', async () => {
|
|
393
|
-
const secret = 'b2df428b9929d3ace7c598bbf4e496b2';
|
|
394
|
-
const user = 'test';
|
|
395
|
-
const pass = 'test';
|
|
396
|
-
// basic authentication need send user as base64
|
|
397
|
-
const token = buildUserBuffer(user, pass).toString('base64');
|
|
398
|
-
const config: Config = getConfig('security-legacy', secret);
|
|
399
|
-
const security: Security = config.security;
|
|
400
|
-
const credentials = getMiddlewareCredentials(security, secret, `Basic ${token}`);
|
|
401
|
-
expect(credentials).toBeDefined();
|
|
402
|
-
// @ts-ignore
|
|
403
|
-
expect(credentials.user).toEqual(user);
|
|
404
|
-
// @ts-ignore
|
|
405
|
-
expect(credentials.password).toEqual(pass);
|
|
406
|
-
});
|
|
407
|
-
|
|
408
|
-
test.concurrent('should return empty credential wrong secret key', async () => {
|
|
409
|
-
const secret = 'b2df428b9929d3ace7c598bbf4e496b2';
|
|
410
|
-
const token = await getTokenByConfiguration(
|
|
411
|
-
'security-legacy',
|
|
412
|
-
'test',
|
|
413
|
-
'test',
|
|
414
|
-
secret,
|
|
415
|
-
'aesEncrypt',
|
|
416
|
-
'jwtEncrypt'
|
|
417
|
-
);
|
|
418
|
-
const config: Config = getConfig('security-legacy', secret);
|
|
419
|
-
const security: Security = config.security;
|
|
420
|
-
const credentials = getMiddlewareCredentials(
|
|
421
|
-
security,
|
|
422
|
-
'b2df428b9929d3ace7c598bbf4e496_BAD_TOKEN',
|
|
423
|
-
buildToken(TOKEN_BEARER, token)
|
|
424
|
-
);
|
|
425
|
-
expect(credentials).not.toBeDefined();
|
|
426
|
-
});
|
|
427
|
-
|
|
428
|
-
test.concurrent('should return empty credential wrong scheme', async () => {
|
|
429
|
-
const secret = 'b2df428b9929d3ace7c598bbf4e496b2';
|
|
430
|
-
const token = await getTokenByConfiguration(
|
|
431
|
-
'security-legacy',
|
|
432
|
-
'test',
|
|
433
|
-
'test',
|
|
434
|
-
secret,
|
|
435
|
-
'aesEncrypt',
|
|
436
|
-
'jwtEncrypt'
|
|
437
|
-
);
|
|
438
|
-
const config: Config = getConfig('security-legacy', secret);
|
|
439
|
-
const security: Security = config.security;
|
|
440
|
-
const credentials = getMiddlewareCredentials(
|
|
441
|
-
security,
|
|
442
|
-
secret,
|
|
443
|
-
buildToken('BAD_SCHEME', token)
|
|
444
|
-
);
|
|
445
|
-
expect(credentials).not.toBeDefined();
|
|
446
|
-
});
|
|
447
|
-
|
|
448
|
-
test.concurrent('should return empty credential corrupted payload', async () => {
|
|
449
|
-
const secret = 'b2df428b9929d3ace7c598bbf4e496b2';
|
|
450
|
-
const config: Config = getConfig('security-legacy', secret);
|
|
451
|
-
const auth: Auth = new Auth(config);
|
|
452
|
-
await auth.init();
|
|
453
|
-
// @ts-expect-error
|
|
454
|
-
const token = auth.aesEncrypt(null);
|
|
455
|
-
const security: Security = config.security;
|
|
456
|
-
const credentials = getMiddlewareCredentials(
|
|
457
|
-
security,
|
|
458
|
-
secret,
|
|
459
|
-
buildToken(TOKEN_BEARER, token as string)
|
|
460
|
-
);
|
|
461
|
-
expect(credentials).not.toBeDefined();
|
|
462
|
-
});
|
|
463
|
-
});
|
|
464
|
-
|
|
465
|
-
describe('verifyJWTPayload', () => {
|
|
466
|
-
test('should fail on verify the token and return anonymous users', () => {
|
|
467
|
-
expect(verifyJWTPayload('fakeToken', 'b2df428b9929d3ace7c598bbf4e496b2')).toEqual(
|
|
468
|
-
createAnonymousRemoteUser()
|
|
469
|
-
);
|
|
470
|
-
});
|
|
471
|
-
|
|
472
|
-
test('should verify the token and return a remote user', async () => {
|
|
473
|
-
const remoteUser = createRemoteUser('foo', []);
|
|
474
|
-
const token = await signPayload(remoteUser, '12345');
|
|
475
|
-
const verifiedToken = verifyJWTPayload(token, '12345');
|
|
476
|
-
expect(verifiedToken.groups).toEqual(remoteUser.groups);
|
|
477
|
-
expect(verifiedToken.name).toEqual(remoteUser.name);
|
|
478
|
-
});
|
|
479
|
-
});
|
|
480
|
-
|
|
481
|
-
describe('should get JWT credentials', () => {
|
|
482
|
-
test('should return anonymous whether token is corrupted', () => {
|
|
483
|
-
const config: Config = getConfig('security-jwt', '12345');
|
|
484
|
-
const security: Security = config.security;
|
|
485
|
-
const credentials = getMiddlewareCredentials(
|
|
486
|
-
security,
|
|
487
|
-
'12345',
|
|
488
|
-
buildToken(TOKEN_BEARER, 'fakeToken')
|
|
489
|
-
) as RemoteUser;
|
|
490
|
-
|
|
491
|
-
expect(credentials).toBeDefined();
|
|
492
|
-
expect(credentials.name).not.toBeDefined();
|
|
493
|
-
expect(credentials.real_groups).toBeDefined();
|
|
494
|
-
|
|
495
|
-
expect(credentials.groups).toEqual(['$all', '$anonymous', '@all', '@anonymous']);
|
|
496
|
-
});
|
|
497
|
-
|
|
498
|
-
test('should return anonymous whether token and scheme are corrupted', () => {
|
|
499
|
-
const config: Config = getConfig('security-jwt', '12345');
|
|
500
|
-
const security: Security = config.security;
|
|
501
|
-
const credentials = getMiddlewareCredentials(
|
|
502
|
-
security,
|
|
503
|
-
'12345',
|
|
504
|
-
buildToken('FakeScheme', 'fakeToken')
|
|
505
|
-
);
|
|
506
|
-
|
|
507
|
-
expect(credentials).not.toBeDefined();
|
|
508
|
-
});
|
|
509
|
-
|
|
510
|
-
test('should verify successfully a JWT token', async () => {
|
|
511
|
-
const secret = 'b2df428b9929d3ace7c598bbf4e496b2';
|
|
512
|
-
const user = 'test';
|
|
513
|
-
const config: Config = getConfig('security-jwt', secret);
|
|
514
|
-
const token = await getTokenByConfiguration(
|
|
515
|
-
'security-jwt',
|
|
516
|
-
user,
|
|
517
|
-
'secretTest',
|
|
518
|
-
secret,
|
|
519
|
-
'jwtEncrypt',
|
|
520
|
-
'aesEncrypt'
|
|
521
|
-
);
|
|
522
|
-
const security: Security = config.security;
|
|
523
|
-
const credentials = getMiddlewareCredentials(
|
|
524
|
-
security,
|
|
525
|
-
secret,
|
|
526
|
-
buildToken(TOKEN_BEARER, token)
|
|
527
|
-
) as RemoteUser;
|
|
528
|
-
expect(credentials).toBeDefined();
|
|
529
|
-
|
|
530
|
-
expect(credentials.name).toEqual(user);
|
|
531
|
-
expect(credentials.real_groups).toBeDefined();
|
|
532
|
-
expect(credentials.real_groups).toEqual([
|
|
533
|
-
'test',
|
|
534
|
-
'$all',
|
|
535
|
-
'$authenticated',
|
|
536
|
-
'@all',
|
|
537
|
-
'@authenticated',
|
|
538
|
-
'all',
|
|
539
|
-
]);
|
|
540
|
-
expect(credentials.groups).toEqual([
|
|
541
|
-
'company-role1',
|
|
542
|
-
'company-role2',
|
|
543
|
-
'test',
|
|
544
|
-
'$all',
|
|
545
|
-
'$authenticated',
|
|
546
|
-
'@all',
|
|
547
|
-
'@authenticated',
|
|
548
|
-
'all',
|
|
549
|
-
]);
|
|
550
|
-
});
|
|
551
|
-
});
|
|
552
|
-
});
|
|
553
361
|
});
|
package/test/auth.spec.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import express from 'express';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import supertest from 'supertest';
|
|
4
|
+
import { describe, expect, test, vi } from 'vitest';
|
|
4
5
|
|
|
5
6
|
import { Config as AppConfig, ROLES, createRemoteUser, getDefaultConfig } from '@verdaccio/config';
|
|
6
7
|
import {
|
|
@@ -27,9 +28,9 @@ import {
|
|
|
27
28
|
setup({});
|
|
28
29
|
|
|
29
30
|
// to avoid flaky test generate same ramdom key
|
|
30
|
-
|
|
31
|
+
vi.mock('@verdaccio/utils', async (importOriginal) => {
|
|
31
32
|
return {
|
|
32
|
-
...
|
|
33
|
+
...(await importOriginal<typeof import('@verdaccio/utils')>()),
|
|
33
34
|
// used by enhanced legacy aes signature (minimum 32 characters)
|
|
34
35
|
generateRandomSecretKey: () => 'GCYW/3IJzQI6GvPmy9sbMkFoiL7QLVw',
|
|
35
36
|
// used by legacy aes signature
|
|
@@ -82,7 +83,7 @@ describe('AuthTest', () => {
|
|
|
82
83
|
await auth.init();
|
|
83
84
|
expect(auth).toBeDefined();
|
|
84
85
|
|
|
85
|
-
const callback =
|
|
86
|
+
const callback = vi.fn();
|
|
86
87
|
const groups = ['test'];
|
|
87
88
|
|
|
88
89
|
auth.authenticate('foo', 'bar', callback);
|
|
@@ -109,7 +110,7 @@ describe('AuthTest', () => {
|
|
|
109
110
|
await auth.init();
|
|
110
111
|
expect(auth).toBeDefined();
|
|
111
112
|
|
|
112
|
-
const callback =
|
|
113
|
+
const callback = vi.fn();
|
|
113
114
|
|
|
114
115
|
auth.authenticate('foo', 'bar', callback);
|
|
115
116
|
expect(callback).toHaveBeenCalledTimes(1);
|
|
@@ -128,7 +129,7 @@ describe('AuthTest', () => {
|
|
|
128
129
|
await auth.init();
|
|
129
130
|
expect(auth).toBeDefined();
|
|
130
131
|
|
|
131
|
-
const callback =
|
|
132
|
+
const callback = vi.fn();
|
|
132
133
|
let index = 0;
|
|
133
134
|
|
|
134
135
|
// as defined by https://developer.mozilla.org/en-US/docs/Glossary/Falsy
|
|
@@ -148,7 +149,7 @@ describe('AuthTest', () => {
|
|
|
148
149
|
await auth.init();
|
|
149
150
|
expect(auth).toBeDefined();
|
|
150
151
|
|
|
151
|
-
const callback =
|
|
152
|
+
const callback = vi.fn();
|
|
152
153
|
|
|
153
154
|
for (const value of [true, 1, 'test', {}]) {
|
|
154
155
|
expect(function () {
|
|
@@ -166,7 +167,7 @@ describe('AuthTest', () => {
|
|
|
166
167
|
await auth.init();
|
|
167
168
|
expect(auth).toBeDefined();
|
|
168
169
|
|
|
169
|
-
const callback =
|
|
170
|
+
const callback = vi.fn();
|
|
170
171
|
const value = [];
|
|
171
172
|
|
|
172
173
|
// @ts-ignore
|
|
@@ -183,7 +184,7 @@ describe('AuthTest', () => {
|
|
|
183
184
|
await auth.init();
|
|
184
185
|
expect(auth).toBeDefined();
|
|
185
186
|
|
|
186
|
-
const callback =
|
|
187
|
+
const callback = vi.fn();
|
|
187
188
|
let index = 0;
|
|
188
189
|
|
|
189
190
|
for (const value of [[''], ['1'], ['0'], ['000']]) {
|
|
@@ -231,7 +232,7 @@ describe('AuthTest', () => {
|
|
|
231
232
|
const auth: Auth = new Auth(config);
|
|
232
233
|
await auth.init();
|
|
233
234
|
expect(auth).toBeDefined();
|
|
234
|
-
const callback =
|
|
235
|
+
const callback = vi.fn();
|
|
235
236
|
|
|
236
237
|
auth.changePassword('foo', 'bar', 'newFoo', callback);
|
|
237
238
|
|
|
@@ -246,8 +247,8 @@ describe('AuthTest', () => {
|
|
|
246
247
|
const auth: Auth = new Auth(config);
|
|
247
248
|
await auth.init();
|
|
248
249
|
expect(auth).toBeDefined();
|
|
249
|
-
const callback =
|
|
250
|
-
auth.add_user('foo', 'bar',
|
|
250
|
+
const callback = vi.fn();
|
|
251
|
+
auth.add_user('foo', 'bar', vi.fn());
|
|
251
252
|
auth.changePassword('foo', 'bar', 'newFoo', callback);
|
|
252
253
|
expect(callback).toHaveBeenCalledTimes(1);
|
|
253
254
|
expect(callback).toHaveBeenCalledWith(null, true);
|
|
@@ -265,7 +266,7 @@ describe('AuthTest', () => {
|
|
|
265
266
|
await auth.init();
|
|
266
267
|
expect(auth).toBeDefined();
|
|
267
268
|
|
|
268
|
-
const callback =
|
|
269
|
+
const callback = vi.fn();
|
|
269
270
|
const groups = ['test'];
|
|
270
271
|
|
|
271
272
|
auth.allow_access(
|
|
@@ -287,7 +288,7 @@ describe('AuthTest', () => {
|
|
|
287
288
|
await auth.init();
|
|
288
289
|
expect(auth).toBeDefined();
|
|
289
290
|
|
|
290
|
-
const callback =
|
|
291
|
+
const callback = vi.fn();
|
|
291
292
|
// $all comes from configuration file
|
|
292
293
|
const groups = [ROLES.$ALL];
|
|
293
294
|
|
|
@@ -314,7 +315,7 @@ describe('AuthTest', () => {
|
|
|
314
315
|
await auth.init();
|
|
315
316
|
expect(auth).toBeDefined();
|
|
316
317
|
|
|
317
|
-
const callback =
|
|
318
|
+
const callback = vi.fn();
|
|
318
319
|
const groups = ['test'];
|
|
319
320
|
|
|
320
321
|
auth.allow_publish(
|
|
@@ -336,7 +337,7 @@ describe('AuthTest', () => {
|
|
|
336
337
|
await auth.init();
|
|
337
338
|
expect(auth).toBeDefined();
|
|
338
339
|
|
|
339
|
-
const callback =
|
|
340
|
+
const callback = vi.fn();
|
|
340
341
|
// $all comes from configuration file
|
|
341
342
|
const groups = [ROLES.$AUTH];
|
|
342
343
|
|
|
@@ -361,7 +362,7 @@ describe('AuthTest', () => {
|
|
|
361
362
|
await auth.init();
|
|
362
363
|
expect(auth).toBeDefined();
|
|
363
364
|
|
|
364
|
-
const callback =
|
|
365
|
+
const callback = vi.fn();
|
|
365
366
|
const groups = ['test'];
|
|
366
367
|
|
|
367
368
|
auth.allow_unpublish(
|
|
@@ -395,7 +396,7 @@ describe('AuthTest', () => {
|
|
|
395
396
|
await auth.init();
|
|
396
397
|
expect(auth).toBeDefined();
|
|
397
398
|
|
|
398
|
-
const callback =
|
|
399
|
+
const callback = vi.fn();
|
|
399
400
|
const groups = ['test'];
|
|
400
401
|
|
|
401
402
|
auth.allow_unpublish(
|
|
@@ -418,7 +419,7 @@ describe('AuthTest', () => {
|
|
|
418
419
|
await auth.init();
|
|
419
420
|
expect(auth).toBeDefined();
|
|
420
421
|
|
|
421
|
-
const callback =
|
|
422
|
+
const callback = vi.fn();
|
|
422
423
|
// $all comes from configuration file
|
|
423
424
|
const groups = [ROLES.$AUTH];
|
|
424
425
|
|
|
@@ -445,7 +446,7 @@ describe('AuthTest', () => {
|
|
|
445
446
|
await auth.init();
|
|
446
447
|
expect(auth).toBeDefined();
|
|
447
448
|
|
|
448
|
-
const callback =
|
|
449
|
+
const callback = vi.fn();
|
|
449
450
|
|
|
450
451
|
auth.add_user('juan', 'password', callback);
|
|
451
452
|
|
|
@@ -468,7 +469,7 @@ describe('AuthTest', () => {
|
|
|
468
469
|
await auth.init();
|
|
469
470
|
expect(auth).toBeDefined();
|
|
470
471
|
|
|
471
|
-
const callback =
|
|
472
|
+
const callback = vi.fn();
|
|
472
473
|
|
|
473
474
|
// note: fail uas username make plugin fails
|
|
474
475
|
auth.add_user('fail', 'password', callback);
|
|
@@ -492,7 +493,7 @@ describe('AuthTest', () => {
|
|
|
492
493
|
await auth.init();
|
|
493
494
|
expect(auth).toBeDefined();
|
|
494
495
|
|
|
495
|
-
const callback =
|
|
496
|
+
const callback = vi.fn();
|
|
496
497
|
|
|
497
498
|
// note: fail uas username make plugin fails
|
|
498
499
|
auth.add_user('skip', 'password', callback);
|
|
@@ -516,7 +517,7 @@ describe('AuthTest', () => {
|
|
|
516
517
|
await auth.init();
|
|
517
518
|
expect(auth).toBeDefined();
|
|
518
519
|
|
|
519
|
-
const callback =
|
|
520
|
+
const callback = vi.fn();
|
|
520
521
|
|
|
521
522
|
auth.add_user('something', 'password', callback);
|
|
522
523
|
|
|
@@ -540,7 +541,7 @@ describe('AuthTest', () => {
|
|
|
540
541
|
await auth.init();
|
|
541
542
|
expect(auth).toBeDefined();
|
|
542
543
|
|
|
543
|
-
const callback =
|
|
544
|
+
const callback = vi.fn();
|
|
544
545
|
|
|
545
546
|
auth.add_user('something', 'password', callback);
|
|
546
547
|
|