fix: add passkey limits

This commit is contained in:
David Nguyen
2024-03-17 15:10:32 +08:00
parent e4ad940a06
commit 87b79451d5
4 changed files with 25 additions and 5 deletions

View File

@@ -11,6 +11,7 @@ import { match } from 'ts-pattern';
import { UAParser } from 'ua-parser-js'; import { UAParser } from 'ua-parser-js';
import { z } from 'zod'; import { z } from 'zod';
import { MAXIMUM_PASSKEYS } from '@documenso/lib/constants/auth';
import { AppError } from '@documenso/lib/errors/app-error'; import { AppError } from '@documenso/lib/errors/app-error';
import { trpc } from '@documenso/trpc/react'; import { trpc } from '@documenso/trpc/react';
import { Alert, AlertDescription, AlertTitle } from '@documenso/ui/primitives/alert'; import { Alert, AlertDescription, AlertTitle } from '@documenso/ui/primitives/alert';
@@ -189,6 +190,11 @@ export const CreatePasskeyDialog = ({ trigger, ...props }: CreatePasskeyDialogPr
.with('ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED', () => ( .with('ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED', () => (
<AlertDescription>This passkey has already been registered.</AlertDescription> <AlertDescription>This passkey has already been registered.</AlertDescription>
)) ))
.with('TOO_MANY_PASSKEYS', () => (
<AlertDescription>
You cannot have more than {MAXIMUM_PASSKEYS} passkeys.
</AlertDescription>
))
.with('InvalidStateError', () => ( .with('InvalidStateError', () => (
<> <>
<AlertTitle className="text-sm"> <AlertTitle className="text-sm">

View File

@@ -32,3 +32,8 @@ export const USER_SECURITY_AUDIT_LOG_MAP: { [key in UserSecurityAuditLogType]: s
* The duration to wait for a passkey to be verified in MS. * The duration to wait for a passkey to be verified in MS.
*/ */
export const PASSKEY_TIMEOUT = 60000; export const PASSKEY_TIMEOUT = 60000;
/**
* The maximum number of passkeys are user can have.
*/
export const MAXIMUM_PASSKEYS = 50;

View File

@@ -4,6 +4,7 @@ import type { RegistrationResponseJSON } from '@simplewebauthn/types';
import { prisma } from '@documenso/prisma'; import { prisma } from '@documenso/prisma';
import { UserSecurityAuditLogType } from '@documenso/prisma/client'; import { UserSecurityAuditLogType } from '@documenso/prisma/client';
import { MAXIMUM_PASSKEYS } from '../../constants/auth';
import { AppError, AppErrorCode } from '../../errors/app-error'; import { AppError, AppErrorCode } from '../../errors/app-error';
import type { RequestMetadata } from '../../universal/extract-request-metadata'; import type { RequestMetadata } from '../../universal/extract-request-metadata';
import { getAuthenticatorRegistrationOptions } from '../../utils/authenticator'; import { getAuthenticatorRegistrationOptions } from '../../utils/authenticator';
@@ -21,12 +22,23 @@ export const createPasskey = async ({
verificationResponse, verificationResponse,
requestMetadata, requestMetadata,
}: CreatePasskeyOptions) => { }: CreatePasskeyOptions) => {
await prisma.user.findFirstOrThrow({ const { _count } = await prisma.user.findFirstOrThrow({
where: { where: {
id: userId, id: userId,
}, },
include: {
_count: {
select: {
passkeys: true,
},
},
},
}); });
if (_count.passkeys >= MAXIMUM_PASSKEYS) {
throw new AppError('TOO_MANY_PASSKEYS');
}
const verificationToken = await prisma.verificationToken.findFirst({ const verificationToken = await prisma.verificationToken.findFirst({
where: { where: {
userId, userId,

View File

@@ -110,10 +110,7 @@ export const authRouter = router({
} catch (err) { } catch (err) {
console.error(err); console.error(err);
throw new TRPCError({ throw AppError.parseErrorToTRPCError(err);
code: 'BAD_REQUEST',
message: 'We were unable to create this passkey. Please try again later.',
});
} }
}), }),