Skip to content

Commit

Permalink
Merge branch 'jul/stop-oidc-verification-method-provider-id-usage' in…
Browse files Browse the repository at this point in the history
…to 'master'

test(oidc): add oidc_provider_group tests

See merge request TankerHQ/sdk-js!1029
  • Loading branch information
JMounier committed Aug 7, 2024
2 parents dceb38f + 26a06f9 commit c4499e2
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 22 deletions.
26 changes: 20 additions & 6 deletions packages/functional-tests/src/helpers/AppHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export const provisionalUserTypes = {

export type ProvisionalUserType = number;

type KnownProvider = 'google' | 'pro-sante-bas' | 'pro-sante-bas-no-expiry' | 'fake-oidc' | 'fake-oidc/alt' | 'fake-oidc/wrong';
export class AppHelper {
makeTanker: TankerFactory;
appId: Uint8Array;
Expand Down Expand Up @@ -54,28 +55,41 @@ export class AppHelper {
});
}

async setOidc(provider: 'google' | 'pro-sante-bas' | 'pro-sante-bas-no-expiry' | 'fake-oidc' = 'google', oidc_provider_group_id: string = 'AYBa9RHeILz7WKXm4DL3pmVufbP2-ihlKBl9c0hgHVk') {
const providers = {

async setOidc(providers: Array<KnownProvider> = ['google']) {
const providersClientId = {
google: oidcSettings.googleAuth.clientId,
'pro-sante-bas': 'doctolib-dev',
'pro-sante-bas-no-expiry': 'doctolib-dev',
'fake-oidc': 'tanker',
'fake-oidc/alt': 'tanker',
'fake-oidc/wrong': 'tanker',
};
const providersIssuer = {
google: 'https://accounts.google.com',
'pro-sante-bas': 'https://auth.bas.psc.esante.gouv.fr/auth/realms/esante-wallet',
'pro-sante-bas-no-expiry': 'https://auth.bas.psc.esante.gouv.fr/auth/realms/esante-wallet',
'fake-oidc': `${oidcSettings.fakeOidc.url}/issuers/main`,
'fake-oidc/alt': `${oidcSettings.fakeOidc.url}/issuers/alt`,
'fake-oidc/wrong': `${oidcSettings.fakeOidc.url}/issuers/wrong-group`,
};
const providersGroup = {
google: 'AYBa9RHeILz7WKXm4DL3pmVufbP2-ihlKBl9c0hgHVk',
'pro-sante-bas': 'bBrMrmc71WMdcaoKPSZtqTvCad4YXt1fCAUCW3nT7dI',
'pro-sante-bas-no-expiry': 'bBrMrmc71WMdcaoKPSZtqTvCad4YXt1fCAUCW3nT7dI',
'fake-oidc': 'GodwrLmwsALA0Nuu2lHalxksaDdnhXXZCDpjE8pmNbM',
'fake-oidc/alt': 'GodwrLmwsALA0Nuu2lHalxksaDdnhXXZCDpjE8pmNbM',
'fake-oidc/wrong': 'a0Ce8E1LQvs7CHdNu7-Rpk_5L8qAzORUqNpp3q9Itog',
};

return this._update({
oidc_providers: [{
oidc_providers: providers.map((provider) => ({
display_name: provider,
issuer: providersIssuer[provider],
client_id: providers[provider],
oidc_provider_group_id,
client_id: providersClientId[provider],
oidc_provider_group_id: providersGroup[provider],
ignore_token_expiration: provider === 'pro-sante-bas-no-expiry',
}],
})),
}) as Promise<{ app: { oidc_providers: Array<{ id: string, display_name: string }> } }>;
}

Expand Down
72 changes: 56 additions & 16 deletions packages/functional-tests/src/verification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -710,10 +710,14 @@ export const generateVerificationTests = (args: TestArgs) => {
let martineIdToken: string;
let subject: string;
let provider: { id:string, display_name: string };
let fakeOidcMain: { id:string, display_name: string };
let fakeOidcAlt: { id:string, display_name: string };

before(async () => {
const config = await appHelper.setOidc();
provider = config.app.oidc_providers[0]!;
const config = await appHelper.setOidc(['google', 'fake-oidc', 'fake-oidc/alt']);
provider = config.app.oidc_providers.find((pro) => pro.display_name === 'google')!;
fakeOidcMain = config.app.oidc_providers.find((pro) => pro.display_name === 'fake-oidc')!;
fakeOidcAlt = config.app.oidc_providers.find((pro) => pro.display_name === 'fake-oidc/alt')!;

martineIdToken = await getGoogleIdToken(martineRefreshToken);
subject = extractSubject(martineIdToken);
Expand Down Expand Up @@ -749,6 +753,19 @@ export const generateVerificationTests = (args: TestArgs) => {
await bobPhone.setOidcTestNonce(await bobPhone.createOidcNonce());
await bobPhone.verifyIdentity({ oidcIdToken: martineIdToken });
});

it('sets a verification method for every oidc provider from the same oidc provider group at once', async () => {
const email = await appHelper.generateRandomEmail();
let verificationCode = await appHelper.getEmailVerificationCode(email);
await bobLaptop.registerIdentity({ email, verificationCode });

await bobLaptop.setVerificationMethod({ preverifiedOidcSubject: subject, oidcProviderId: fakeOidcMain.id });
expect(await bobLaptop.getVerificationMethods()).to.have.deep.members([
{ type: 'email', email },
{ type: 'oidcIdToken', providerId: fakeOidcMain.id, providerDisplayName: fakeOidcMain.display_name },
{ type: 'oidcIdToken', providerId: fakeOidcAlt.id, providerDisplayName: fakeOidcAlt.display_name },
]);
});
});

describe('verification by oidc id token', () => {
Expand Down Expand Up @@ -874,15 +891,15 @@ export const generateVerificationTests = (args: TestArgs) => {
});

it('rejects expired token on pro-sante-bas', async () => {
await appHelper.setOidc('pro-sante-bas');
await appHelper.setOidc(['pro-sante-bas']);

const nonce = await bobLaptop.createOidcNonce();
await bobLaptop.setOidcTestNonce(nonce);
await expect(bobLaptop.registerIdentity({ oidcIdToken: pscIdToken })).to.be.rejectedWith(errors.InvalidVerification);
});

it('accepts expired token on pro-sante-bas-no-expiry', async () => {
await appHelper.setOidc('pro-sante-bas-no-expiry');
await appHelper.setOidc(['pro-sante-bas-no-expiry']);

const nonce = await bobLaptop.createOidcNonce();
await bobLaptop.setOidcTestNonce(nonce);
Expand All @@ -899,7 +916,7 @@ export const generateVerificationTests = (args: TestArgs) => {

describe('authenticateWithIdP', () => {
it('is restricted to trusted OIDC providers', async () => {
const config = await appHelper.setOidc('google');
const config = await appHelper.setOidc(['google']);
const provider = config.app.oidc_providers[0]!;

await expect(authenticateWithIdP(bobLaptop, provider.id)).to.be.rejectedWith(errors.PreconditionFailed);
Expand All @@ -908,28 +925,33 @@ export const generateVerificationTests = (args: TestArgs) => {

if (isBrowser()) {
describe('verification by oidc authorization code', () => {
let provider: { id: string, display_name: string };
let fakeOIDCMain: { id: string, display_name: string };
let fakeOIDCAlt: { id: string, display_name: string };
let fakeOIDCWrongGroup: { id: string, display_name: string };

const setFakeOidcSubjectCookie = async (subject: string) => fetch(`${oidcSettings.fakeOidc.url}/issuers/main/subject`, {
const setFakeOidcSubjectCookie = async (subject: string, provider: 'main' | 'alt' | 'wrong-group' = 'main') => fetch(`${oidcSettings.fakeOidc.url}/issuers/${provider}/subject`, {
method: 'POST',
body: JSON.stringify({ subject }),
credentials: 'include',
});

before(async () => {
const config = await appHelper.setOidc('fake-oidc');
provider = config.app.oidc_providers[0]!;
const config = await appHelper.setOidc(['fake-oidc', 'fake-oidc/alt', 'fake-oidc/wrong']);
fakeOIDCMain = config.app.oidc_providers.find((provider) => provider.display_name === 'fake-oidc')!;
fakeOIDCAlt = config.app.oidc_providers.find((provider) => provider.display_name === 'fake-oidc/alt')!;
fakeOIDCWrongGroup = config.app.oidc_providers.find((provider) => provider.display_name === 'fake-oidc/wrong')!;
});

after(async () => {
appHelper.unsetOidc();
});


it('registers and verifies with an oidc authorization code', async () => {
await setFakeOidcSubjectCookie('bob');

const verification1 = await authenticateWithIdP(bobLaptop, provider.id);
const verification2 = await authenticateWithIdP(bobLaptop, provider.id);
const verification1 = await authenticateWithIdP(bobLaptop, fakeOIDCMain.id);
const verification2 = await authenticateWithIdP(bobLaptop, fakeOIDCMain.id);
await expect(bobLaptop.registerIdentity(verification1)).to.be.fulfilled;

await bobPhone.start(bobIdentity);
Expand All @@ -941,7 +963,7 @@ export const generateVerificationTests = (args: TestArgs) => {
it('fails to verify an oidc authorization code twice', async () => {
await setFakeOidcSubjectCookie('bob');

const verification1 = await authenticateWithIdP(bobLaptop, provider.id);
const verification1 = await authenticateWithIdP(bobLaptop, fakeOIDCMain.id);
await expect(bobLaptop.registerIdentity(verification1)).to.be.fulfilled;

await bobPhone.start(bobIdentity);
Expand All @@ -952,11 +974,11 @@ export const generateVerificationTests = (args: TestArgs) => {
it('fails to verify an oidc authorization code for the wrong user', async () => {
await setFakeOidcSubjectCookie('bob');

const verification1 = await authenticateWithIdP(bobLaptop, provider.id);
const verification1 = await authenticateWithIdP(bobLaptop, fakeOIDCMain.id);
await expect(bobLaptop.registerIdentity(verification1)).to.be.fulfilled;

await setFakeOidcSubjectCookie('alice');
const verification2 = await authenticateWithIdP(bobLaptop, provider.id);
const verification2 = await authenticateWithIdP(bobLaptop, fakeOIDCMain.id);
await bobPhone.start(bobIdentity);
expect(bobPhone.status).to.equal(IDENTITY_VERIFICATION_NEEDED);
await expect(bobPhone.verifyIdentity(verification2)).to.be.rejectedWith(errors.InvalidVerification);
Expand All @@ -965,18 +987,36 @@ export const generateVerificationTests = (args: TestArgs) => {
it('updates and verifies with an oidc authorization code', async () => {
await expect(bobLaptop.registerIdentity({ passphrase: 'plain old passphrase' })).to.be.fulfilled;
await expect(bobLaptop.setVerificationMethod({
oidcProviderId: provider.id,
oidcProviderId: fakeOIDCMain.id,
preverifiedOidcSubject: 'bob',
})).to.be.fulfilled;

await bobPhone.start(bobIdentity);
expect(bobPhone.status).to.equal(IDENTITY_VERIFICATION_NEEDED);

await setFakeOidcSubjectCookie('bob');
const verification = await authenticateWithIdP(bobPhone, provider.id);
const verification = await authenticateWithIdP(bobPhone, fakeOIDCMain.id);
await expect(bobPhone.verifyIdentity(verification)).to.be.fulfilled;
expect(bobPhone.status).to.equal(READY);
});

it('registers and verifies with different oidc providers from the same provider group', async () => {
await setFakeOidcSubjectCookie('bob', 'main');
await setFakeOidcSubjectCookie('bob', 'alt');
await setFakeOidcSubjectCookie('bob', 'wrong-group');

const verification1 = await authenticateWithIdP(bobLaptop, fakeOIDCMain.id);
const verification2 = await authenticateWithIdP(bobLaptop, fakeOIDCWrongGroup.id);
const verification3 = await authenticateWithIdP(bobLaptop, fakeOIDCAlt.id);

await expect(bobLaptop.registerIdentity(verification1)).to.be.fulfilled;

await bobPhone.start(bobIdentity);
expect(bobPhone.status).to.equal(IDENTITY_VERIFICATION_NEEDED);
await expect(bobPhone.verifyIdentity(verification2)).to.be.rejectedWith(errors.PreconditionFailed);
await expect(bobPhone.verifyIdentity(verification3)).to.be.fulfilled;
expect(bobPhone.status).to.equal(READY);
});
});
}

Expand Down

0 comments on commit c4499e2

Please sign in to comment.