mirror of
https://github.com/verdaccio/verdaccio.git
synced 2025-01-20 22:52:46 -05:00
refactor: fix imports
This commit is contained in:
parent
463888165d
commit
f414f710d6
9 changed files with 150 additions and 145 deletions
|
@ -2,7 +2,8 @@ import _ from 'lodash';
|
||||||
import Cookies from 'cookies';
|
import Cookies from 'cookies';
|
||||||
import { Response, Router } from 'express';
|
import { Response, Router } from 'express';
|
||||||
|
|
||||||
import { createRemoteUser, createSessionToken, getApiToken, getAuthenticatedMessage, validatePassword, ErrorCode } from '@verdaccio/utils';
|
import { createRemoteUser, createSessionToken, getAuthenticatedMessage, validatePassword, ErrorCode } from '@verdaccio/utils';
|
||||||
|
import { getApiToken } from '@verdaccio/auth';
|
||||||
import { logger } from '@verdaccio/logger';
|
import { logger } from '@verdaccio/logger';
|
||||||
|
|
||||||
import { Config, RemoteUser } from '@verdaccio/types';
|
import { Config, RemoteUser } from '@verdaccio/types';
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { HTTP_STATUS, SUPPORT_ERRORS } from '@verdaccio/dev-commons';
|
import { HTTP_STATUS, SUPPORT_ERRORS } from '@verdaccio/dev-commons';
|
||||||
import {ErrorCode, stringToMD5, mask, getApiToken } from '@verdaccio/utils';
|
import {ErrorCode, stringToMD5, mask } from '@verdaccio/utils';
|
||||||
|
import { getApiToken } from '@verdaccio/auth';
|
||||||
import { logger } from '@verdaccio/logger';
|
import { logger } from '@verdaccio/logger';
|
||||||
import { Response, Router } from 'express';
|
import { Response, Router } from 'express';
|
||||||
|
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { NextFunction } from 'express';
|
import { NextFunction } from 'express';
|
||||||
|
|
||||||
import { VerdaccioError } from '@verdaccio/commons-api';
|
import { VerdaccioError, getBadRequest, getInternalError, getForbidden } from '@verdaccio/commons-api';
|
||||||
import {API_ERROR, SUPPORT_ERRORS, TOKEN_BASIC, TOKEN_BEARER} from '@verdaccio/dev-commons';
|
import {API_ERROR, SUPPORT_ERRORS, TOKEN_BASIC, TOKEN_BEARER} from '@verdaccio/dev-commons';
|
||||||
import { loadPlugin } from '@verdaccio/loaders';
|
import { loadPlugin } from '@verdaccio/loaders';
|
||||||
import { aesEncrypt, signPayload } from '@verdaccio/utils';
|
import { aesEncrypt, signPayload } from '@verdaccio/utils';
|
||||||
import {
|
import {
|
||||||
getDefaultPlugins,
|
getDefaultPlugins,
|
||||||
verifyJWTPayload,
|
|
||||||
createAnonymousRemoteUser,
|
createAnonymousRemoteUser,
|
||||||
isAuthHeaderValid,
|
|
||||||
getSecurity,
|
|
||||||
isAESLegacy,
|
|
||||||
convertPayloadToBase64,
|
convertPayloadToBase64,
|
||||||
ErrorCode,
|
|
||||||
parseAuthTokenHeader,
|
|
||||||
parseBasicPayload,
|
|
||||||
createRemoteUser,
|
createRemoteUser,
|
||||||
} from '@verdaccio/utils';
|
} from '@verdaccio/utils';
|
||||||
|
|
||||||
import { getMatchedPackagesSpec } from '@verdaccio/utils';
|
import { getMatchedPackagesSpec } from '@verdaccio/utils';
|
||||||
import { Config, Logger, Callback, IPluginAuth, RemoteUser, JWTSignOptions, Security, AuthPluginPackage, AllowAccess, PackageAccess } from '@verdaccio/types';
|
import { Config, Logger, Callback, IPluginAuth, RemoteUser, JWTSignOptions, Security, AuthPluginPackage, AllowAccess, PackageAccess } from '@verdaccio/types';
|
||||||
import { $RequestExtend, $ResponseExtend, IAuth, AESPayload } from '@verdaccio/dev-types';
|
import { $RequestExtend, $ResponseExtend, IAuth, AESPayload } from '@verdaccio/dev-types';
|
||||||
import {getMiddlewareCredentials} from "./utils";
|
import {
|
||||||
|
getMiddlewareCredentials,
|
||||||
|
getSecurity,
|
||||||
|
verifyJWTPayload,
|
||||||
|
parseBasicPayload,
|
||||||
|
parseAuthTokenHeader,
|
||||||
|
isAuthHeaderValid,
|
||||||
|
isAESLegacy } from "./utils";
|
||||||
|
|
||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||||
const LoggerApi = require('@verdaccio/logger');
|
const LoggerApi = require('@verdaccio/logger');
|
||||||
|
@ -68,7 +68,8 @@ class Auth implements IAuth {
|
||||||
const validPlugins = _.filter(this.plugins, plugin => _.isFunction(plugin.changePassword));
|
const validPlugins = _.filter(this.plugins, plugin => _.isFunction(plugin.changePassword));
|
||||||
|
|
||||||
if (_.isEmpty(validPlugins)) {
|
if (_.isEmpty(validPlugins)) {
|
||||||
return cb(ErrorCode.getInternalError(SUPPORT_ERRORS.PLUGIN_MISSING_INTERFACE));
|
return cb(
|
||||||
|
getInternalError(SUPPORT_ERRORS.PLUGIN_MISSING_INTERFACE));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const plugin of validPlugins) {
|
for (const plugin of validPlugins) {
|
||||||
|
@ -319,7 +320,7 @@ class Auth implements IAuth {
|
||||||
|
|
||||||
if (!isAuthHeaderValid(authorization)) {
|
if (!isAuthHeaderValid(authorization)) {
|
||||||
this.logger.trace('api middleware auth heather is not valid');
|
this.logger.trace('api middleware auth heather is not valid');
|
||||||
return next(ErrorCode.getBadRequest(API_ERROR.BAD_AUTH_HEADER));
|
return next(getBadRequest(API_ERROR.BAD_AUTH_HEADER));
|
||||||
}
|
}
|
||||||
|
|
||||||
const security: Security = getSecurity(this.config);
|
const security: Security = getSecurity(this.config);
|
||||||
|
@ -363,7 +364,7 @@ class Auth implements IAuth {
|
||||||
next();
|
next();
|
||||||
} else {
|
} else {
|
||||||
// with JWT throw 401
|
// with JWT throw 401
|
||||||
next(ErrorCode.getForbidden(API_ERROR.BAD_USERNAME_PASSWORD));
|
next(getForbidden(API_ERROR.BAD_USERNAME_PASSWORD));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -387,7 +388,7 @@ class Auth implements IAuth {
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// we force npm client to ask again with basic authentication
|
// we force npm client to ask again with basic authentication
|
||||||
return next(ErrorCode.getBadRequest(API_ERROR.BAD_AUTH_HEADER));
|
return next(getBadRequest(API_ERROR.BAD_AUTH_HEADER));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -421,7 +422,7 @@ class Auth implements IAuth {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isAuthHeaderValid(authorization)) {
|
if (!isAuthHeaderValid(authorization)) {
|
||||||
return next(ErrorCode.getBadRequest(API_ERROR.BAD_AUTH_HEADER));
|
return next(getBadRequest(API_ERROR.BAD_AUTH_HEADER));
|
||||||
}
|
}
|
||||||
|
|
||||||
const token = (authorization || '').replace(`${TOKEN_BEARER} `, '');
|
const token = (authorization || '').replace(`${TOKEN_BEARER} `, '');
|
||||||
|
|
|
@ -1,15 +1,40 @@
|
||||||
import {Security} from "@verdaccio/types";
|
import {Config, RemoteUser, Security} from "@verdaccio/types";
|
||||||
import {AuthMiddlewarePayload} from "@verdaccio/dev-types";
|
import {AuthMiddlewarePayload, AuthTokenHeader, BasicPayload, IAuthWebUI} from "@verdaccio/dev-types";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import {TOKEN_BEARER} from "@verdaccio/dev-commons";
|
import {HTTP_STATUS, TOKEN_BASIC, TOKEN_BEARER} from "@verdaccio/dev-commons";
|
||||||
import {
|
import {
|
||||||
isAESLegacy,
|
aesDecrypt,
|
||||||
parseAESCredentials,
|
buildUserBuffer,
|
||||||
parseAuthTokenHeader,
|
convertPayloadToBase64,
|
||||||
parseBasicPayload,
|
createAnonymousRemoteUser,
|
||||||
verifyJWTPayload
|
defaultSecurity,
|
||||||
|
ErrorCode,
|
||||||
|
verifyPayload
|
||||||
} from "@verdaccio/utils";
|
} from "@verdaccio/utils";
|
||||||
|
|
||||||
|
export function parseAuthTokenHeader(authorizationHeader: string): AuthTokenHeader {
|
||||||
|
const parts = authorizationHeader.split(' ');
|
||||||
|
const [scheme, token] = parts;
|
||||||
|
|
||||||
|
return { scheme, token };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parseAESCredentials(authorizationHeader: string, secret: string) {
|
||||||
|
const { scheme, token } = parseAuthTokenHeader(authorizationHeader);
|
||||||
|
|
||||||
|
// basic is deprecated and should not be enforced
|
||||||
|
if (scheme.toUpperCase() === TOKEN_BASIC.toUpperCase()) {
|
||||||
|
const credentials = convertPayloadToBase64(token).toString();
|
||||||
|
|
||||||
|
return credentials;
|
||||||
|
} else if (scheme.toUpperCase() === TOKEN_BEARER.toUpperCase()) {
|
||||||
|
const tokenAsBuffer = convertPayloadToBase64(token);
|
||||||
|
const credentials = aesDecrypt(tokenAsBuffer, secret).toString('utf8');
|
||||||
|
|
||||||
|
return credentials;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function getMiddlewareCredentials(security: Security, secret: string, authorizationHeader: string): AuthMiddlewarePayload {
|
export function getMiddlewareCredentials(security: Security, secret: string, authorizationHeader: string): AuthMiddlewarePayload {
|
||||||
if (isAESLegacy(security)) {
|
if (isAESLegacy(security)) {
|
||||||
const credentials = parseAESCredentials(authorizationHeader, secret);
|
const credentials = parseAESCredentials(authorizationHeader, secret);
|
||||||
|
@ -30,3 +55,73 @@ export function getMiddlewareCredentials(security: Security, secret: string, aut
|
||||||
return verifyJWTPayload(token, secret);
|
return verifyJWTPayload(token, secret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function isAESLegacy(security: Security): boolean {
|
||||||
|
const { legacy, jwt } = security.api;
|
||||||
|
|
||||||
|
return _.isNil(legacy) === false && _.isNil(jwt) && legacy === true;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getApiToken(auth: IAuthWebUI, config: Config, remoteUser: RemoteUser, aesPassword: string): Promise<string> {
|
||||||
|
const security: Security = getSecurity(config);
|
||||||
|
|
||||||
|
if (isAESLegacy(security)) {
|
||||||
|
// fallback all goes to AES encryption
|
||||||
|
return await new Promise((resolve): void => {
|
||||||
|
resolve(auth.aesEncrypt(buildUserBuffer(remoteUser.name as string, aesPassword)).toString('base64'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// i am wiling to use here _.isNil but flow does not like it yet.
|
||||||
|
const { jwt } = security.api;
|
||||||
|
|
||||||
|
if (jwt && jwt.sign) {
|
||||||
|
return await auth.jwtEncrypt(remoteUser, jwt.sign);
|
||||||
|
}
|
||||||
|
return await new Promise((resolve): void => {
|
||||||
|
resolve(auth.aesEncrypt(buildUserBuffer(remoteUser.name as string, aesPassword)).toString('base64'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSecurity(config: Config): Security {
|
||||||
|
if (_.isNil(config.security) === false) {
|
||||||
|
return _.merge(defaultSecurity, config.security);
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultSecurity;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const expireReasons: string[] = ['JsonWebTokenError', 'TokenExpiredError'];
|
||||||
|
|
||||||
|
export function verifyJWTPayload(token: string, secret: string): RemoteUser {
|
||||||
|
try {
|
||||||
|
const payload: RemoteUser = verifyPayload(token, secret);
|
||||||
|
|
||||||
|
return payload;
|
||||||
|
} catch (error) {
|
||||||
|
// #168 this check should be removed as soon AES encrypt is removed.
|
||||||
|
if (expireReasons.includes(error.name)) {
|
||||||
|
// it might be possible the jwt configuration is enabled and
|
||||||
|
// old tokens fails still remains in usage, thus
|
||||||
|
// we return an anonymous user to force log in.
|
||||||
|
return createAnonymousRemoteUser();
|
||||||
|
}
|
||||||
|
throw ErrorCode.getCode(HTTP_STATUS.UNAUTHORIZED, error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isAuthHeaderValid(authorization: string): boolean {
|
||||||
|
return authorization.split(' ').length === 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parseBasicPayload(credentials: string): BasicPayload {
|
||||||
|
const index = credentials.indexOf(':');
|
||||||
|
if (index < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const user: string = credentials.slice(0, index);
|
||||||
|
const password: string = credentials.slice(index + 1);
|
||||||
|
|
||||||
|
return { user, password };
|
||||||
|
}
|
||||||
|
|
|
@ -8,17 +8,21 @@ import {setup} from '@verdaccio/logger';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
buildUserBuffer,
|
buildUserBuffer,
|
||||||
getApiToken,
|
|
||||||
getAuthenticatedMessage,
|
getAuthenticatedMessage,
|
||||||
getSecurity,
|
|
||||||
aesDecrypt,
|
aesDecrypt,
|
||||||
verifyPayload,
|
verifyPayload,
|
||||||
buildToken,
|
buildToken,
|
||||||
convertPayloadToBase64,
|
convertPayloadToBase64,
|
||||||
parseConfigFile
|
parseConfigFile,
|
||||||
|
createAnonymousRemoteUser,
|
||||||
|
createRemoteUser,
|
||||||
|
signPayload
|
||||||
} from '@verdaccio/utils';
|
} from '@verdaccio/utils';
|
||||||
|
|
||||||
import { getMiddlewareCredentials } from '../src'
|
import {
|
||||||
|
getMiddlewareCredentials,
|
||||||
|
getApiToken,
|
||||||
|
getSecurity } from '../src'
|
||||||
|
|
||||||
import { IAuth } from '@verdaccio/dev-types';
|
import { IAuth } from '@verdaccio/dev-types';
|
||||||
import {Config, Security, RemoteUser} from '@verdaccio/types';
|
import {Config, Security, RemoteUser} from '@verdaccio/types';
|
||||||
|
@ -220,6 +224,20 @@ describe('Auth utilities', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('verifyJWTPayload', () => {
|
||||||
|
test('should fail on verify the token and return anonymous users', () => {
|
||||||
|
expect(verifyJWTPayload('fakeToken', 'secret')).toEqual(createAnonymousRemoteUser());
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should fail on verify the token and return anonymous users', async () => {
|
||||||
|
const remoteUser = createRemoteUser('foo', []);
|
||||||
|
const token = await signPayload(remoteUser, '12345');
|
||||||
|
const verifiedToken = verifyJWTPayload(token, '12345');
|
||||||
|
expect(verifiedToken.groups).toEqual(remoteUser.groups);
|
||||||
|
expect(verifiedToken.name).toEqual(remoteUser.name);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('should get JWT credentials', () => {
|
describe('should get JWT credentials', () => {
|
||||||
test('should return anonymous whether token is corrupted', () => {
|
test('should return anonymous whether token is corrupted', () => {
|
||||||
const config: Config = getConfig('security-jwt', '12345');
|
const config: Config = getConfig('security-jwt', '12345');
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
const config = require('../../jest/config');
|
const config = require('../../jest/config');
|
||||||
|
|
||||||
module.exports = Object.assign({}, config, {
|
module.exports = Object.assign({}, config, {
|
||||||
collectCoverage: true,
|
collectCoverage: false
|
||||||
coveragePathIgnorePatterns: ['node_modules', 'fixtures'],
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
|
||||||
import { API_ERROR, HTTP_STATUS, ROLES, TIME_EXPIRATION_7D, TOKEN_BASIC, TOKEN_BEARER, DEFAULT_MIN_LIMIT_PASSWORD } from '@verdaccio/dev-commons';
|
import { API_ERROR, ROLES, TIME_EXPIRATION_7D, DEFAULT_MIN_LIMIT_PASSWORD } from '@verdaccio/dev-commons';
|
||||||
import { CookieSessionToken, IAuthWebUI, AuthTokenHeader, BasicPayload } from '@verdaccio/dev-types';
|
import { CookieSessionToken, AuthTokenHeader, BasicPayload } from '@verdaccio/dev-types';
|
||||||
import { RemoteUser, AllowAccess, PackageAccess, Callback, Config, Security, APITokenOptions, JWTOptions, IPluginAuth } from '@verdaccio/types';
|
import { RemoteUser, AllowAccess, PackageAccess, Callback, Config, Security, APITokenOptions, JWTOptions, IPluginAuth } from '@verdaccio/types';
|
||||||
import { VerdaccioError } from '@verdaccio/commons-api';
|
import { VerdaccioError } from '@verdaccio/commons-api';
|
||||||
|
|
||||||
import { convertPayloadToBase64, ErrorCode } from './utils';
|
import { ErrorCode } from './utils';
|
||||||
import { aesDecrypt, verifyPayload } from './crypto-utils';
|
|
||||||
|
|
||||||
import { logger } from '@verdaccio/logger';
|
import { logger } from '@verdaccio/logger';
|
||||||
|
|
||||||
|
@ -152,14 +151,6 @@ export const defaultSecurity: Security = {
|
||||||
api: defaultApiTokenConf,
|
api: defaultApiTokenConf,
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getSecurity(config: Config): Security {
|
|
||||||
if (_.isNil(config.security) === false) {
|
|
||||||
return _.merge(defaultSecurity, config.security);
|
|
||||||
}
|
|
||||||
|
|
||||||
return defaultSecurity;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getAuthenticatedMessage(user: string): string {
|
export function getAuthenticatedMessage(user: string): string {
|
||||||
return `you are authenticated as '${user}'`;
|
return `you are authenticated as '${user}'`;
|
||||||
}
|
}
|
||||||
|
@ -167,88 +158,3 @@ export function getAuthenticatedMessage(user: string): string {
|
||||||
export function buildUserBuffer(name: string, password: string): Buffer {
|
export function buildUserBuffer(name: string, password: string): Buffer {
|
||||||
return Buffer.from(`${name}:${password}`, 'utf8');
|
return Buffer.from(`${name}:${password}`, 'utf8');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isAESLegacy(security: Security): boolean {
|
|
||||||
const { legacy, jwt } = security.api;
|
|
||||||
|
|
||||||
return _.isNil(legacy) === false && _.isNil(jwt) && legacy === true;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getApiToken(auth: IAuthWebUI, config: Config, remoteUser: RemoteUser, aesPassword: string): Promise<string> {
|
|
||||||
const security: Security = getSecurity(config);
|
|
||||||
|
|
||||||
if (isAESLegacy(security)) {
|
|
||||||
// fallback all goes to AES encryption
|
|
||||||
return await new Promise((resolve): void => {
|
|
||||||
resolve(auth.aesEncrypt(buildUserBuffer(remoteUser.name as string, aesPassword)).toString('base64'));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// i am wiling to use here _.isNil but flow does not like it yet.
|
|
||||||
const { jwt } = security.api;
|
|
||||||
|
|
||||||
if (jwt && jwt.sign) {
|
|
||||||
return await auth.jwtEncrypt(remoteUser, jwt.sign);
|
|
||||||
}
|
|
||||||
return await new Promise((resolve): void => {
|
|
||||||
resolve(auth.aesEncrypt(buildUserBuffer(remoteUser.name as string, aesPassword)).toString('base64'));
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export function parseAuthTokenHeader(authorizationHeader: string): AuthTokenHeader {
|
|
||||||
const parts = authorizationHeader.split(' ');
|
|
||||||
const [scheme, token] = parts;
|
|
||||||
|
|
||||||
return { scheme, token };
|
|
||||||
}
|
|
||||||
|
|
||||||
export function parseBasicPayload(credentials: string): BasicPayload {
|
|
||||||
const index = credentials.indexOf(':');
|
|
||||||
if (index < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const user: string = credentials.slice(0, index);
|
|
||||||
const password: string = credentials.slice(index + 1);
|
|
||||||
|
|
||||||
return { user, password };
|
|
||||||
}
|
|
||||||
|
|
||||||
export function parseAESCredentials(authorizationHeader: string, secret: string) {
|
|
||||||
const { scheme, token } = parseAuthTokenHeader(authorizationHeader);
|
|
||||||
|
|
||||||
// basic is deprecated and should not be enforced
|
|
||||||
if (scheme.toUpperCase() === TOKEN_BASIC.toUpperCase()) {
|
|
||||||
const credentials = convertPayloadToBase64(token).toString();
|
|
||||||
|
|
||||||
return credentials;
|
|
||||||
} else if (scheme.toUpperCase() === TOKEN_BEARER.toUpperCase()) {
|
|
||||||
const tokenAsBuffer = convertPayloadToBase64(token);
|
|
||||||
const credentials = aesDecrypt(tokenAsBuffer, secret).toString('utf8');
|
|
||||||
|
|
||||||
return credentials;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const expireReasons: string[] = ['JsonWebTokenError', 'TokenExpiredError'];
|
|
||||||
|
|
||||||
export function verifyJWTPayload(token: string, secret: string): RemoteUser {
|
|
||||||
try {
|
|
||||||
const payload: RemoteUser = verifyPayload(token, secret);
|
|
||||||
|
|
||||||
return payload;
|
|
||||||
} catch (error) {
|
|
||||||
// #168 this check should be removed as soon AES encrypt is removed.
|
|
||||||
if (expireReasons.includes(error.name)) {
|
|
||||||
// it might be possible the jwt configuration is enabled and
|
|
||||||
// old tokens fails still remains in usage, thus
|
|
||||||
// we return an anonymous user to force log in.
|
|
||||||
return createAnonymousRemoteUser();
|
|
||||||
}
|
|
||||||
throw ErrorCode.getCode(HTTP_STATUS.UNAUTHORIZED, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isAuthHeaderValid(authorization: string): boolean {
|
|
||||||
return authorization.split(' ').length === 2;
|
|
||||||
}
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ import {
|
||||||
getDefaultPlugins,
|
getDefaultPlugins,
|
||||||
createSessionToken,
|
createSessionToken,
|
||||||
getAuthenticatedMessage,
|
getAuthenticatedMessage,
|
||||||
verifyJWTPayload, defaultNonLoggedUserRoles, signPayload
|
|
||||||
} from "../src";
|
} from "../src";
|
||||||
import { API_ERROR, ROLES } from "@verdaccio/dev-commons";
|
import { API_ERROR, ROLES } from "@verdaccio/dev-commons";
|
||||||
import { VerdaccioError, getForbidden } from "@verdaccio/commons-api";
|
import { VerdaccioError, getForbidden } from "@verdaccio/commons-api";
|
||||||
|
@ -164,20 +163,4 @@ describe('Auth Utilities', () => {
|
||||||
expect(getAuthenticatedMessage('foo')).toEqual('you are authenticated as \'foo\'');
|
expect(getAuthenticatedMessage('foo')).toEqual('you are authenticated as \'foo\'');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('verifyJWTPayload', () => {
|
|
||||||
test('should fail on verify the token and return anonymous users', () => {
|
|
||||||
expect(verifyJWTPayload('fakeToken', 'secret')).toEqual(createAnonymousRemoteUser());
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should fail on verify the token and return anonymous users', async () => {
|
|
||||||
const remoteUser = createRemoteUser('foo', []);
|
|
||||||
const token = await signPayload(remoteUser, '12345');
|
|
||||||
const verifiedToken = verifyJWTPayload(token, '12345');
|
|
||||||
expect(verifiedToken.groups).toEqual(remoteUser.groups);
|
|
||||||
expect(verifiedToken.name).toEqual(remoteUser.name);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// verifyJWTPayload
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,7 +5,8 @@ import { Config, RemoteUser, JWTSignOptions } from '@verdaccio/types';
|
||||||
|
|
||||||
import { API_ERROR, APP_ERROR, HTTP_STATUS } from '@verdaccio/dev-commons';
|
import { API_ERROR, APP_ERROR, HTTP_STATUS } from '@verdaccio/dev-commons';
|
||||||
import { IAuth, $NextFunctionVer } from '@verdaccio/dev-types';
|
import { IAuth, $NextFunctionVer } from '@verdaccio/dev-types';
|
||||||
import { getSecurity, validatePassword, ErrorCode } from '@verdaccio/utils';
|
import { validatePassword, ErrorCode } from '@verdaccio/utils';
|
||||||
|
import { getSecurity } from '@verdaccio/auth';
|
||||||
|
|
||||||
function addUserAuthApi(route: Router, auth: IAuth, config: Config): void {
|
function addUserAuthApi(route: Router, auth: IAuth, config: Config): void {
|
||||||
route.post('/login', function(req: Request, res: Response, next: $NextFunctionVer): void {
|
route.post('/login', function(req: Request, res: Response, next: $NextFunctionVer): void {
|
||||||
|
|
Loading…
Add table
Reference in a new issue