mirror of
https://github.com/verdaccio/verdaccio.git
synced 2024-12-16 21:56:25 -05:00
fix: duplicated groups on use jwt tokens (#3151)
* fix: duplicated groups on use jwt tokens * chore: format * chore: fix jest ci
This commit is contained in:
parent
34b7394bcf
commit
51803c3477
4 changed files with 46 additions and 16 deletions
4
.github/workflows/e2e-jest-workflow.yml
vendored
4
.github/workflows/e2e-jest-workflow.yml
vendored
|
@ -140,7 +140,7 @@ jobs:
|
||||||
yarn jest module.test.js
|
yarn jest module.test.js
|
||||||
|
|
||||||
pnpm6:
|
pnpm6:
|
||||||
name: 'pnpm:next-6:jest example'
|
name: 'pnpm:latest-6:jest example'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
@ -151,7 +151,7 @@ jobs:
|
||||||
with:
|
with:
|
||||||
node-version: 12.x
|
node-version: 12.x
|
||||||
- name: 'install latest pnpm'
|
- name: 'install latest pnpm'
|
||||||
run: npm i -g pnpm@next-6
|
run: npm i -g pnpm@latest-6
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: yarn install
|
run: yarn install
|
||||||
- name: 'Run verdaccio in the background'
|
- name: 'Run verdaccio in the background'
|
||||||
|
|
|
@ -24,7 +24,7 @@ export function validatePassword(
|
||||||
*/
|
*/
|
||||||
export function createRemoteUser(name: string, pluginGroups: string[]): RemoteUser {
|
export function createRemoteUser(name: string, pluginGroups: string[]): RemoteUser {
|
||||||
const isGroupValid: boolean = Array.isArray(pluginGroups);
|
const isGroupValid: boolean = Array.isArray(pluginGroups);
|
||||||
const groups = (isGroupValid ? pluginGroups : []).concat([ROLES.$ALL, ROLES.$AUTH, ROLES.DEPRECATED_ALL, ROLES.DEPRECATED_AUTH, ROLES.ALL]);
|
const groups = Array.from(new Set((isGroupValid ? pluginGroups : []).concat([ROLES.$ALL, ROLES.$AUTH, ROLES.DEPRECATED_ALL, ROLES.DEPRECATED_AUTH, ROLES.ALL])));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name,
|
name,
|
||||||
|
|
|
@ -420,7 +420,7 @@ class Auth implements IAuth {
|
||||||
public async jwtEncrypt(user: RemoteUser, signOptions: JWTSignOptions): Promise<string> {
|
public async jwtEncrypt(user: RemoteUser, signOptions: JWTSignOptions): Promise<string> {
|
||||||
const { real_groups, name, groups } = user;
|
const { real_groups, name, groups } = user;
|
||||||
const realGroupsValidated = _.isNil(real_groups) ? [] : real_groups;
|
const realGroupsValidated = _.isNil(real_groups) ? [] : real_groups;
|
||||||
const groupedGroups = _.isNil(groups) ? real_groups : groups.concat(realGroupsValidated);
|
const groupedGroups = _.isNil(groups) ? real_groups : Array.from(new Set([...groups.concat(realGroupsValidated)]));
|
||||||
const payload: RemoteUser = {
|
const payload: RemoteUser = {
|
||||||
real_groups: realGroupsValidated,
|
real_groups: realGroupsValidated,
|
||||||
name,
|
name,
|
||||||
|
|
|
@ -3,7 +3,15 @@ import _ from 'lodash';
|
||||||
import { Config, RemoteUser, Security } from '@verdaccio/types';
|
import { Config, RemoteUser, Security } from '@verdaccio/types';
|
||||||
|
|
||||||
import Auth from '../../../../src/lib/auth';
|
import Auth from '../../../../src/lib/auth';
|
||||||
import { buildUserBuffer, getApiToken, getAuthenticatedMessage, getMiddlewareCredentials, getSecurity } from '../../../../src/lib/auth-utils';
|
import {
|
||||||
|
buildUserBuffer,
|
||||||
|
createAnonymousRemoteUser,
|
||||||
|
createRemoteUser,
|
||||||
|
getApiToken,
|
||||||
|
getAuthenticatedMessage,
|
||||||
|
getMiddlewareCredentials,
|
||||||
|
getSecurity,
|
||||||
|
} from '../../../../src/lib/auth-utils';
|
||||||
import AppConfig from '../../../../src/lib/config';
|
import AppConfig from '../../../../src/lib/config';
|
||||||
import { CHARACTER_ENCODING, TOKEN_BEARER } from '../../../../src/lib/constants';
|
import { CHARACTER_ENCODING, TOKEN_BEARER } from '../../../../src/lib/constants';
|
||||||
import { aesDecrypt, verifyPayload } from '../../../../src/lib/crypto-utils';
|
import { aesDecrypt, verifyPayload } from '../../../../src/lib/crypto-utils';
|
||||||
|
@ -41,8 +49,8 @@ describe('Auth utilities', () => {
|
||||||
const spyNotCalled = jest.spyOn(auth, methodNotBeenCalled);
|
const spyNotCalled = jest.spyOn(auth, methodNotBeenCalled);
|
||||||
const user: RemoteUser = {
|
const user: RemoteUser = {
|
||||||
name: username,
|
name: username,
|
||||||
real_groups: [],
|
real_groups: ['test', '$all', '$authenticated', '@all', '@authenticated', 'all'],
|
||||||
groups: [],
|
groups: ['company-role1', 'company-role2'],
|
||||||
};
|
};
|
||||||
const token = await getApiToken(auth, config, user, password);
|
const token = await getApiToken(auth, config, user, password);
|
||||||
expect(spy).toHaveBeenCalled();
|
expect(spy).toHaveBeenCalled();
|
||||||
|
@ -57,7 +65,9 @@ describe('Auth utilities', () => {
|
||||||
const payload = verifyPayload(token, secret);
|
const payload = verifyPayload(token, secret);
|
||||||
expect(payload.name).toBe(user);
|
expect(payload.name).toBe(user);
|
||||||
expect(payload.groups).toBeDefined();
|
expect(payload.groups).toBeDefined();
|
||||||
|
expect(payload.groups).toEqual(['company-role1', 'company-role2', 'test', '$all', '$authenticated', '@all', '@authenticated', 'all']);
|
||||||
expect(payload.real_groups).toBeDefined();
|
expect(payload.real_groups).toBeDefined();
|
||||||
|
expect(payload.real_groups).toEqual(['test', '$all', '$authenticated', '@all', '@authenticated', 'all']);
|
||||||
};
|
};
|
||||||
|
|
||||||
const verifyAES = (token: string, user: string, password: string, secret: string) => {
|
const verifyAES = (token: string, user: string, password: string, secret: string) => {
|
||||||
|
@ -68,6 +78,30 @@ describe('Auth utilities', () => {
|
||||||
expect(content[0]).toBe(password);
|
expect(content[0]).toBe(password);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
describe('createRemoteUser', () => {
|
||||||
|
test('create remote user', () => {
|
||||||
|
expect(createRemoteUser('test', [])).toEqual({
|
||||||
|
name: 'test',
|
||||||
|
real_groups: [],
|
||||||
|
groups: ['$all', '$authenticated', '@all', '@authenticated', 'all'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
test('create remote user with groups', () => {
|
||||||
|
expect(createRemoteUser('test', ['group1', 'group2'])).toEqual({
|
||||||
|
name: 'test',
|
||||||
|
real_groups: ['group1', 'group2'],
|
||||||
|
groups: ['group1', 'group2', '$all', '$authenticated', '@all', '@authenticated', 'all'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
test('create anonymous remote user', () => {
|
||||||
|
expect(createAnonymousRemoteUser()).toEqual({
|
||||||
|
name: undefined,
|
||||||
|
real_groups: [],
|
||||||
|
groups: ['$all', '$anonymous', '@all', '@anonymous'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('getApiToken test', () => {
|
describe('getApiToken test', () => {
|
||||||
test('should sign token with aes and security missing', async () => {
|
test('should sign token with aes and security missing', async () => {
|
||||||
const token = await signCredentials('security-missing', 'test', 'test', '1234567', 'aesEncrypt', 'jwtEncrypt');
|
const token = await signCredentials('security-missing', 'test', 'test', '1234567', 'aesEncrypt', 'jwtEncrypt');
|
||||||
|
@ -190,15 +224,13 @@ describe('Auth utilities', () => {
|
||||||
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');
|
||||||
const security: Security = getSecurity(config);
|
const security: Security = getSecurity(config);
|
||||||
const credentials = getMiddlewareCredentials(security, '12345', buildToken(TOKEN_BEARER, 'fakeToken'));
|
const credentials = getMiddlewareCredentials(security, '12345', buildToken(TOKEN_BEARER, 'fakeToken')) as RemoteUser;
|
||||||
|
|
||||||
expect(credentials).toBeDefined();
|
expect(credentials).toBeDefined();
|
||||||
// @ts-ignore
|
|
||||||
expect(credentials.name).not.toBeDefined();
|
expect(credentials.name).not.toBeDefined();
|
||||||
// @ts-ignore
|
|
||||||
expect(credentials.real_groups).toBeDefined();
|
expect(credentials.real_groups).toBeDefined();
|
||||||
// @ts-ignore
|
|
||||||
expect(credentials.real_groups).toEqual([]);
|
expect(credentials.real_groups).toEqual([]);
|
||||||
|
expect(credentials.groups).toEqual(['$all', '$anonymous', '@all', '@anonymous']);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should return anonymous whether token and scheme are corrupted', () => {
|
test('should return anonymous whether token and scheme are corrupted', () => {
|
||||||
|
@ -215,14 +247,12 @@ describe('Auth utilities', () => {
|
||||||
const config: Config = getConfig('security-jwt', secret);
|
const config: Config = getConfig('security-jwt', secret);
|
||||||
const token = await signCredentials('security-jwt', user, 'secretTest', secret, 'jwtEncrypt', 'aesEncrypt');
|
const token = await signCredentials('security-jwt', user, 'secretTest', secret, 'jwtEncrypt', 'aesEncrypt');
|
||||||
const security: Security = getSecurity(config);
|
const security: Security = getSecurity(config);
|
||||||
const credentials = getMiddlewareCredentials(security, secret, buildToken(TOKEN_BEARER, token));
|
const credentials = getMiddlewareCredentials(security, secret, buildToken(TOKEN_BEARER, token)) as RemoteUser;
|
||||||
expect(credentials).toBeDefined();
|
expect(credentials).toBeDefined();
|
||||||
// @ts-ignore
|
|
||||||
expect(credentials.name).toEqual(user);
|
expect(credentials.name).toEqual(user);
|
||||||
// @ts-ignore
|
|
||||||
expect(credentials.real_groups).toBeDefined();
|
expect(credentials.real_groups).toBeDefined();
|
||||||
// @ts-ignore
|
expect(credentials.real_groups).toEqual(['test', '$all', '$authenticated', '@all', '@authenticated', 'all']);
|
||||||
expect(credentials.real_groups).toEqual([]);
|
expect(credentials.groups).toEqual(['company-role1', 'company-role2', 'test', '$all', '$authenticated', '@all', '@authenticated', 'all']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue