permission-backend: validate resourceRefs

Signed-off-by: Vincenzo Scamporlino <vincenzos@spotify.com>
This commit is contained in:
Vincenzo Scamporlino
2025-04-23 14:51:07 +02:00
parent f2cd66a162
commit 1b4cba98e0
2 changed files with 20 additions and 10 deletions
@@ -920,6 +920,20 @@ describe('createRouter', () => {
},
],
},
{
items: [
{
id: '123',
resourceRefs: [],
permission: {
type: 'resource',
name: 'test.permission',
attributes: {},
resourceType: 'test-resource-1',
},
},
],
},
{
items: [
{
@@ -965,13 +979,7 @@ describe('createRouter', () => {
const response = await request(app).post('/authorize').send(requestBody);
expect(response.status).toEqual(400);
expect(response.body).toEqual(
expect.objectContaining({
error: expect.objectContaining({
message: expect.stringMatching(/invalid/i),
}),
}),
);
expect(response.body.error.name).toEqual('InputError');
});
it('returns a 500 error if the policy returns a different resourceType', async () => {
@@ -1009,7 +1017,7 @@ describe('createRouter', () => {
);
});
it(`returns a 400 error if the request doesn't contain resourceRef for credentials not issued by a service`, async () => {
it(`returns a 400 error if the request doesn't contain resourceRef or resourceRefs for credentials not issued by a service`, async () => {
policy.handle.mockResolvedValueOnce({
result: AuthorizeResult.CONDITIONAL,
pluginId: 'test-plugin',
@@ -88,7 +88,7 @@ const evaluatePermissionRequestSchema = z.union([
z.object({
id: z.string(),
resourceRef: z.undefined().optional(),
resourceRefs: z.array(z.string()),
resourceRefs: z.array(z.string()).nonempty().optional(),
permission: resourcePermissionSchema,
}),
]);
@@ -265,7 +265,9 @@ export async function createRouter(
if (
body.items.some(
r =>
isResourcePermission(r.permission) && r.resourceRef === undefined,
isResourcePermission(r.permission) &&
r.resourceRef === undefined &&
r.resourceRefs === undefined,
)
) {
throw new InputError(