-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathuseConditionalMediation.ts
More file actions
75 lines (57 loc) · 2.58 KB
/
useConditionalMediation.ts
File metadata and controls
75 lines (57 loc) · 2.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import { browserSupportsWebAuthnAutofill, startAuthentication } from '@simplewebauthn/browser';
import { useQuery } from '@tanstack/react-query';
import { signInWithCustomToken } from 'firebase/auth';
import { fetcher } from '@workspace/common/client/api/fetcher';
import { parseUnknownError } from '@workspace/common/client/errors';
import { auth } from '@workspace/common/client/firebase/config';
import { useSnack } from '@workspace/common/client/snackbar/hooks';
import { logger } from '@workspace/common/logger';
import type { StartLoginResponseData } from '~pages/api/webauthn/login/options';
import type { VerifyLoginRequestData, VerifyLoginResponseData } from '~pages/api/webauthn/login/verify';
import { useExampleRouter } from '../../router';
export function useConditionalMediation() {
const { redirect } = useExampleRouter();
const snack = useSnack();
return useQuery({
queryKey: ['passkeysAutoFill'],
queryFn: async () => {
try {
const supported = await browserSupportsWebAuthnAutofill();
if (!supported) {
return false;
}
const {
data: { publicKeyOptions },
} = await fetcher<StartLoginResponseData>({
method: 'GET',
url: '/webauthn/login/options',
});
logger.info('/webauthn/login/options', publicKeyOptions);
const result = await startAuthentication({
optionsJSON: publicKeyOptions,
useBrowserAutofill: true,
});
logger.info('startAuthentication', result);
const { data } = await fetcher<VerifyLoginResponseData>({
method: 'POST',
url: '/webauthn/login/verify',
body: {
authenticationResponse: result,
} satisfies VerifyLoginRequestData,
});
logger.info('/webauthn/login/verify', data);
const userCredential = await signInWithCustomToken(auth(), data.customToken);
logger.info('signInWithCustomToken', { userCredential });
redirect('/passkeys');
return true;
} catch (error) {
const parsedError = await parseUnknownError(error);
if (parsedError.type !== 'ABORT_ERROR') {
snack('error', parsedError.message);
}
throw error;
}
},
retry: false,
});
}