-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathverify.ts
More file actions
71 lines (54 loc) · 2.8 KB
/
Copy pathverify.ts
File metadata and controls
71 lines (54 loc) · 2.8 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
import type { NextApiRequest, NextApiResponse } from 'next';
import { verifyRegistrationResponse } from '@simplewebauthn/server';
import type { RegistrationResponseJSON } from '@simplewebauthn/types';
import { env } from '@workspace/common/client/env';
import { logger } from '@workspace/common/logger';
import { auth } from '@workspace/common/server/config/firebase';
import { retrieveAndInvalidateChallengeSession } from '@workspace/common/server/services/challenge-session';
import { createUserPasskey, findUserByUsername } from '@workspace/common/server/services/users';
export type VerifyRegistrationRequestData = {
registrationResponse: RegistrationResponseJSON;
};
export type VerifyRegistrationResponseData = {
customToken: string;
};
export default async function handler(req: NextApiRequest, res: NextApiResponse<VerifyRegistrationResponseData>) {
try {
const { registrationResponse } = req.body as VerifyRegistrationRequestData;
const challengeSession = await retrieveAndInvalidateChallengeSession(req, res, 'attestation');
if (!challengeSession || challengeSession.type !== 'attestation') {
return res.status(401).end('Challenge session is not active. Please start the registration process again.');
}
const verifiedRegistrationResponse = await verifyRegistrationResponse({
response: registrationResponse,
expectedChallenge: challengeSession.challenge,
expectedOrigin: challengeSession.origin,
expectedRPID: challengeSession.rpId,
});
if (!verifiedRegistrationResponse.verified) {
return res.status(401).end('User not authenticated.');
}
logger.debug('verifiedRegistrationResponse', verifiedRegistrationResponse);
// Just an example what you can do with the result, not needed for this current authentication process itself
// parseRegistrationResponse(registrationResponse);
const { username } = challengeSession;
const existingUser = await findUserByUsername(username);
if (existingUser) {
return res.status(400).end('User already exists.');
}
const userId = await createUserPasskey(username, verifiedRegistrationResponse.registrationInfo);
/**
* Creates a new Firebase custom token (JWT)
* that can be sent back to a client device to use to sign in with the client SDKs' signInWithCustomToken() methods.
*/
const customToken = await auth().createCustomToken(userId);
res.status(200).json({ customToken });
} catch (error) {
logger.error(error);
res.status(500).end(
error instanceof Error && env.NEXT_PUBLIC_NODE_ENV !== 'production'
? error.message
: 'Internal Server Error',
);
}
}