import { Config , CookieOptions , generateToken , HttpResponse } from '@foal/core' ; import { decode , sign } from 'jsonwebtoken' ; import { JWT_DEFAULT_COOKIE_NAME , JWT_DEFAULT_COOKIE_PATH , JWT_DEFAULT_CSRF_COOKIE_NAME , JWT_DEFAULT_SAME_SITE_ON_CSRF_ENABLED } from './constants' ; import { getSecretOrPrivateKey } from './get-secret-or-private-key.util' ; export async function setAuthCookie ( response , token ) { const cookieName = Config . get ( 'settings.jwt.cookie.name' , 'string' , JWT_DEFAULT_COOKIE_NAME ) ; const csrfEnabled = Config . get ( 'settings.jwt.csrf.enabled' , 'boolean' , false ) ; let sameSite = Config . get ( 'settings.jwt.cookie.sameSite' , 'string' ) as 'strict' | 'lax' | 'none' | undefined ; if ( csrfEnabled && sameSite === undefined ) { sameSite = JWT_DEFAULT_SAME_SITE_ON_CSRF_ENABLED ; } const options = { domain : Config . get ( 'settings.jwt.cookie.domain' , 'string' ) , path : Config . get ( 'settings.jwt.cookie.path' , 'string' , JWT_DEFAULT_COOKIE_PATH ) , sameSite , secure : Config . get ( 'settings.jwt.cookie.secure' , 'boolean' ) , } ; const decodedToken = decode ( token , { complete : true } ) ; if ( typeof decodedToken === 'string' || decodedToken === null ) { throw new Error ( 'The given token is not a valid JWT.' ) ; } const { header , payload } = decodedToken ; if ( payload . exp !== undefined ) { options . expires = new Date ( payload . exp * 1000 ) ; } response . setCookie ( cookieName , token , { ... options , httpOnly : Config . get ( 'settings.jwt.cookie.httpOnly' , 'boolean' ) , } ) ; if ( ! csrfEnabled ) { return ; } const jwtOptions = { algorithm : header . alg } ; const csrfPayload = { csrfToken : await generateToken ( ) , sub : payload . sub , } ; if ( payload . exp !== undefined ) { csrfPayload . exp = payload . exp ; } const jwt = await new Promise < string > ( ( resolve , reject ) => sign ( csrfPayload , getSecretOrPrivateKey ( ) , jwtOptions , ( err , encoded ) => { if ( err ) { return reject ( err ) ; } resolve ( encoded ) ; } ) ) ; const csrfCookieName = Config . get ( 'settings.jwt.csrf.cookie.name' , 'string' , JWT_DEFAULT_CSRF_COOKIE_NAME ) ; response . setCookie ( csrfCookieName , jwt , { ... options , httpOnly : false , } ) ; }