Skip to content

Commit b8bc5f8

Browse files
committed
Fix old browser compat
1 parent 7425680 commit b8bc5f8

File tree

3 files changed

+23
-29
lines changed

3 files changed

+23
-29
lines changed

packages/connect-react/src/components/append/AppendInitScreen.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,8 @@ const AppendInitScreen = () => {
205205
const res = await getConnectService().completeAppend(attestationOptions, 'conditional');
206206
if (res.err) {
207207
await handleSituation(AppendSituationCode.ClientPasskeyOperationErrorSilent, res.val);
208-
return false;
208+
209+
return res.val.type === ConnectErrorType.RaceTimeout;
209210
}
210211

211212
navigateToScreen(AppendScreenType.Success, {

packages/web-core/src/services/WebAuthnService.ts

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
/// <reference types="web-bluetooth" />
22
/// <reference types="user-agent-data-types" /> <- add this line
33
import type { ClientCapabilities } from '@corbado/types';
4-
import { parseCreationOptionsFromJSON, parseRequestOptionsFromJSON } from '@corbado/webauthn-json/browser-ponyfill';
4+
import { create, get } from '@corbado/webauthn-json';
55
import FingerprintJS from '@fingerprintjs/fingerprintjs';
66
import { detectIncognito } from 'detectincognitojs';
77
import log from 'loglevel';
88
import type { Result } from 'ts-results';
99
import { Err, Ok } from 'ts-results';
1010

1111
import type { ClientInformation, ClientStateMeta, JavaScriptHighEntropy } from '../api/v2';
12-
import { CorbadoError } from '../utils';
12+
import { ConnectError, ConnectErrorType, CorbadoError } from '../utils';
1313
import type { ClientStateEntry } from './ClientStateService';
1414
import { ClientStateService } from './ClientStateService';
1515

@@ -40,23 +40,20 @@ export class WebAuthnService {
4040
}
4141

4242
async createPasskeyRaw(attestationOptions: string, conditional: boolean): Promise<ResponseWithMessage> {
43-
let message;
4443
const abortController = this.abortOngoingOperation();
4544
const attestationOptionsJSON = JSON.parse(attestationOptions);
4645
this.#abortController = abortController;
4746

48-
let publicKey: PublicKeyCredentialCreationOptions | undefined;
49-
if (PublicKeyCredential.parseCreationOptionsFromJSON) {
50-
publicKey = PublicKeyCredential.parseCreationOptionsFromJSON(attestationOptionsJSON.publicKey);
51-
} else {
52-
message = 'parseCreationOptionsFromJSON not available';
53-
publicKey = parseCreationOptionsFromJSON(attestationOptionsJSON).publicKey;
54-
}
55-
56-
if (!publicKey) {
57-
throw new Error('No publicKey in assertionOptions');
47+
if (!PublicKeyCredential.parseCreationOptionsFromJSON) {
48+
attestationOptionsJSON.signal = abortController.signal;
49+
const signedChallenge = await create(attestationOptionsJSON);
50+
return {
51+
response: JSON.stringify(signedChallenge),
52+
message: 'parseCreationOptionsFromJSON not available',
53+
};
5854
}
5955

56+
const publicKey = PublicKeyCredential.parseCreationOptionsFromJSON(attestationOptionsJSON.publicKey);
6057
let credential: PublicKeyCredential;
6158
if (conditional) {
6259
const result = await WebAuthnService.raceWithTimeout(
@@ -78,7 +75,7 @@ export class WebAuthnService {
7875

7976
return {
8077
response: JSON.stringify(credential.toJSON()),
81-
message,
78+
message: '',
8279
};
8380
}
8481

@@ -104,24 +101,19 @@ export class WebAuthnService {
104101
conditional: boolean,
105102
onConditionalLoginStart?: (ac: AbortController) => void,
106103
): Promise<ResponseWithMessage> {
107-
let message: string | undefined;
108104
const abortController = this.abortOngoingOperation();
109105
const assertionOptionsJSON = JSON.parse(assertionOptions);
110106
this.#abortController = abortController;
111107
onConditionalLoginStart?.(abortController);
112-
113-
let publicKey: PublicKeyCredentialRequestOptions | undefined;
114-
if (PublicKeyCredential.parseRequestOptionsFromJSON) {
115-
publicKey = PublicKeyCredential.parseRequestOptionsFromJSON(assertionOptionsJSON.publicKey);
116-
} else {
117-
publicKey = parseRequestOptionsFromJSON(assertionOptionsJSON).publicKey;
118-
message = 'parseRequestOptionsFromJSON not available';
119-
}
120-
121-
if (!publicKey) {
122-
throw new Error('No publicKey in assertionOptions');
108+
if (!PublicKeyCredential.parseRequestOptionsFromJSON) {
109+
const signedChallenge = await get(assertionOptionsJSON);
110+
return {
111+
response: JSON.stringify(signedChallenge),
112+
message: 'parseRequestOptionsFromJSON not available',
113+
};
123114
}
124115

116+
const publicKey = PublicKeyCredential.parseRequestOptionsFromJSON(assertionOptionsJSON.publicKey);
125117
let mediation: CredentialMediationRequirement | undefined;
126118
if (conditional) {
127119
mediation = 'conditional';
@@ -135,7 +127,7 @@ export class WebAuthnService {
135127

136128
return {
137129
response: JSON.stringify(credential.toJSON()),
138-
message,
130+
message: '',
139131
};
140132
}
141133

@@ -333,7 +325,7 @@ export class WebAuthnService {
333325

334326
static async raceWithTimeout<T>(p: Promise<T>, ms: number): Promise<T> {
335327
const timeout = new Promise<never>((_, reject) =>
336-
setTimeout(() => reject(new Error(`timeout of ${ms}ms reached`)), ms),
328+
setTimeout(() => reject(new ConnectError(ConnectErrorType.RaceTimeout, `timeout of ${ms}ms reached`)), ms),
337329
);
338330

339331
return Promise.race<T>([p, timeout]);

packages/web-core/src/utils/errors/connectErrors.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export enum ConnectErrorType {
88
InvalidState,
99
SecurityError,
1010
ExcludeCredentialsMatch,
11+
RaceTimeout,
1112
}
1213

1314
export class ConnectError {

0 commit comments

Comments
 (0)