Skip to content

Commit

Permalink
[v17] WebUI MFA types refactor (#49974)
Browse files Browse the repository at this point in the history
* Unify mfa types.

* Move DeviceUsage to mfa/types.

* Refactor mfa options and move to services/mfa.

* Lint fix.

* Fix mfa challenge json.

* Add MFA Option constants.

* Fix lint; Fix test.

* Address comments.

* Add license.

* Fix lint.

* typescript version upgrade to v5.7.2.
  • Loading branch information
Joerger authored Dec 10, 2024
1 parent e357726 commit f8fe5c5
Show file tree
Hide file tree
Showing 33 changed files with 584 additions and 349 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
"prettier": "^3.3.3",
"react-select-event": "^5.5.1",
"storybook": "^8.3.4",
"typescript": "^5.6.2",
"typescript": "^5.7.2",
"vite": "^5.4.8"
},
"dependencies": {
Expand Down Expand Up @@ -101,3 +101,4 @@
},
"packageManager": "[email protected]"
}

186 changes: 93 additions & 93 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions web/packages/shared/utils/createMfaOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

import { Auth2faType, PreferredMfaType } from 'shared/services/types';

// Deprecated: use getMfaRegisterOptions or getMfaChallengeOptions instead.
// TODO(Joerger): Delete once no longer used.
export default function createMfaOptions(opts: Options) {
const { auth2faType, required = false } = opts;
const mfaOptions: MfaOption[] = [];
Expand Down
4 changes: 2 additions & 2 deletions web/packages/teleport/src/Account/Account.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ import {

import cfg from 'teleport/config';

import { DeviceUsage } from 'teleport/services/auth';

import { PasswordState } from 'teleport/services/user';

import { DeviceUsage } from 'teleport/services/mfa';

import { AuthDeviceList } from './ManageDevices/AuthDeviceList/AuthDeviceList';
import useManageDevices, {
State as ManageDevicesState,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ import useAttempt from 'shared/hooks/useAttemptNext';

import Ctx from 'teleport/teleportContext';
import cfg from 'teleport/config';
import auth, { DeviceUsage } from 'teleport/services/auth';
import { MfaDevice } from 'teleport/services/mfa';
import auth from 'teleport/services/auth';
import { DeviceUsage, MfaDevice } from 'teleport/services/mfa';
import { MfaChallengeScope } from 'teleport/services/auth/auth';

export default function useManageDevices(ctx: Ctx) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@ import Dialog from 'design/Dialog';

import { http, HttpResponse, delay } from 'msw';

import { DeviceUsage } from 'teleport/services/auth';
import { createTeleportContext } from 'teleport/mocks/contexts';
import { ContextProvider } from 'teleport/index';

import cfg from 'teleport/config';

import { DeviceUsage } from 'teleport/services/mfa';

import {
AddAuthDeviceWizardStepProps,
CreateDeviceStep,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,9 @@ import { StepHeader } from 'design/StepSlider';
import { P } from 'design/Text/Text';

import auth from 'teleport/services/auth/auth';
import { DeviceUsage } from 'teleport/services/auth';
import useTeleport from 'teleport/useTeleport';

import { MfaDevice } from 'teleport/services/mfa';
import { DeviceUsage, MfaDevice } from 'teleport/services/mfa';

import { PasskeyBlurb } from '../../../components/Passkeys/PasskeyBlurb';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ import { NodeMeta } from '../../useDiscover';

import type { Option } from 'shared/components/Select';
import type { AgentStepProps } from '../../types';
import type { MfaAuthnResponse } from 'teleport/services/mfa';
import type { MfaChallengeResponse } from 'teleport/services/mfa';
import type { ConnectionDiagnosticRequest } from 'teleport/services/agents';

export function TestConnection(props: AgentStepProps) {
Expand Down Expand Up @@ -144,7 +144,7 @@ export function TestConnection(props: AgentStepProps) {
function testConnection(args: {
login: string;
sshPrincipalSelectionMode: ConnectionDiagnosticRequest['sshPrincipalSelectionMode'];
mfaResponse?: MfaAuthnResponse;
mfaResponse?: MfaChallengeResponse;
}) {
return runConnectionDiagnostic(
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import { CustomInputFieldForAsterisks } from 'teleport/Discover/Shared/CustomInp

import { MfaChallengeScope } from 'teleport/services/auth/auth';
import { DbMeta, useDiscover } from 'teleport/Discover/useDiscover';
import { MfaAuthnResponse } from 'teleport/services/mfa';
import { MfaChallengeResponse } from 'teleport/services/mfa';
import { WILD_CARD } from 'teleport/Discover/Shared/const';

import {
Expand Down Expand Up @@ -93,7 +93,7 @@ export function TestConnection() {

function testConnection(
validator: Validator,
mfaResponse?: MfaAuthnResponse
mfaResponse?: MfaChallengeResponse
) {
if (!validator.validate()) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { KubeMeta } from '../../useDiscover';

import type { KubeImpersonation } from 'teleport/services/agents';
import type { AgentStepProps } from '../../types';
import type { MfaAuthnResponse } from 'teleport/services/mfa';
import type { MfaChallengeResponse } from 'teleport/services/mfa';

/**
* @deprecated Refactor Discover/Kubernetes/TestConnection away from the container component
Expand All @@ -34,7 +34,7 @@ export function useTestConnection(props: AgentStepProps) {

function testConnection(
impersonate: KubeImpersonation,
mfaResponse?: MfaAuthnResponse
mfaResponse?: MfaChallengeResponse
) {
runConnectionDiagnostic(
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import { NodeMeta } from '../../useDiscover';

import type { Option } from 'shared/components/Select';
import type { AgentStepProps } from '../../types';
import type { MfaAuthnResponse } from 'teleport/services/mfa';
import type { MfaChallengeResponse } from 'teleport/services/mfa';

export function TestConnection(props: AgentStepProps) {
const {
Expand All @@ -65,7 +65,7 @@ export function TestConnection(props: AgentStepProps) {
openNewTab(url);
}

function testConnection(login: string, mfaResponse?: MfaAuthnResponse) {
function testConnection(login: string, mfaResponse?: MfaChallengeResponse) {
runConnectionDiagnostic(
{
resourceKind: 'node',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import type {
ConnectionDiagnostic,
ConnectionDiagnosticRequest,
} from 'teleport/services/agents';
import type { MfaAuthnResponse } from 'teleport/services/mfa';
import type { MfaChallengeResponse } from 'teleport/services/mfa';
import type { ResourceSpec } from 'teleport/Discover/SelectResource';

export function useConnectionDiagnostic() {
Expand Down Expand Up @@ -60,7 +60,7 @@ export function useConnectionDiagnostic() {
*/
async function runConnectionDiagnostic(
req: ConnectionDiagnosticRequest,
mfaAuthnResponse?: MfaAuthnResponse
mfaAuthnResponse?: MfaChallengeResponse
): Promise<{ mfaRequired: boolean }> {
setDiagnosis(null); // reset since user's can re-test connection.
setRanDiagnosis(true);
Expand Down
3 changes: 2 additions & 1 deletion web/packages/teleport/src/Welcome/NewCredentials/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ import { NewFlow, StepComponentProps } from 'design/StepSlider';

import { ReactElement } from 'react';

import { DeviceUsage, RecoveryCodes, ResetToken } from 'teleport/services/auth';
import { RecoveryCodes, ResetToken } from 'teleport/services/auth';
import { RecoveryCodesProps } from 'teleport/components/RecoveryCodes';
import { DeviceUsage } from 'teleport/services/mfa';

export type UseTokenState = {
auth2faType: Auth2faType;
Expand Down
2 changes: 1 addition & 1 deletion web/packages/teleport/src/Welcome/useToken.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ import cfg from 'teleport/config';
import history from 'teleport/services/history';
import auth, {
ChangedUserAuthn,
DeviceUsage,
RecoveryCodes,
ResetPasswordReqWithEvent,
ResetPasswordWithWebauthnReqWithEvent,
ResetToken,
} from 'teleport/services/auth';
import { UseTokenState } from 'teleport/Welcome/NewCredentials/types';
import { DeviceUsage } from 'teleport/services/mfa';

export default function useToken(tokenId: string): UseTokenState {
const [resetToken, setResetToken] = useState<ResetToken>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ import React from 'react';
import { render, screen, fireEvent } from 'design/utils/testing';

import { makeDefaultMfaState, MfaState } from 'teleport/lib/useMfa';
import { SSOChallenge } from 'teleport/services/auth';

import { SSOChallenge } from 'teleport/services/mfa';

import AuthnDialog from './AuthnDialog';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import cfg from 'teleport/config';
import auth from 'teleport/services/auth';
import { MfaChallengeScope } from 'teleport/services/auth/auth';

import type { MfaAuthnResponse } from 'teleport/services/mfa';
import type { MfaChallengeResponse } from 'teleport/services/mfa';

// useReAuthenticate will have different "submit" behaviors depending on:
// - If prop field `onMfaResponse` is defined, after a user submits, the
Expand Down Expand Up @@ -121,7 +121,7 @@ type BaseProps = {
// that accepts a MFA response. No
// authentication has been done at this point.
type MfaResponseProps = BaseProps & {
onMfaResponse(res: MfaAuthnResponse): void;
onMfaResponse(res: MfaChallengeResponse): void;
/**
* The MFA challenge scope of the action to perform, as defined in webauthn.proto.
*/
Expand Down
2 changes: 1 addition & 1 deletion web/packages/teleport/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import type {

import type { SortType } from 'teleport/services/agents';
import type { RecordingType } from 'teleport/services/recordings';
import type { WebauthnAssertionResponse } from './services/auth';
import type { WebauthnAssertionResponse } from './services/mfa';
import type {
PluginKind,
Regions,
Expand Down
2 changes: 1 addition & 1 deletion web/packages/teleport/src/lib/EventEmitterMfaSender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { EventEmitter } from 'events';
import {
MfaChallengeResponse,
WebauthnAssertionResponse,
} from 'teleport/services/auth';
} from 'teleport/services/mfa';

class EventEmitterMfaSender extends EventEmitter {
constructor() {
Expand Down
2 changes: 1 addition & 1 deletion web/packages/teleport/src/lib/tdp/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ import type {
SyncKeys,
SharedDirectoryTruncateResponse,
} from './codec';
import type { WebauthnAssertionResponse } from 'teleport/services/auth';
import type { WebauthnAssertionResponse } from 'teleport/services/mfa';

export enum TdpClientEvent {
TDP_CLIENT_SCREEN_SPEC = 'tdp client screen spec',
Expand Down
7 changes: 3 additions & 4 deletions web/packages/teleport/src/lib/term/tty.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,11 @@
import Logger from 'shared/libs/logger';

import { EventEmitterMfaSender } from 'teleport/lib/EventEmitterMfaSender';
import {
MfaChallengeResponse,
WebauthnAssertionResponse,
} from 'teleport/services/auth';
import { WebauthnAssertionResponse } from 'teleport/services/mfa';
import { AuthenticatedWebSocket } from 'teleport/lib/AuthenticatedWebSocket';

import { MfaChallengeResponse } from 'teleport/services/mfa';

import { EventType, TermEvent, WebsocketCloseCode } from './enums';
import { Protobuf, MessageTypeEnum } from './protobuf';

Expand Down
13 changes: 10 additions & 3 deletions web/packages/teleport/src/lib/useMfa.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,13 @@ import { useState, useEffect, useCallback } from 'react';
import { EventEmitterMfaSender } from 'teleport/lib/EventEmitterMfaSender';
import { TermEvent } from 'teleport/lib/term/enums';
import {
makeMfaAuthenticateChallenge,
parseMfaChallengeJson as parseMfaChallenge,
makeWebauthnAssertionResponse,
} from 'teleport/services/mfa/makeMfa';
import {
MfaAuthenticateChallengeJson,
SSOChallenge,
} from 'teleport/services/auth';
} from 'teleport/services/mfa';

export function useMfa(emitterSender: EventEmitterMfaSender): MfaState {
const [state, setState] = useState<{
Expand Down Expand Up @@ -129,8 +132,12 @@ export function useMfa(emitterSender: EventEmitterMfaSender): MfaState {
useEffect(() => {
let ssoChallengeAbortController: AbortController | undefined;
const challengeHandler = (challengeJson: string) => {
const challenge = JSON.parse(
challengeJson
) as MfaAuthenticateChallengeJson;

const { webauthnPublicKey, ssoChallenge, totpChallenge } =
makeMfaAuthenticateChallenge(challengeJson);
parseMfaChallenge(challenge);

setState(prevState => ({
...prevState,
Expand Down
4 changes: 2 additions & 2 deletions web/packages/teleport/src/services/agents/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { Desktop } from 'teleport/services/desktops';

import { UserGroup } from '../userGroups';

import type { MfaAuthnResponse } from '../mfa';
import type { MfaChallengeResponse } from '../mfa';
import type { Platform } from 'design/platform';

export type UnifiedResource =
Expand Down Expand Up @@ -143,7 +143,7 @@ export type ConnectionDiagnosticRequest = {
sshNodeSetupMethod?: 'script' | 'connect_my_computer'; // `json:"ssh_node_setup_method"`
kubeImpersonation?: KubeImpersonation; // `json:"kubernetes_impersonation"`
dbTester?: DatabaseTester;
mfaAuthnResponse?: MfaAuthnResponse;
mfaAuthnResponse?: MfaChallengeResponse;
};

export type KubeImpersonation = {
Expand Down
2 changes: 1 addition & 1 deletion web/packages/teleport/src/services/api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import auth, { MfaChallengeScope } from 'teleport/services/auth/auth';
import websession from 'teleport/services/websession';

import { storageService } from '../storageService';
import { WebauthnAssertionResponse } from '../auth';
import { WebauthnAssertionResponse } from '../mfa';

import parseError, { ApiError } from './parseError';

Expand Down
24 changes: 12 additions & 12 deletions web/packages/teleport/src/services/auth/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,25 @@

import api from 'teleport/services/api';
import cfg from 'teleport/config';
import { DeviceType } from 'teleport/services/mfa';
import { DeviceType, DeviceUsage } from 'teleport/services/mfa';

import { CaptureEvent, userEventService } from 'teleport/services/userEvent';

import makePasswordToken from './makePasswordToken';
import { makeChangedUserAuthn } from './make';
import {
makeMfaAuthenticateChallenge,
makeMfaRegistrationChallenge,
parseMfaChallengeJson,
parseMfaRegistrationChallengeJson,
makeWebauthnAssertionResponse,
makeWebauthnCreationResponse,
} from './makeMfa';
} from '../mfa/makeMfa';

import makePasswordToken from './makePasswordToken';
import { makeChangedUserAuthn } from './make';
import {
ResetPasswordReqWithEvent,
ResetPasswordWithWebauthnReqWithEvent,
UserCredentials,
ChangePasswordReq,
CreateNewHardwareDeviceRequest,
DeviceUsage,
CreateAuthenticateChallengeRequest,
} from './types';

Expand Down Expand Up @@ -65,7 +65,7 @@ const auth = {
deviceType,
deviceUsage,
})
.then(makeMfaRegistrationChallenge);
.then(parseMfaRegistrationChallengeJson);
},

/**
Expand Down Expand Up @@ -94,7 +94,7 @@ const auth = {
createMfaAuthnChallengeWithToken(tokenId: string) {
return api
.post(cfg.getAuthnChallengeWithTokenUrl(tokenId))
.then(makeMfaAuthenticateChallenge);
.then(parseMfaChallengeJson);
},

// mfaLoginBegin retrieves users mfa challenges for their
Expand All @@ -107,7 +107,7 @@ const auth = {
user: creds?.username,
pass: creds?.password,
})
.then(makeMfaAuthenticateChallenge);
.then(parseMfaChallengeJson);
},

login(userId: string, password: string, otpCode: string) {
Expand Down Expand Up @@ -270,7 +270,7 @@ const auth = {
},
abortSignal
)
.then(makeMfaAuthenticateChallenge);
.then(parseMfaChallengeJson);
},

async fetchWebAuthnChallenge(
Expand All @@ -291,7 +291,7 @@ const auth = {
},
abortSignal
)
.then(makeMfaAuthenticateChallenge)
.then(parseMfaChallengeJson)
)
.then(res =>
navigator.credentials.get({
Expand Down
Loading

0 comments on commit f8fe5c5

Please sign in to comment.