fix(core): Improve the security on OAuth callback endpoints (#11593)

This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™
2024-11-19 16:17:20 +01:00
committed by GitHub
parent c265d44841
commit 274fcf45d3
9 changed files with 285 additions and 173 deletions

View File

@@ -8,7 +8,7 @@ import { CredentialsHelper } from '@/credentials-helper';
import type { CredentialsEntity } from '@/databases/entities/credentials-entity';
import type { User } from '@/databases/entities/user';
import { saveCredential } from '@test-integration/db/credentials';
import { createOwner } from '@test-integration/db/users';
import { createMember, createOwner } from '@test-integration/db/users';
import * as testDb from '@test-integration/test-db';
import type { SuperAgentTest } from '@test-integration/types';
import { setupTestServer } from '@test-integration/utils';
@@ -17,6 +17,7 @@ describe('OAuth2 API', () => {
const testServer = setupTestServer({ endpointGroups: ['oauth2'] });
let owner: User;
let anotherUser: User;
let ownerAgent: SuperAgentTest;
let credential: CredentialsEntity;
const credentialData = {
@@ -32,6 +33,7 @@ describe('OAuth2 API', () => {
beforeAll(async () => {
owner = await createOwner();
anotherUser = await createMember();
ownerAgent = testServer.authAgentFor(owner);
});
@@ -74,6 +76,28 @@ describe('OAuth2 API', () => {
});
});
it('should fail on auth when callback is called as another user', async () => {
const controller = Container.get(OAuth2CredentialController);
const csrfSpy = jest.spyOn(controller, 'createCsrfState').mockClear();
const renderSpy = (Response.render = jest.fn(function () {
this.end();
}));
await ownerAgent.get('/oauth2-credential/auth').query({ id: credential.id }).expect(200);
const [_, state] = csrfSpy.mock.results[0].value;
await testServer
.authAgentFor(anotherUser)
.get('/oauth2-credential/callback')
.query({ code: 'auth_code', state })
.expect(200);
expect(renderSpy).toHaveBeenCalledWith('oauth-error-callback', {
error: { message: 'Unauthorized' },
});
});
it('should handle a valid callback without auth', async () => {
const controller = Container.get(OAuth2CredentialController);
const csrfSpy = jest.spyOn(controller, 'createCsrfState').mockClear();
@@ -87,7 +111,7 @@ describe('OAuth2 API', () => {
nock('https://test.domain').post('/oauth2/token').reply(200, { access_token: 'updated_token' });
await testServer.authlessAgent
await ownerAgent
.get('/oauth2-credential/callback')
.query({ code: 'auth_code', state })
.expect(200);