prevent handlers overrides
Signed-off-by: Juan Pablo Garcia Ripa <sarabadu@gmail.com>
This commit is contained in:
+70
@@ -354,6 +354,76 @@ describe('ExternalTokenHandler', () => {
|
||||
|
||||
expect(verifyMock).toHaveBeenCalledWith(customToken, { context: 'a' });
|
||||
});
|
||||
it('should fail if custom handler has same type as builtin handlers', async () => {
|
||||
const logger = mockServices.logger.mock();
|
||||
const customStaticHandler: ExternalTokenHandler<unknown> =
|
||||
createExternalTokenHandler({
|
||||
type: 'static',
|
||||
initialize: jest.fn().mockResolvedValue(undefined),
|
||||
verifyToken: jest.fn().mockResolvedValue({
|
||||
subject: 'custom-static-subject',
|
||||
}),
|
||||
});
|
||||
|
||||
const createHandler = () =>
|
||||
ExternalAuthTokenHandler.create({
|
||||
ownPluginId: 'catalog',
|
||||
logger,
|
||||
config: mockServices.rootConfig({
|
||||
data: {
|
||||
backend: {
|
||||
auth: {
|
||||
externalAccess: [
|
||||
{
|
||||
type: 'static',
|
||||
options: {
|
||||
token: 'mytoken',
|
||||
subject: 'static-subject',
|
||||
},
|
||||
accessRestrictions: [
|
||||
{ plugin: 'catalog', permission: 'catalog.entity.read' },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
externalTokenHandlers: [customStaticHandler],
|
||||
});
|
||||
|
||||
expect(createHandler).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Duplicate external token handler type 'static', each handler must have a unique type"`,
|
||||
);
|
||||
});
|
||||
it('should fail if 2 custom handlers have the same type', async () => {
|
||||
const createHandler = () =>
|
||||
ExternalAuthTokenHandler.create({
|
||||
ownPluginId: 'catalog',
|
||||
logger: mockServices.logger.mock(),
|
||||
config: mockServices.rootConfig(),
|
||||
externalTokenHandlers: [
|
||||
createExternalTokenHandler({
|
||||
type: 'internal-custom',
|
||||
initialize: jest.fn().mockResolvedValue(undefined),
|
||||
verifyToken: jest.fn().mockResolvedValue({
|
||||
subject: 'sub',
|
||||
}),
|
||||
}),
|
||||
createExternalTokenHandler({
|
||||
type: 'internal-custom',
|
||||
initialize: jest.fn().mockResolvedValue(undefined),
|
||||
verifyToken: jest.fn().mockResolvedValue({
|
||||
subject: 'sub',
|
||||
}),
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
expect(createHandler).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Duplicate external token handler type 'internal-custom', each handler must have a unique type"`,
|
||||
);
|
||||
});
|
||||
it('should fail if config contains types not declared', async () => {
|
||||
const createHandler = () =>
|
||||
ExternalAuthTokenHandler.create({
|
||||
|
||||
+24
-9
@@ -42,11 +42,11 @@ export const externalTokenHandlersServiceRef = createServiceRef<
|
||||
multiton: true,
|
||||
});
|
||||
|
||||
const defaultHandlers: ExternalTokenHandler<unknown>[] = [
|
||||
staticTokenHandler,
|
||||
legacyTokenHandler,
|
||||
jwksTokenHandler,
|
||||
];
|
||||
const defaultHandlers: Record<string, ExternalTokenHandler<unknown>> = {
|
||||
static: staticTokenHandler,
|
||||
legacy: legacyTokenHandler,
|
||||
jwks: jwksTokenHandler,
|
||||
};
|
||||
|
||||
type ContextMapEntry<T> = {
|
||||
context: T;
|
||||
@@ -70,20 +70,35 @@ export class ExternalAuthTokenHandler {
|
||||
const {
|
||||
ownPluginId,
|
||||
config,
|
||||
externalTokenHandlers: customHandlers,
|
||||
externalTokenHandlers: customHandlers = [],
|
||||
logger,
|
||||
} = options;
|
||||
|
||||
const handlersTypes = [...defaultHandlers, ...(customHandlers ?? [])];
|
||||
const handlersTypes = customHandlers.reduce<
|
||||
Record<string, ExternalTokenHandler<unknown>>
|
||||
>(
|
||||
(acc, handler) => {
|
||||
if (acc[handler.type]) {
|
||||
throw new Error(
|
||||
`Duplicate external token handler type '${handler.type}', each handler must have a unique type`,
|
||||
);
|
||||
}
|
||||
acc[handler.type] = handler;
|
||||
return acc;
|
||||
},
|
||||
{ ...defaultHandlers },
|
||||
);
|
||||
|
||||
const handlerConfigs = config.getOptionalConfigArray(NEW_CONFIG_KEY) ?? [];
|
||||
const contexts: ContextMapEntry<unknown>[] = handlerConfigs.map(
|
||||
handlerConfig => {
|
||||
const type = handlerConfig.getString('type');
|
||||
|
||||
const handler = handlersTypes.find(h => h.type === type);
|
||||
const handler = handlersTypes[type];
|
||||
if (!handler) {
|
||||
const valid = handlersTypes.map(h => `'${h.type}'`).join(', ');
|
||||
const valid = Object.keys(handlersTypes)
|
||||
.map(h => `'${h}'`)
|
||||
.join(', ');
|
||||
throw new Error(
|
||||
`Unknown type '${type}' in ${NEW_CONFIG_KEY}, expected one of ${valid}`,
|
||||
);
|
||||
|
||||
@@ -75,7 +75,6 @@ export const jwksTokenHandler = createExternalTokenHandler<JWKSTokenContext>({
|
||||
: 'external:';
|
||||
return {
|
||||
subject: `${prefix}${sub}`,
|
||||
allAccessRestrictions: context.allAccessRestrictions,
|
||||
};
|
||||
}
|
||||
} catch {
|
||||
|
||||
Reference in New Issue
Block a user