mirror of
https://github.com/hanzoai/sign.git
synced 2026-10-21 01:21:51 +00:00
The product is branded Hanzo eSign (esign.hanzo.ai, repo hanzoai/esign). Rename all workspace packages @hanzo/sign-* → @hanzo/esign-* (1052 files) and align docker/Dockerfile turbo --scope/--filter to the actual remix package name @hanzo/esign (was a pre-existing mismatch with -remix that broke the build). Protected deps (@hanzo/insights, @hanzo/logo) untouched.
59 lines
1.6 KiB
TypeScript
59 lines
1.6 KiB
TypeScript
import { generateRegistrationOptions } from '@simplewebauthn/server';
|
|
import type { AuthenticatorTransportFuture } from '@simplewebauthn/server';
|
|
import { isoBase64URL } from '@simplewebauthn/server/helpers';
|
|
import { DateTime } from 'luxon';
|
|
|
|
import { prisma } from '@hanzo/esign-prisma';
|
|
|
|
import { PASSKEY_TIMEOUT } from '../../constants/auth';
|
|
import { getAuthenticatorOptions } from '../../utils/authenticator';
|
|
|
|
type CreatePasskeyRegistrationOptions = {
|
|
userId: number;
|
|
};
|
|
|
|
export const createPasskeyRegistrationOptions = async ({
|
|
userId,
|
|
}: CreatePasskeyRegistrationOptions) => {
|
|
const user = await prisma.user.findFirstOrThrow({
|
|
where: {
|
|
id: userId,
|
|
},
|
|
select: {
|
|
name: true,
|
|
email: true,
|
|
passkeys: true,
|
|
},
|
|
});
|
|
|
|
const { passkeys } = user;
|
|
|
|
const { rpName, rpId: rpID } = getAuthenticatorOptions();
|
|
|
|
const options = await generateRegistrationOptions({
|
|
rpName,
|
|
rpID,
|
|
userID: Buffer.from(userId.toString()),
|
|
userName: user.email,
|
|
userDisplayName: user.name ?? undefined,
|
|
timeout: PASSKEY_TIMEOUT,
|
|
attestationType: 'none',
|
|
excludeCredentials: passkeys.map((passkey) => ({
|
|
id: isoBase64URL.fromBuffer(passkey.credentialId),
|
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
transports: passkey.transports as AuthenticatorTransportFuture[],
|
|
})),
|
|
});
|
|
|
|
await prisma.verificationToken.create({
|
|
data: {
|
|
userId,
|
|
token: options.challenge,
|
|
expires: DateTime.now().plus({ minutes: 2 }).toJSDate(),
|
|
identifier: 'PASSKEY_CHALLENGE',
|
|
},
|
|
});
|
|
|
|
return options;
|
|
};
|