From 08b9cef5ec1a6559fef872929f88103fec6606c0 Mon Sep 17 00:00:00 2001 From: LEGO Technix <109212476+lego-technix@users.noreply.github.com> Date: Fri, 15 Nov 2024 16:58:23 +0100 Subject: [PATCH] test(api): add OidcAuthenticationServiceRegistry integration tests --- ...dc-authentication-service-registry.test.js | 379 ++++++++++++++++++ 1 file changed, 379 insertions(+) create mode 100644 api/tests/identity-access-management/integration/domain/services/oidc-authentication-service-registry.test.js diff --git a/api/tests/identity-access-management/integration/domain/services/oidc-authentication-service-registry.test.js b/api/tests/identity-access-management/integration/domain/services/oidc-authentication-service-registry.test.js new file mode 100644 index 00000000000..5ac5ec8cb6b --- /dev/null +++ b/api/tests/identity-access-management/integration/domain/services/oidc-authentication-service-registry.test.js @@ -0,0 +1,379 @@ +import { PIX_ADMIN } from '../../../../../src/authorization/domain/constants.js'; +import { OidcProvider } from '../../../../../src/identity-access-management/domain/models/OidcProvider.js'; +import { FwbOidcAuthenticationService } from '../../../../../src/identity-access-management/domain/services/fwb-oidc-authentication-service.js'; +import { OidcAuthenticationService } from '../../../../../src/identity-access-management/domain/services/oidc-authentication-service.js'; +import { OidcAuthenticationServiceRegistry } from '../../../../../src/identity-access-management/domain/services/oidc-authentication-service-registry.js'; +import { PoleEmploiOidcAuthenticationService } from '../../../../../src/identity-access-management/domain/services/pole-emploi-oidc-authentication-service.js'; +import { oidcProviderRepository } from '../../../../../src/identity-access-management/infrastructure/repositories/oidc-provider-repository.js'; +import { InvalidIdentityProviderError } from '../../../../../src/shared/domain/errors.js'; +import { catchErrSync, databaseBuilder, expect, sinon } from '../../../../test-helper.js'; + +describe('Integration | Identity Access Management | Domain | Service | oidc-authentication-service-registry', function () { + let oidcAuthenticationServiceRegistry; + + beforeEach(async function () { + const genericOidcProviderProperties = { + enabled: true, + accessTokenLifespan: '7d', + clientId: 'client', + clientSecret: 'plainTextSecret', + shouldCloseSession: true, + identityProvider: 'OIDC_EXAMPLE', + openidConfigurationUrl: 'https://oidc.example.net/.well-known/openid-configuration', + organizationName: 'OIDC Example', + redirectUri: 'https://app.dev.pix.org/connexion/oidc-example-net', + scope: 'openid profile', + slug: 'oidc-example-net', + source: 'oidcexamplenet', + }; + await databaseBuilder.factory.buildOidcProvider(genericOidcProviderProperties); + + const genericDisabledOidcProviderProperties = { + enabled: false, + accessTokenLifespan: '7d', + clientId: 'client', + clientSecret: 'plainTextSecret', + shouldCloseSession: true, + identityProvider: 'OIDC_EXAMPLE_DISABLED', + openidConfigurationUrl: 'https://oidc.example.net/.well-known/openid-configuration', + organizationName: 'OIDC Example', + redirectUri: 'https://app.dev.pix.org/connexion/oidc-example-net', + scope: 'openid profile', + slug: 'oidc-example-net', + source: 'oidcexamplenet', + }; + await databaseBuilder.factory.buildOidcProvider(genericDisabledOidcProviderProperties); + + const genericOidcProviderFoxPixAdminProperties = { + enabledForPixAdmin: true, + accessTokenLifespan: '7d', + clientId: 'client', + clientSecret: 'plainTextSecret', + shouldCloseSession: true, + identityProvider: 'OIDC_EXAMPLE_FOR_PIX_ADMIN', + openidConfigurationUrl: 'https://oidc.example.net/.well-known/openid-configuration', + organizationName: 'OIDC Example', + redirectUri: 'https://app.dev.pix.org/connexion/oidc-example-net', + scope: 'openid profile', + slug: 'oidc-example-net', + source: 'oidcexamplenet', + }; + await databaseBuilder.factory.buildOidcProvider(genericOidcProviderFoxPixAdminProperties); + + const poleEmploiOidcProviderProperties = { + additionalRequiredProperties: { + logoutUrl: 'https://example.net', + afterLogoutUrl: 'https://example.net', + sendingUrl: 'https://example.net', + }, + enabled: true, + accessTokenLifespan: '7d', + clientId: 'client', + clientSecret: 'plainTextSecret', + shouldCloseSession: true, + identityProvider: 'POLE_EMPLOI', + openidConfigurationUrl: 'https://oidc.example.net/.well-known/openid-configuration', + organizationName: 'OIDC Example', + redirectUri: 'https://app.dev.pix.org/connexion/oidc-example-net', + scope: 'openid profile', + slug: 'oidc-example-net', + source: 'oidcexamplenet', + }; + await databaseBuilder.factory.buildOidcProvider(poleEmploiOidcProviderProperties); + + const fwbOidcProviderProperties = { + additionalRequiredProperties: { logoutUrl: 'https://example.net' }, + enabled: true, + accessTokenLifespan: '7d', + clientId: 'client', + clientSecret: 'plainTextSecret', + shouldCloseSession: true, + identityProvider: 'FWB', + openidConfigurationUrl: 'https://oidc.example.net/.well-known/openid-configuration', + organizationName: 'OIDC Example', + redirectUri: 'https://app.dev.pix.org/connexion/oidc-example-net', + scope: 'openid profile', + slug: 'oidc-example-net', + source: 'oidcexamplenet', + }; + await databaseBuilder.factory.buildOidcProvider(fwbOidcProviderProperties); + + await databaseBuilder.commit(); + + oidcAuthenticationServiceRegistry = new OidcAuthenticationServiceRegistry({ oidcProviderRepository }); + }); + + describe('#getAllOidcProviderServices', function () { + it('returns all OIDC Providers', async function () { + // given + await oidcAuthenticationServiceRegistry.loadOidcProviderServices(); + + // when + const services = oidcAuthenticationServiceRegistry.getAllOidcProviderServices(); + + // then + const serviceCodes = services.map((service) => service.code); + expect(serviceCodes).to.have.length(5); + expect(serviceCodes).to.contain('OIDC_EXAMPLE'); + expect(serviceCodes).to.contain('OIDC_EXAMPLE_DISABLED'); + expect(serviceCodes).to.contain('OIDC_EXAMPLE_FOR_PIX_ADMIN'); + expect(serviceCodes).to.contain('POLE_EMPLOI'); + expect(serviceCodes).to.contain('FWB'); + }); + }); + + describe('#getReadyOidcProviderServices', function () { + it('returns ready OIDC Providers', async function () { + // given + await oidcAuthenticationServiceRegistry.loadOidcProviderServices(); + + // when + const services = oidcAuthenticationServiceRegistry.getReadyOidcProviderServices(); + + // then + const serviceCodes = services.map((service) => service.code); + expect(serviceCodes.length).to.equal(3); + expect(serviceCodes).to.contain('OIDC_EXAMPLE'); + expect(serviceCodes).to.contain('POLE_EMPLOI'); + expect(serviceCodes).to.contain('FWB'); + }); + }); + + describe('#getReadyOidcProviderServicesForPixAdmin', function () { + it('returns ready OIDC Providers for Pix Admin', async function () { + // given + await oidcAuthenticationServiceRegistry.loadOidcProviderServices(); + + // when + const services = oidcAuthenticationServiceRegistry.getReadyOidcProviderServicesForPixAdmin(); + + // then + const serviceCodes = services.map((service) => service.code); + expect(serviceCodes.length).to.equal(1); + expect(serviceCodes).to.contain('OIDC_EXAMPLE_FOR_PIX_ADMIN'); + }); + }); + + // describe('#getOidcProviderServiceByCode', function () { + // describe('when the audience is admin', function () { + // it('returns a ready OIDC provider for Pix Admin', async function () { + // // given + // const oidcProviderForPixApp = { + // code: 'PROVIDER_FOR_APP', + // isReady: true, + // }; + // const oidcProviderForPixAdmin = { + // code: 'PROVIDER_FOR_ADMIN', + // isReadyForPixAdmin: true, + // }; + + // await oidcAuthenticationServiceRegistry.loadOidcProviderServices([ + // oidcProviderForPixApp, + // oidcProviderForPixAdmin, + // ]); + + // // when + // const service = oidcAuthenticationServiceRegistry.getOidcProviderServiceByCode({ + // identityProviderCode: 'PROVIDER_FOR_ADMIN', + // audience: PIX_ADMIN.AUDIENCE, + // }); + + // // then + // expect(service.code).to.equal('PROVIDER_FOR_ADMIN'); + // }); + // }); + + // describe('when audience is not provided', function () { + // it('returns a ready OIDC Provider for Pix App', async function () { + // // given + // const identityProviderCode = 'FIRST'; + // const firstOidcProviderService = { + // code: identityProviderCode, + // isReady: true, + // }; + // const secondOidcProviderService = { + // code: 'SECOND', + // }; + + // await oidcAuthenticationServiceRegistry.loadOidcProviderServices([ + // firstOidcProviderService, + // secondOidcProviderService, + // ]); + + // // when + // const service = oidcAuthenticationServiceRegistry.getOidcProviderServiceByCode({ identityProviderCode }); + + // // then + // expect(service.code).to.equal('FIRST'); + // }); + // }); + + // it('throws an error when identity provider is not supported', async function () { + // // given + // const identityProviderCode = 'UNSUPPORTED_OIDC_PROVIDER'; + // const firstOidcProviderService = { + // code: 'FIRST', + // isReady: true, + // }; + // const secondOidcProviderService = { + // code: 'SECOND', + // }; + + // await oidcAuthenticationServiceRegistry.loadOidcProviderServices([ + // firstOidcProviderService, + // secondOidcProviderService, + // ]); + + // // when + // const error = catchErrSync( + // oidcAuthenticationServiceRegistry.getOidcProviderServiceByCode, + // oidcAuthenticationServiceRegistry, + // )({ identityProviderCode }); + + // // then + // expect(error).to.be.an.instanceOf(InvalidIdentityProviderError); + // expect(error.message).to.equal(`Identity provider ${identityProviderCode} is not supported.`); + // }); + // }); + + // describe('#loadOidcProviderServices', function () { + // describe('when oidc provider services are already loaded', function () { + // it('returns undefined', async function () { + // // given + // sinon + // .stub(oidcProviderRepository, 'findAllOidcProviders') + // .resolves([{ code: 'ONE' }, { code: 'OIDC' }, { code: 'OIDC_FOR_PIX_ADMIN' }]); + + // const oidcProviderServices = [ + // { code: 'ONE' }, + // { code: 'OIDC', isReady: true }, + // { code: 'OIDC_FOR_PIX_ADMIN', isReadyForPixAdmin: true }, + // ]; + // await oidcAuthenticationServiceRegistry.loadOidcProviderServices(oidcProviderServices); + + // // when + // const result = await oidcAuthenticationServiceRegistry.loadOidcProviderServices(oidcProviderServices); + + // // then + // expect(result).to.be.undefined; + // }); + // }); + + // describe('when oidc provider services are not loaded', function () { + // it('loads all given oidc provider services, filters them and returns true', async function () { + // // given + // const oidcProviderServices = [ + // { code: 'ONE' }, + // { code: 'OIDC', isReady: true }, + // { code: 'OIDC_FOR_PIX_ADMIN', isReadyForPixAdmin: true }, + // ]; + + // // when + // const result = await oidcAuthenticationServiceRegistry.loadOidcProviderServices(oidcProviderServices); + + // // then + // const allOidcProviderServices = oidcAuthenticationServiceRegistry.getAllOidcProviderServices(); + // const readyOidcProviderServices = oidcAuthenticationServiceRegistry.getReadyOidcProviderServices(); + // const readyOidcProviderServicesForPixAdmin = + // oidcAuthenticationServiceRegistry.getReadyOidcProviderServicesForPixAdmin(); + + // expect(result).to.be.true; + // expect(allOidcProviderServices).to.have.lengthOf(3); + + // expect(readyOidcProviderServices).to.have.lengthOf(1); + // expect(readyOidcProviderServices.map((service) => service.code)).to.contain('OIDC'); + + // expect(readyOidcProviderServicesForPixAdmin).to.have.lengthOf(1); + // expect(readyOidcProviderServicesForPixAdmin.map((service) => service.code)).to.contain('OIDC_FOR_PIX_ADMIN'); + // }); + // }); + + // describe('when oidc provider services loads providers', function () { + // it('instantciates the correct OIDC authentication services', async function () { + // // given + // sinon + // .stub(oidcProviderRepository, 'findAllOidcProviders') + // .resolves([ + // new OidcProvider({ identityProvider: 'GENERIC' }), + // new OidcProvider({ identityProvider: 'FWB' }), + // new OidcProvider({ identityProvider: 'POLE_EMPLOI' }), + // ]); + + // // when + // await oidcAuthenticationServiceRegistry.loadOidcProviderServices(); + // const services = oidcAuthenticationServiceRegistry.getAllOidcProviderServices(); + + // // then + // expect(services).to.have.length(3); + + // const genericService = services.find((service) => service.identityProvider === 'GENERIC'); + // expect(genericService).not.to.be.empty; + // expect(genericService).to.be.instanceOf(OidcAuthenticationService); + + // const fwbService = services.find((service) => service.identityProvider === 'FWB'); + // expect(fwbService).not.to.be.empty; + // expect(fwbService).to.be.instanceOf(FwbOidcAuthenticationService); + + // const poleEmploiService = services.find((service) => service.identityProvider === 'POLE_EMPLOI'); + // expect(poleEmploiService).not.to.be.empty; + // expect(poleEmploiService).to.be.instanceOf(PoleEmploiOidcAuthenticationService); + // }); + // }); + // }); + + // describe('#configureReadyOidcProviderServiceByCode', function () { + // context('when oidc provider service does not exist', function () { + // it('returns undefined', async function () { + // // when + // const result = await oidcAuthenticationServiceRegistry.configureReadyOidcProviderServiceByCode('OIDC'); + + // // then + // expect(result).to.be.undefined; + // }); + // }); + + // context('when oidc provider service exists and loaded', function () { + // it('configures openid client for ready oidc provider service and returns true', async function () { + // // given + // const createClient = sinon.stub().resolves(); + // const oidcProviderServices = [ + // { + // code: 'OIDC', + // isReady: true, + // createClient, + // }, + // ]; + // await oidcAuthenticationServiceRegistry.loadOidcProviderServices(oidcProviderServices); + + // // when + // const result = await oidcAuthenticationServiceRegistry.configureReadyOidcProviderServiceByCode( + // oidcProviderServices[0].code, + // ); + + // // then + // expect(result).to.be.true; + // expect(createClient).to.have.been.calledOnce; + // }); + + // context('when there is already a client instantiated', function () { + // it('returns undefined', async function () { + // // given + // const oidcProviderServices = [ + // { + // code: 'OIDC', + // isReady: true, + // client: {}, + // }, + // ]; + // await oidcAuthenticationServiceRegistry.loadOidcProviderServices(oidcProviderServices); + + // // when + // const result = await oidcAuthenticationServiceRegistry.configureReadyOidcProviderServiceByCode('OIDC'); + + // // then + // expect(result).to.be.undefined; + // }); + // }); + // }); + // }); +});