0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-30 20:33:54 -05:00
logto/packages/core/src/routes/authn.test.ts
2022-12-12 13:43:23 +08:00

116 lines
3.8 KiB
TypeScript

import { mockEsmWithActual, pickDefault } from '@logto/shared/esm';
import RequestError from '#src/errors/RequestError/index.js';
import { createRequester } from '#src/utils/test-utils.js';
const { jest } = import.meta;
const { verifyBearerTokenFromRequest } = await mockEsmWithActual(
'#src/middleware/koa-auth.js',
() => ({
verifyBearerTokenFromRequest: jest.fn(),
})
);
const request = createRequester({
anonymousRoutes: await pickDefault(import('#src/routes/authn.js')),
});
describe('authn route for Hasura', () => {
const mockUserId = 'foo';
const mockExpectedRole = 'some_role';
const mockUnauthorizedRole = 'V';
const keys = Object.freeze({
expectedRole: 'Expected-Role',
hasuraUserId: 'X-Hasura-User-Id',
hasuraRole: 'X-Hasura-Role',
});
describe('with successful verification', () => {
beforeEach(() => {
verifyBearerTokenFromRequest.mockResolvedValue({
clientId: 'ok',
sub: mockUserId,
roleNames: [mockExpectedRole],
});
});
it('has expected role', async () => {
const response = await request
.get('/authn/hasura')
.query({ resource: 'https://api.logto.io' })
.set(keys.expectedRole, mockExpectedRole);
expect(response.status).toEqual(200);
expect(response.body).toEqual({
[keys.hasuraUserId]: mockUserId,
[keys.hasuraRole]: mockExpectedRole,
});
});
it('throws 401 if no expected role present', async () => {
const response = await request
.get('/authn/hasura')
.query({ resource: 'https://api.logto.io' })
.set(keys.expectedRole, mockExpectedRole + '1');
expect(response.status).toEqual(401);
});
it('falls back to unauthorized role if no expected role present', async () => {
const response = await request
.get('/authn/hasura')
.query({ resource: 'https://api.logto.io', unauthorizedRole: mockUnauthorizedRole })
.set(keys.expectedRole, mockExpectedRole + '1');
expect(response.status).toEqual(200);
expect(response.body).toEqual({
[keys.hasuraUserId]: mockUserId,
[keys.hasuraRole]: mockUnauthorizedRole,
});
});
});
describe('with failed verification', () => {
beforeEach(() => {
verifyBearerTokenFromRequest.mockImplementation(async (_, resource) => {
if (resource) {
throw new RequestError({ code: 'auth.jwt_sub_missing', status: 401 });
}
return { clientId: 'not ok', sub: mockUserId };
});
});
it('throws 401 if no unauthorized role presents', async () => {
const response = await request
.get('/authn/hasura')
.query({ resource: 'https://api.logto.io' })
.set(keys.expectedRole, mockExpectedRole);
expect(response.status).toEqual(401);
});
it('falls back to unauthorized role with user id if no expected resource present', async () => {
const response = await request
.get('/authn/hasura')
.query({ resource: 'https://api.logto.io', unauthorizedRole: mockUnauthorizedRole })
.set(keys.expectedRole, mockExpectedRole);
expect(response.status).toEqual(200);
expect(response.body).toEqual({
[keys.hasuraUserId]: mockUserId,
[keys.hasuraRole]: mockUnauthorizedRole,
});
});
it('falls back to unauthorized role if JWT is invalid', async () => {
verifyBearerTokenFromRequest.mockRejectedValue(
new RequestError({ code: 'auth.jwt_sub_missing', status: 401 })
);
const response = await request
.get('/authn/hasura')
.query({ resource: 'https://api.logto.io', unauthorizedRole: mockUnauthorizedRole });
expect(response.status).toEqual(200);
expect(response.body).toEqual({
[keys.hasuraRole]: mockUnauthorizedRole,
});
});
});
});