Skip to content

Commit

Permalink
runfix: fresh client snoozable after oidc failure [WPB-8878] (#17407)
Browse files Browse the repository at this point in the history
* runfix: fresh client snoozable after oidc failure

* test: enrollment error with and without snooze option

* docs: add comment to snooze param when client is fresh
  • Loading branch information
PatrykBuniX authored May 15, 2024
1 parent 2625382 commit 1588a84
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 2 deletions.
79 changes: 79 additions & 0 deletions src/script/E2EIdentity/E2EIdentityEnrollment.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,85 @@ describe('E2EIHandler', () => {
return enrollPromise;
});

it('shows the error modal without the snooze option after enrollment failed and the client is fresh', async () => {
jest.spyOn(coreMock.service!.e2eIdentity!, 'isFreshMLSSelfClient').mockResolvedValue(true);
jest.spyOn(coreMock.service!.e2eIdentity!, 'isEnrollmentInProgress').mockResolvedValue(true);
jest.spyOn(coreMock, 'enrollE2EI').mockRejectedValue(new Error('OIDC Error'));

const handler = E2EIHandler.getInstance();

// mock window search params (code, session_state, state)
const searchParams = new URLSearchParams();
searchParams.append('code', 'CODE');
searchParams.append('session_state', 'SESSION_STATE');
searchParams.append('state', 'STATE');

Object.defineProperty(window, 'location', {
value: {
search: searchParams.toString(),
},
writable: true,
});

const enrollPromise = handler.initialize(params);

await waitFor(() => {
expect(modalMock).toHaveBeenCalledWith(
PrimaryModalType.ACKNOWLEDGE,
expect.objectContaining({text: expect.objectContaining({title: 'acme.error.headline'})}),
);
expect(modalMock).not.toHaveBeenCalledWith(
PrimaryModalType.CONFIRM,
expect.objectContaining({secondaryAction: expect.objectContaining({text: 'acme.error.button.secondary'})}),
);
});

jest.spyOn(handler, 'enroll').mockImplementation(() => Promise.resolve());

modalMock.mock.lastCall?.[1].primaryAction?.action?.();

return enrollPromise;
});

it('shows the error modal with the snooze option after enrollment failed and the client is an e2ei client already', async () => {
jest.spyOn(coreMock.service!.e2eIdentity!, 'isFreshMLSSelfClient').mockResolvedValue(false);
jest.spyOn(coreMock.service!.e2eIdentity!, 'isEnrollmentInProgress').mockResolvedValue(true);
jest.spyOn(coreMock, 'enrollE2EI').mockRejectedValue(new Error('OIDC Error'));

const handler = E2EIHandler.getInstance();

// mock window search params (code, session_state, state)
const searchParams = new URLSearchParams();
searchParams.append('code', 'CODE');
searchParams.append('session_state', 'SESSION_STATE');
searchParams.append('state', 'STATE');

Object.defineProperty(window, 'location', {
value: {
search: searchParams.toString(),
},
writable: true,
});

const enrollPromise = handler.initialize(params);

await waitFor(() => {
expect(modalMock).toHaveBeenCalledWith(
PrimaryModalType.CONFIRM,
expect.objectContaining({
text: expect.objectContaining({title: 'acme.error.headline'}),
secondaryAction: expect.objectContaining({text: 'acme.error.button.secondary'}),
}),
);
});

jest.spyOn(handler, 'enroll').mockImplementation(() => Promise.resolve());

modalMock.mock.lastCall?.[1].primaryAction?.action?.();

return enrollPromise;
});

it('registers a renew timer when device is enrolled', async () => {
const conversationState = container.resolve(ConversationState);
jest.spyOn(conversationState, 'getSelfMLSConversation').mockReturnValue(new Conversation() as any);
Expand Down
7 changes: 5 additions & 2 deletions src/script/E2EIdentity/E2EIdentityEnrollment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,16 +142,19 @@ export class E2EIHandler extends TypedEventEmitter<Events> {

await this.coreE2EIService.initialize(discoveryUrl);

const isFreshClient = await isFreshMLSSelfClient();

if (await this.coreE2EIService.isEnrollmentInProgress()) {
// If we have an enrollment in progress, we can just finish it (meaning we are coming back from an idp redirect)
if (this.wasJustRedirected()) {
await this.enroll();
// We should not allow to snooze the enorollment if the client is still fresh and the user is coming back from an idp redirect
await this.enroll(!isFreshClient);
} else {
// If we have an enrollment in progress but we are not coming back from an idp redirect, we need to clear the progress and start over
await this.coreE2EIService.clearAllProgress();
await this.startEnrollment(ModalType.ENROLL, false);
}
} else if (await isFreshMLSSelfClient()) {
} else if (isFreshClient) {
// When the user logs in to a new device in an environment that has e2ei enabled, they should be forced to enroll
await this.startEnrollment(ModalType.ENROLL, false);
}
Expand Down

0 comments on commit 1588a84

Please sign in to comment.