fix: secure passkey cookies (#1533)

This commit is contained in:
David Nguyen
2024-12-12 01:16:29 +09:00
committed by GitHub
parent 76028771b8
commit 161d40cde7
3 changed files with 16 additions and 10 deletions

View File

@ -46,3 +46,10 @@ export const PASSKEY_TIMEOUT = 60000;
* The maximum number of passkeys are user can have.
*/
export const MAXIMUM_PASSKEYS = 50;
export const useSecureCookies =
process.env.NODE_ENV === 'production' && String(process.env.NEXTAUTH_URL).startsWith('https://');
const secureCookiePrefix = useSecureCookies ? '__Secure-' : '';
export const formatSecureCookieName = (name: string) => `${secureCookiePrefix}${name}`;

View File

@ -13,6 +13,7 @@ import { env } from 'next-runtime-env';
import { prisma } from '@documenso/prisma';
import { IdentityProvider, UserSecurityAuditLogType } from '@documenso/prisma/client';
import { formatSecureCookieName, useSecureCookies } from '../constants/auth';
import { AppError, AppErrorCode } from '../errors/app-error';
import { jobsClient } from '../jobs/client';
import { isTwoFactorAuthenticationEnabled } from '../server-only/2fa/is-2fa-availble';
@ -26,10 +27,6 @@ import { extractNextAuthRequestMetadata } from '../universal/extract-request-met
import { getAuthenticatorOptions } from '../utils/authenticator';
import { ErrorCode } from './error-codes';
const useSecureCookies =
process.env.NODE_ENV === 'production' && String(process.env.NEXTAUTH_URL).startsWith('https://');
const cookiePrefix = useSecureCookies ? '__Secure-' : '';
export const NEXT_AUTH_OPTIONS: AuthOptions = {
adapter: PrismaAdapter(prisma),
secret: process.env.NEXTAUTH_SECRET ?? 'secret',
@ -437,7 +434,7 @@ export const NEXT_AUTH_OPTIONS: AuthOptions = {
},
cookies: {
sessionToken: {
name: `${cookiePrefix}next-auth.session-token`,
name: formatSecureCookieName('next-auth.session-token'),
options: {
httpOnly: true,
sameSite: useSecureCookies ? 'none' : 'lax',
@ -446,7 +443,7 @@ export const NEXT_AUTH_OPTIONS: AuthOptions = {
},
},
callbackUrl: {
name: `${cookiePrefix}next-auth.callback-url`,
name: formatSecureCookieName('next-auth.callback-url'),
options: {
sameSite: useSecureCookies ? 'none' : 'lax',
path: '/',
@ -456,7 +453,7 @@ export const NEXT_AUTH_OPTIONS: AuthOptions = {
csrfToken: {
// Default to __Host- for CSRF token for additional protection if using useSecureCookies
// NB: The `__Host-` prefix is stricter than the `__Secure-` prefix.
name: `${cookiePrefix}next-auth.csrf-token`,
name: formatSecureCookieName('next-auth.csrf-token'),
options: {
httpOnly: true,
sameSite: useSecureCookies ? 'none' : 'lax',
@ -465,7 +462,7 @@ export const NEXT_AUTH_OPTIONS: AuthOptions = {
},
},
pkceCodeVerifier: {
name: `${cookiePrefix}next-auth.pkce.code_verifier`,
name: formatSecureCookieName('next-auth.pkce.code_verifier'),
options: {
httpOnly: true,
sameSite: useSecureCookies ? 'none' : 'lax',
@ -474,7 +471,7 @@ export const NEXT_AUTH_OPTIONS: AuthOptions = {
},
},
state: {
name: `${cookiePrefix}next-auth.state`,
name: formatSecureCookieName('next-auth.state'),
options: {
httpOnly: true,
sameSite: useSecureCookies ? 'none' : 'lax',

View File

@ -4,6 +4,7 @@ import { parse } from 'cookie-es';
import { env } from 'next-runtime-env';
import { IS_BILLING_ENABLED } from '@documenso/lib/constants/app';
import { formatSecureCookieName } from '@documenso/lib/constants/auth';
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
import { jobsClient } from '@documenso/lib/jobs/client';
import { ErrorCode } from '@documenso/lib/next-auth/error-codes';
@ -111,7 +112,8 @@ export const authRouter = router({
const cookies = parse(ctx.req.headers.cookie ?? '');
const sessionIdToken =
cookies['__Host-next-auth.csrf-token'] || cookies['next-auth.csrf-token'];
cookies[formatSecureCookieName('__Host-next-auth.csrf-token')] ||
cookies[formatSecureCookieName('next-auth.csrf-token')];
if (!sessionIdToken) {
throw new Error('Missing CSRF token');