Skip to content

Commit

Permalink
Refactor useReauthenticate and Reauthenticate component.
Browse files Browse the repository at this point in the history
  • Loading branch information
Joerger committed Dec 5, 2024
1 parent 1babeb9 commit 56c0d8c
Show file tree
Hide file tree
Showing 15 changed files with 439 additions and 472 deletions.
21 changes: 12 additions & 9 deletions web/packages/teleport/src/Account/Account.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ import cfg from 'teleport/config';
import { createTeleportContext } from 'teleport/mocks/contexts';
import { PasswordState } from 'teleport/services/user';
import auth from 'teleport/services/auth/auth';
import MfaService, { MfaDevice } from 'teleport/services/mfa';
import MfaService, {
MfaDevice,
WebauthnAssertionResponse,
} from 'teleport/services/mfa';

const defaultAuthType = cfg.auth.second_factor;
const defaultPasswordless = cfg.auth.allowPasswordless;
Expand Down Expand Up @@ -244,7 +247,7 @@ test('adding an MFA device', async () => {
const ctx = createTeleportContext();
jest.spyOn(ctx.mfaService, 'fetchDevices').mockResolvedValue([testPasskey]);
jest.spyOn(auth, 'getMfaChallenge').mockResolvedValue({
webauthnPublicKey: null,
webauthnPublicKey: {} as PublicKeyCredentialRequestOptions,
totpChallenge: true,
ssoChallenge: null,
});
Expand All @@ -255,8 +258,8 @@ test('adding an MFA device', async () => {
.spyOn(MfaService.prototype, 'saveNewWebAuthnDevice')
.mockResolvedValueOnce(undefined);
jest
.spyOn(auth, 'createPrivilegeTokenWithWebauthn')
.mockResolvedValueOnce('webauthn-privilege-token');
.spyOn(auth, 'createPrivilegeToken')
.mockResolvedValueOnce('privilege-token');
cfg.auth.second_factor = 'on';

await renderComponent(ctx);
Expand All @@ -276,7 +279,7 @@ test('adding an MFA device', async () => {
addRequest: {
deviceName: 'new-mfa',
deviceUsage: 'mfa',
tokenId: 'webauthn-privilege-token',
tokenId: 'privilege-token',
},
});
expect(
Expand All @@ -296,7 +299,7 @@ test('adding a passkey', async () => {
.mockResolvedValueOnce(undefined);
jest
.spyOn(auth, 'createPrivilegeTokenWithWebauthn')
.mockResolvedValueOnce('webauthn-privilege-token');
.mockResolvedValueOnce('privilege-token');
cfg.auth.second_factor = 'on';
cfg.auth.allowPasswordless = true;

Expand All @@ -315,7 +318,7 @@ test('adding a passkey', async () => {
addRequest: {
deviceName: 'new-passkey',
deviceUsage: 'passwordless',
tokenId: 'webauthn-privilege-token',
tokenId: 'privilege-token',
},
});
expect(
Expand All @@ -334,7 +337,7 @@ test('removing an MFA method', async () => {
});
jest
.spyOn(auth, 'createPrivilegeTokenWithWebauthn')
.mockResolvedValueOnce('webauthn-privilege-token');
.mockResolvedValueOnce('privilege-token');
jest
.spyOn(MfaService.prototype, 'removeDevice')
.mockResolvedValueOnce(undefined);
Expand All @@ -352,7 +355,7 @@ test('removing an MFA method', async () => {
await user.click(deleteStep.getByRole('button', { name: 'Delete' }));

expect(ctx.mfaService.removeDevice).toHaveBeenCalledWith(
'webauthn-privilege-token',
'privilege-token',
'touch_id'
);
expect(screen.queryByTestId('delete-step')).not.toBeInTheDocument();
Expand Down
3 changes: 0 additions & 3 deletions web/packages/teleport/src/Account/Account.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -279,16 +279,13 @@ export function Account({
usage={newDeviceUsage}
auth2faType={cfg.getAuth2faType()}
privilegeToken={token}
devices={devices}
onClose={closeAddDeviceWizard}
onSuccess={onAddDeviceSuccess}
/>
)}

{deviceToRemove && (
<DeleteAuthDeviceWizard
auth2faType={cfg.getAuth2faType()}
devices={devices}
deviceToDelete={deviceToRemove}
onClose={hideRemoveDevice}
onSuccess={onDeleteDeviceSuccess}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@

import React from 'react';

import { Auth2faType } from 'shared/services';

import Dialog from 'design/Dialog';

import { http, HttpResponse, delay } from 'msw';
Expand All @@ -29,14 +27,21 @@ import { ContextProvider } from 'teleport/index';

import cfg from 'teleport/config';

import { DeviceUsage } from 'teleport/services/mfa';
import {
DeviceType,
DeviceUsage,
MFA_OPTION_SSO_DEFAULT,
MFA_OPTION_TOTP,
MFA_OPTION_WEBAUTHN,
} from 'teleport/services/mfa';

import {
AddAuthDeviceWizardStepProps,
CreateDeviceStep,
SaveDeviceStep,
} from './AddAuthDeviceWizard';
import { ReauthenticateStep } from './ReauthenticateStep';
import { Attempt } from 'shared/hooks/useAttemptNext';

export default {
title: 'teleport/Account/Manage Devices/Add Device Wizard',
Expand All @@ -62,25 +67,11 @@ export function ReauthenticateLimitedOptions() {
return (
<ReauthenticateStep
{...stepProps}
devices={[
{
id: '1',
description: 'Authenticator App',
name: 'gizmo',
registeredDate: new Date(1628799417000),
lastUsedDate: new Date(1628799417000),
type: 'totp',
usage: 'mfa',
},
]}
mfaChallengeOptions={[{ value: 'totp', label: 'Authenticator App' }]}
/>
);
}

export function ReauthenticateNoOptions() {
return <ReauthenticateStep {...stepProps} devices={[]} />;
}

export function CreatePasskey() {
return <CreateDeviceStep {...stepProps} usage="passwordless" />;
}
Expand All @@ -92,7 +83,9 @@ export function CreateMfaHardwareDevice() {
}

export function CreateMfaAppQrCodeLoading() {
return <CreateDeviceStep {...stepProps} usage="mfa" newMfaDeviceType="otp" />;
return (
<CreateDeviceStep {...stepProps} usage="mfa" newMfaDeviceType="totp" />
);
}
CreateMfaAppQrCodeLoading.parameters = {
msw: {
Expand All @@ -105,10 +98,12 @@ CreateMfaAppQrCodeLoading.parameters = {
},
};

export function CreateMfaAppQrCodeFailed() {
return <CreateDeviceStep {...stepProps} usage="mfa" newMfaDeviceType="otp" />;
export function CreateAuthenticatorAppQrCodeFailed() {
return (
<CreateDeviceStep {...stepProps} usage="mfa" newMfaDeviceType="totp" />
);
}
CreateMfaAppQrCodeFailed.parameters = {
CreateAuthenticatorAppQrCodeFailed.parameters = {
msw: {
handlers: [
http.post(
Expand All @@ -128,10 +123,12 @@ CreateMfaAppQrCodeFailed.parameters = {
const dummyQrCode =
'iVBORw0KGgoAAAANSUhEUgAAAB0AAAAdAQMAAABsXfVMAAAABlBMVEUAAAD///+l2Z/dAAAAAnRSTlP//8i138cAAAAJcEhZcwAACxIAAAsSAdLdfvwAAABrSURBVAiZY/gPBAxoxAcxh3qG71fv1zN8iQ8EEReBRACQ+H4ZKPZBFCj7/3v9f4aPU9vqGX4kFtUzfG5mBLK2aNUz/PM3AsmqAk2RNQTquLYLqDdG/z/QlGAgES4CFLu4GygrXF2Pbi+IAADZqFQFAjXZWgAAAABJRU5ErkJggg==';

export function CreateMfaApp() {
return <CreateDeviceStep {...stepProps} usage="mfa" newMfaDeviceType="otp" />;
export function CreateAuthenticatorApp() {
return (
<CreateDeviceStep {...stepProps} usage="mfa" newMfaDeviceType="totp" />
);
}
CreateMfaApp.parameters = {
CreateAuthenticatorApp.parameters = {
msw: {
handlers: [
http.post(
Expand All @@ -153,7 +150,7 @@ export function SaveMfaHardwareDevice() {
}

export function SaveMfaAuthenticatorApp() {
return <SaveDeviceStep {...stepProps} usage="mfa" newMfaDeviceType="otp" />;
return <SaveDeviceStep {...stepProps} usage="mfa" newMfaDeviceType="totp" />;
}

const stepProps: AddAuthDeviceWizardStepProps = {
Expand All @@ -165,35 +162,28 @@ const stepProps: AddAuthDeviceWizardStepProps = {
flowLength: 1,
refCallback: () => {},

// Other props
// Shared props
privilegeToken: 'privilege-token',
usage: 'passwordless' as DeviceUsage,
auth2faType: 'on' as Auth2faType,
credential: { id: 'cred-id', type: 'public-key' },
newMfaDeviceType: 'webauthn' as Auth2faType,
devices: [
{
id: '1',
description: 'Authenticator App',
name: 'gizmo',
registeredDate: new Date(1628799417000),
lastUsedDate: new Date(1628799417000),
type: 'totp',
usage: 'mfa',
},
{
id: '2',
description: 'Hardware Key',
name: 'key',
registeredDate: new Date(1623722252000),
lastUsedDate: new Date(1623981452000),
type: 'webauthn',
usage: 'mfa',
},
],
onNewMfaDeviceTypeChange: () => {},
onDeviceCreated: () => {},
onAuthenticated: () => {},
newMfaDeviceType: 'webauthn',
onClose: () => {},
onSuccess: () => {},
usage: 'passwordless' as DeviceUsage,

// Reauth props
reauthAttempt: {} as Attempt,
clearReauthAttempt: () => {},
mfaChallengeOptions: [
MFA_OPTION_WEBAUTHN,
MFA_OPTION_TOTP,
MFA_OPTION_SSO_DEFAULT,
],
submitWithMfa: async (mfaType?: DeviceType, otpCode?: string) => {},

// Create props
mfaRegisterOptions: [MFA_OPTION_WEBAUTHN, MFA_OPTION_TOTP],
onDeviceCreated: (c: Credential) => {},
onNewMfaDeviceTypeChange: (d: DeviceType) => {},

// Save props
credential: { id: 'cred-id', type: 'public-key' },
};
Loading

0 comments on commit 56c0d8c

Please sign in to comment.