From c8922ca032a0bd377c4fc4c279029c51f52ddde7 Mon Sep 17 00:00:00 2001 From: Incorbador Date: Wed, 29 Jan 2025 21:43:58 +0100 Subject: [PATCH 1/3] Update connect default timeouts --- packages/web-core/src/services/ConnectService.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/web-core/src/services/ConnectService.ts b/packages/web-core/src/services/ConnectService.ts index 03f27887e..c64f8e17c 100644 --- a/packages/web-core/src/services/ConnectService.ts +++ b/packages/web-core/src/services/ConnectService.ts @@ -45,7 +45,7 @@ export class ConnectService { constructor(projectId: string, frontendApiUrlSuffix: string, isDebug: boolean) { this.#projectId = projectId; - this.#timeout = 5 * 1000; + this.#timeout = 10 * 1000; this.#frontendApiUrlSuffix = frontendApiUrlSuffix; this.#webAuthnService = new WebAuthnService(); this.#visitorId = ''; @@ -143,7 +143,7 @@ export class ConnectService { const { req, flags } = await this.#getInitReq(); const res = await this.wrapWithErr(() => - this.#connectApi.connectLoginInit(req, { signal: abortController.signal }), + this.#connectApi.connectLoginInit(req, { signal: abortController.signal, timeout: 5 * 1000 }), ); if (res.err) { From 33b158f284445bad8d4bbdc820987bf0147c2ec9 Mon Sep 17 00:00:00 2001 From: Incorbador Date: Wed, 29 Jan 2025 22:01:24 +0100 Subject: [PATCH 2/3] Connect: Add PasskeyAppendNotSupportedLightModal, fix loginSituation logging --- .../src/components/CorbadoConnectDemo.tsx | 7 ++++++ .../src/components/login/LoginInitScreen.tsx | 7 +++++- .../PasskeyAppendNotSupportedLightModal.tsx | 23 +++++++++++++++++++ .../passkeyList/PasskeyListScreen.tsx | 9 ++++++++ .../connect-react/src/types/situations.ts | 2 ++ packages/web-core/openapi/spec_v2.yaml | 3 +++ packages/web-core/src/api/v2/api.ts | 6 +++++ packages/web-core/src/utils/errors/errors.ts | 4 ++-- 8 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 packages/connect-react/src/components/passkeyList/PasskeyAppendNotSupportedLightModal.tsx diff --git a/packages/connect-react/src/components/CorbadoConnectDemo.tsx b/packages/connect-react/src/components/CorbadoConnectDemo.tsx index 4cec7b9d9..6b17f9f3b 100644 --- a/packages/connect-react/src/components/CorbadoConnectDemo.tsx +++ b/packages/connect-react/src/components/CorbadoConnectDemo.tsx @@ -16,6 +16,7 @@ import AlreadyExistingModal from './passkeyList/AlreadyExistingModal'; import DeleteModal from './passkeyList/DeleteModal'; import PasskeyAppendNotSupportedModal from './passkeyList/PasskeyAppendNotSupportedModal'; import PasskeyList, { PasskeyListState } from './passkeyList/PasskeyList'; +import PasskeyAppendNotSupportedLightModal from './passkeyList/PasskeyAppendNotSupportedLightModal'; const getListOfPasskeys = () => { const out: Passkey[] = [ @@ -195,6 +196,12 @@ const CorbadoConnectDemo: FC = _ => { 'This modal is shown to the user when they try to append a passkey but the operation is not supported by their device (e.g. because it is too old).', reactElement: console.log('hide')} />, }, + { + headline: 'Passkey append not supported light modal', + description: + 'This modal is shown to the user when they try to append a passkey but the operation is not supported by their current browser (another browser on the same device might support it though).', + reactElement: console.log('hide')} />, + }, ]; const append: Element[] = [ diff --git a/packages/connect-react/src/components/login/LoginInitScreen.tsx b/packages/connect-react/src/components/login/LoginInitScreen.tsx index d423cca8c..e3985663f 100644 --- a/packages/connect-react/src/components/login/LoginInitScreen.tsx +++ b/packages/connect-react/src/components/login/LoginInitScreen.tsx @@ -2,6 +2,7 @@ import { ConnectConditionalUIPasskeyDeleted, ConnectCustomError, ConnectExistingPasskeysNotAvailable, + ConnectNoPasskeyAvailableError, ConnectUserNotFound, PasskeyChallengeCancelledError, PasskeyLoginSource, @@ -198,6 +199,9 @@ const LoginInitScreen: FC = ({ showFallback = false }) => { if (resStart.val instanceof ConnectExistingPasskeysNotAvailable) { return handleSituation(LoginSituationCode.PreAuthenticatorExistingPasskeysNotAvailable); } + if (resStart.val instanceof ConnectNoPasskeyAvailableError) { + return handleSituation(LoginSituationCode.PreAuthenticatorNoPasskeyAvailable); + } return handleSituation(LoginSituationCode.CboApiNotAvailablePreAuthenticator); } @@ -250,6 +254,8 @@ const LoginInitScreen: FC = ({ showFallback = false }) => { statefulLoader.current.finish(); break; case LoginSituationCode.DeniedByPartialRollout: + case LoginSituationCode.PreAuthenticatorExistingPasskeysNotAvailable: + case LoginSituationCode.PreAuthenticatorNoPasskeyAvailable: automaticFallback(identifier, message); statefulLoader.current.finish(); @@ -259,7 +265,6 @@ const LoginInitScreen: FC = ({ showFallback = false }) => { case LoginSituationCode.CboApiNotAvailablePreConditionalAuthenticator: case LoginSituationCode.CtApiNotAvailablePostAuthenticator: case LoginSituationCode.CboApiNotAvailablePostAuthenticator: - case LoginSituationCode.PreAuthenticatorExistingPasskeysNotAvailable: automaticFallback(identifier, message); void getConnectService().recordEventLoginErrorUnexpected(messageCode); diff --git a/packages/connect-react/src/components/passkeyList/PasskeyAppendNotSupportedLightModal.tsx b/packages/connect-react/src/components/passkeyList/PasskeyAppendNotSupportedLightModal.tsx new file mode 100644 index 000000000..2afc51e20 --- /dev/null +++ b/packages/connect-react/src/components/passkeyList/PasskeyAppendNotSupportedLightModal.tsx @@ -0,0 +1,23 @@ +import React from 'react'; + +import { BaseModal } from '../shared/BaseModal'; + +type Props = { + hide: () => void; +}; + +const PasskeyAppendNotSupportedLightModal = ({ hide }: Props) => ( + hide()} + onCloseButton={() => hide()} + headerText='No passkey created' + primaryButtonText='Okay' + children={ + <> +

This in-app view doesn't support passkeys. Use your standard browser.

+ + } + /> +); + +export default PasskeyAppendNotSupportedLightModal; diff --git a/packages/connect-react/src/components/passkeyList/PasskeyListScreen.tsx b/packages/connect-react/src/components/passkeyList/PasskeyListScreen.tsx index fc4d74342..c7060235e 100644 --- a/packages/connect-react/src/components/passkeyList/PasskeyListScreen.tsx +++ b/packages/connect-react/src/components/passkeyList/PasskeyListScreen.tsx @@ -14,6 +14,7 @@ import AlreadyExistingModal from './AlreadyExistingModal'; import DeleteModal from './DeleteModal'; import PasskeyAppendNotSupportedModal from './PasskeyAppendNotSupportedModal'; import PasskeyList, { PasskeyListState } from './PasskeyList'; +import PasskeyAppendNotSupportedLightModal from './PasskeyAppendNotSupportedLightModal'; const PasskeyListScreen = () => { const { config } = useManageProcess(); @@ -122,6 +123,10 @@ const PasskeyListScreen = () => { } if (!startAppendRes.val.attestationOptions) { + if (startAppendRes.val.isRestrictedBrowser) { + return handleSituation(PasskeyListSituationCode.CboApiPasskeysNotSupportedLight); + } + return handleSituation(PasskeyListSituationCode.CboApiPasskeysNotSupported); } @@ -178,6 +183,10 @@ const PasskeyListScreen = () => { void getConnectService().recordEventAppendCredentialExistsError(); show(); break; + case PasskeyListSituationCode.CboApiPasskeysNotSupportedLight: + setAppendLoading(false); + show(); + break; case PasskeyListSituationCode.CboApiPasskeysNotSupported: setAppendLoading(false); show(); diff --git a/packages/connect-react/src/types/situations.ts b/packages/connect-react/src/types/situations.ts index 2c1a5a96d..89f9335e9 100644 --- a/packages/connect-react/src/types/situations.ts +++ b/packages/connect-react/src/types/situations.ts @@ -13,6 +13,7 @@ export enum LoginSituationCode { DeniedByPartialRollout, PreAuthenticatorCustomError, PreAuthenticatorExistingPasskeysNotAvailable, + PreAuthenticatorNoPasskeyAvailable, } export enum AppendSituationCode { @@ -37,6 +38,7 @@ export enum PasskeyListSituationCode { CboApiNotAvailablePostAuthenticator, ClientPasskeyOperationCancelled, ClientExcludeCredentialsMatch, + CboApiPasskeysNotSupportedLight, } export type PreAuthenticatorCustomErrorData = { diff --git a/packages/web-core/openapi/spec_v2.yaml b/packages/web-core/openapi/spec_v2.yaml index 121372c6e..8412e5e13 100644 --- a/packages/web-core/openapi/spec_v2.yaml +++ b/packages/web-core/openapi/spec_v2.yaml @@ -1337,6 +1337,7 @@ components: required: - attestationOptions - variant + - isRestrictedBrowser properties: attestationOptions: type: string @@ -1346,6 +1347,8 @@ components: - default - after-hybrid - after-error + isRestrictedBrowser: + type: boolean connectAppendFinishReq: type: object diff --git a/packages/web-core/src/api/v2/api.ts b/packages/web-core/src/api/v2/api.ts index e15ca20d2..dcf2b9a94 100644 --- a/packages/web-core/src/api/v2/api.ts +++ b/packages/web-core/src/api/v2/api.ts @@ -384,6 +384,12 @@ export interface ConnectAppendStartRsp { * @memberof ConnectAppendStartRsp */ 'variant': ConnectAppendStartRspVariantEnum; + /** + * + * @type {boolean} + * @memberof ConnectAppendStartRsp + */ + 'isRestrictedBrowser': boolean; } export const ConnectAppendStartRspVariantEnum = { diff --git a/packages/web-core/src/utils/errors/errors.ts b/packages/web-core/src/utils/errors/errors.ts index 0ea6bddc7..82e8bc47b 100644 --- a/packages/web-core/src/utils/errors/errors.ts +++ b/packages/web-core/src/utils/errors/errors.ts @@ -153,7 +153,7 @@ export class CorbadoError extends Error { } static noPasskeyAvailable(): CorbadoError { - return new NoPasskeyAvailableError(); + return new ConnectNoPasskeyAvailableError(); } static onlyHybridPasskeyAvailable(): CorbadoError { @@ -239,7 +239,7 @@ export class UnknownUserError extends RecoverableError { } } -export class NoPasskeyAvailableError extends RecoverableError { +export class ConnectNoPasskeyAvailableError extends RecoverableError { constructor() { super('No passkey available'); this.name = 'errors.noPasskeyAvailable'; From 674e49f8b2cc66aa475310b5c1a48aabea419964 Mon Sep 17 00:00:00 2001 From: Incorbador Date: Wed, 29 Jan 2025 23:08:42 +0100 Subject: [PATCH 3/3] linter --- packages/connect-react/src/components/CorbadoConnectDemo.tsx | 2 +- .../src/components/passkeyList/PasskeyListScreen.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/connect-react/src/components/CorbadoConnectDemo.tsx b/packages/connect-react/src/components/CorbadoConnectDemo.tsx index 6b17f9f3b..555f0339d 100644 --- a/packages/connect-react/src/components/CorbadoConnectDemo.tsx +++ b/packages/connect-react/src/components/CorbadoConnectDemo.tsx @@ -14,9 +14,9 @@ import LoginInitLoading from './login/base/LoginInitLoading'; import LoginOneTap from './login/base/LoginOneTap'; import AlreadyExistingModal from './passkeyList/AlreadyExistingModal'; import DeleteModal from './passkeyList/DeleteModal'; +import PasskeyAppendNotSupportedLightModal from './passkeyList/PasskeyAppendNotSupportedLightModal'; import PasskeyAppendNotSupportedModal from './passkeyList/PasskeyAppendNotSupportedModal'; import PasskeyList, { PasskeyListState } from './passkeyList/PasskeyList'; -import PasskeyAppendNotSupportedLightModal from './passkeyList/PasskeyAppendNotSupportedLightModal'; const getListOfPasskeys = () => { const out: Passkey[] = [ diff --git a/packages/connect-react/src/components/passkeyList/PasskeyListScreen.tsx b/packages/connect-react/src/components/passkeyList/PasskeyListScreen.tsx index c7060235e..3ce754dcf 100644 --- a/packages/connect-react/src/components/passkeyList/PasskeyListScreen.tsx +++ b/packages/connect-react/src/components/passkeyList/PasskeyListScreen.tsx @@ -12,9 +12,9 @@ import { ConnectTokenType } from '../../types/tokens'; import { StatefulLoader } from '../../utils/statefulLoader'; import AlreadyExistingModal from './AlreadyExistingModal'; import DeleteModal from './DeleteModal'; +import PasskeyAppendNotSupportedLightModal from './PasskeyAppendNotSupportedLightModal'; import PasskeyAppendNotSupportedModal from './PasskeyAppendNotSupportedModal'; import PasskeyList, { PasskeyListState } from './PasskeyList'; -import PasskeyAppendNotSupportedLightModal from './PasskeyAppendNotSupportedLightModal'; const PasskeyListScreen = () => { const { config } = useManageProcess();