Skip to content

Commit

Permalink
refactor(api): fix unit tests for oidc-authentication-service
Browse files Browse the repository at this point in the history
  • Loading branch information
bpetetot committed Mar 6, 2025
1 parent bddfb4a commit 75c8aef
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ const defaultSessionTemporaryStorage = temporaryStorage.withPrefix('oidc-session
export class OidcAuthenticationService {
#isReady = false;
#isReadyForPixAdmin = false;
#oidcClientConfig = null;
#openIdClient;
#oidcClientConfig; // TODO: À modifier en openIdClientConfig

constructor(
{
Expand All @@ -55,7 +56,7 @@ export class OidcAuthenticationService {
isVisible = true,
claimMapping,
},
{ sessionTemporaryStorage = defaultSessionTemporaryStorage } = {},
{ sessionTemporaryStorage = defaultSessionTemporaryStorage, openIdClient = client } = {},
) {
this.accessTokenLifespanMs = ms(accessTokenLifespan);
this.additionalRequiredProperties = additionalRequiredProperties;
Expand All @@ -76,6 +77,7 @@ export class OidcAuthenticationService {
this.slug = slug;
this.source = source;
this.isVisible = isVisible;
this.#openIdClient = openIdClient;

claimMapping = claimMapping || DEFAULT_CLAIM_MAPPING;

Expand Down Expand Up @@ -125,7 +127,7 @@ export class OidcAuthenticationService {
...this.openidClientExtraMetadata,
};

this.#oidcClientConfig = await client.discovery(this.openidConfigurationUrl, this.clientId, metadata);
this.#oidcClientConfig = await this.#openIdClient.discovery(this.openidConfigurationUrl, this.clientId, metadata);
} catch (error) {
logger.error(`OIDC Provider "${this.identityProvider}" is UNAVAILABLE: ${error}`);
}
Expand Down Expand Up @@ -158,7 +160,7 @@ export class OidcAuthenticationService {
const checks = { nonce, state: sessionState };
const tokenEndpointParameters = { code, state, iss };

tokenSet = await client.authorizationCodeGrant(
tokenSet = await this.#openIdClient.authorizationCodeGrant(
this.#oidcClientConfig,
this.redirectUri,
checks,
Expand Down Expand Up @@ -190,7 +192,7 @@ export class OidcAuthenticationService {

getAuthorizationUrl() {
const state = randomUUID();
const nonce = randomUUID(); // TODO: client.randomNonce() ?
const nonce = randomUUID(); // TODO: this.#openIdClient.randomNonce() ?

let redirectTarget;

Expand All @@ -203,7 +205,7 @@ export class OidcAuthenticationService {
...this.extraAuthorizationUrlParameters,
};

redirectTarget = client.buildAuthorizationUrl(this.#oidcClientConfig, parameters);
redirectTarget = this.#openIdClient.buildAuthorizationUrl(this.#oidcClientConfig, parameters);
} catch (error) {
_monitorOidcError(error.message, {
data: { organizationName: this.organizationName },
Expand Down Expand Up @@ -273,7 +275,7 @@ export class OidcAuthenticationService {
}

try {
const endSessionUrl = client.buildEndSessionUrl(this.#oidcClientConfig, parameters);
const endSessionUrl = this.#openIdClient.buildEndSessionUrl(this.#oidcClientConfig, parameters);

await this.sessionTemporaryStorage.delete(key);

Expand All @@ -292,11 +294,7 @@ export class OidcAuthenticationService {
let userInfo;

try {
userInfo = await client.fetchUserInfo(
this.#oidcClientConfig,
accessToken,
expectedSubject || client.skipSubjectCheck,
);
userInfo = await this.#openIdClient.fetchUserInfo(this.#oidcClientConfig, accessToken, expectedSubject);
} catch (error) {
_monitorOidcError(error.message, {
data: { organizationName: this.organizationName },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import jsonwebtoken from 'jsonwebtoken';
import ms from 'ms';
import { Issuer } from 'openid-client';

import { OidcAuthenticationService } from '../../../../../src/identity-access-management/domain/services/oidc-authentication-service.js';
import { config as settings } from '../../../../../src/shared/config.js';
Expand All @@ -17,8 +16,19 @@ import { catchErr, catchErrSync, expect, sinon } from '../../../../test-helper.j

const uuidV4Regex = /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i;

const MOCK_OPENID_CLIENT_CONFIG = Symbol('config');

describe('Unit | Domain | Services | oidc-authentication-service', function () {
let openIdClient;

beforeEach(function () {
openIdClient = {
discovery: sinon.stub().resolves(MOCK_OPENID_CLIENT_CONFIG),
authorizationCodeGrant: sinon.stub(),
buildAuthorizationUrl: sinon.stub(),
buildEndSessionUrl: sinon.stub(),
fetchUserInfo: sinon.stub(),
};
sinon.stub(monitoringTools, 'logErrorWithCorrelationIds');
});

Expand Down Expand Up @@ -211,21 +221,19 @@ describe('Unit | Domain | Services | oidc-authentication-service', function () {
};
const postLogoutRedirectUriEncoded = encodeURIComponent(settings.oidcExampleNet.postLogoutRedirectUri);
const endSessionUrl = `https://example.net/logout?post_logout_redirect_uri=${postLogoutRedirectUriEncoded}&id_token_hint=some_dummy_id_token`;
const clientInstance = { endSessionUrl: sinon.stub().resolves(endSessionUrl) };
const Client = sinon.stub().returns(clientInstance);

sinon.stub(Issuer, 'discover').resolves({ Client });
openIdClient.buildEndSessionUrl.resolves(endSessionUrl);

const oidcAuthenticationService = new OidcAuthenticationService(settings.oidcExampleNet, {
sessionTemporaryStorage,
openIdClient,
});
await oidcAuthenticationService.initializeClientConfig();

// when
const result = await oidcAuthenticationService.getRedirectLogoutUrl({ userId, logoutUrlUUID });

// then
expect(clientInstance.endSessionUrl).to.have.been.calledWith({
expect(openIdClient.buildEndSessionUrl).to.have.been.calledWith(MOCK_OPENID_CLIENT_CONFIG, {
id_token_hint: idToken,
post_logout_redirect_uri: settings.oidcExampleNet.postLogoutRedirectUri,
});
Expand All @@ -246,13 +254,9 @@ describe('Unit | Domain | Services | oidc-authentication-service', function () {
};
const errorThrown = new Error('Fails to generate endSessionUrl');

const clientInstance = { endSessionUrl: sinon.stub().throws(errorThrown) };
const Client = sinon.stub().returns(clientInstance);

sinon.stub(Issuer, 'discover').resolves({ Client });

const oidcAuthenticationService = new OidcAuthenticationService(settings.oidcExampleNet, {
sessionTemporaryStorage,
openIdClient,
});
await oidcAuthenticationService.initializeClientConfig();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Issuer } from 'openid-client';
import * as client from 'openid-client';

import { AuthenticationMethod } from '../../../../../src/identity-access-management/domain/models/AuthenticationMethod.js';
import { PoleEmploiOidcAuthenticationService } from '../../../../../src/identity-access-management/domain/services/pole-emploi-oidc-authentication-service.js';
Expand Down Expand Up @@ -29,9 +29,7 @@ describe('Unit | Identity Access Management | Domain | Services | pole-emploi-oi
describe('#initializeClientConfig', function () {
it('creates an openid client config with extra metadata', async function () {
// given
const Client = sinon.spy();

sinon.stub(Issuer, 'discover').resolves({ Client });
sinon.stub(client, 'discovery').resolves();
sinon.stub(settings, 'poleEmploi').value(settings.oidcExampleNet);

const poleEmploiOidcAuthenticationService = new PoleEmploiOidcAuthenticationService({
Expand All @@ -49,16 +47,15 @@ describe('Unit | Identity Access Management | Domain | Services | pole-emploi-oi
await poleEmploiOidcAuthenticationService.initializeClientConfig();

// then
expect(Issuer.discover).to.have.been.calledWithExactly(
expect(client.discovery).to.have.been.calledWithExactly(
'https://oidc.example.net/.well-known/openid-configuration',
'client',
{
client_secret: 'secret',
redirect_uris: ['https://app.dev.pix.local/connexion/oidc-example-net'],
token_endpoint_auth_method: 'client_secret_post',
},
);
expect(Client).to.have.been.calledWithNew;
expect(Client).to.have.been.calledWithExactly({
client_id: 'client',
client_secret: 'secret',
redirect_uris: ['https://app.dev.pix.local/connexion/oidc-example-net'],
token_endpoint_auth_method: 'client_secret_post',
});
});
});

Expand Down

0 comments on commit 75c8aef

Please sign in to comment.