mirror of
https://github.com/logto-io/logto.git
synced 2024-12-30 20:33:54 -05:00
116 lines
3.8 KiB
TypeScript
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,
|
|
});
|
|
});
|
|
});
|
|
});
|