import { EncryptJWT , jwtDecrypt } from "jose" ; import hkdf from "@panva/hkdf" ; import { v4 as uuid } from "uuid" ; import { SessionStore } from "../core/lib/cookie" ; import type { NextApiRequest } from "next" ; import type { JWT , JWTDecodeParams , JWTEncodeParams , JWTOptions } from "./types" ; import type { LoggerInstance } from ".." ; export * from "./types" ; const DEFAULT_MAX_AGE = 30 * 24 * 60 * 60 ; const now = ( ) => ( Date . now ( ) / 1000 ) | 0 ; /** Issues a JWT. By default, the JWT is encrypted using "A256GCM". */ export async function encode ( { token = { } , secret , maxAge = DEFAULT_MAX_AGE , } ) { const encryptionSecret = await getDerivedEncryptionKey ( secret ) ; return await new EncryptJWT ( token ) . setProtectedHeader ( { alg : "dir" , enc : "A256GCM" } ) . setIssuedAt ( ) . setExpirationTime ( now ( ) + maxAge ) . setJti ( uuid ( ) ) . encrypt ( encryptionSecret ) ; } /** Decodes a NextAuth.js issued JWT. */ export async function decode ( { token , secret , } ) { if ( ! token ) return null ; const encryptionSecret = await getDerivedEncryptionKey ( secret ) ; const { payload } = await jwtDecrypt ( token , encryptionSecret , { clockTolerance : 15 , } ) ; return payload ; } export interface GetTokenParams < R extends boolean = false > { /** The request containing the JWT either in the cookies or in the `Authorization` header. */ req : NextApiRequest ; /**
     * Use secure prefix for cookie name, unless URL in `NEXTAUTH_URL` is http://
     * or not set (e.g. development or test instance) case use unprefixed name
     */ secureCookie ? : boolean ; /** If the JWT is in the cookie, what name `getToken()` should look for. */ cookieName ? : string ; default raw ? : R ; secret : string ; decode ? : JWTOptions [ "decode" ] ; logger ? : LoggerInstance | Console ; } /**
 * Takes a NextAuth.js request (`req`) and returns either the NextAuth.js issued JWT's payload,
 * or the raw JWT string. We look for the JWT in the either the cookies, or the `Authorization` header.
 * [Documentation](https://next-auth.js.org/tutorials/securing-pages-and-api-routes#using-gettoken)
 */ export async function getToken < R extends boolean = false > ( params ? ) { const { req , secureCookie = process . env . NEXTAUTH_URL ?. startsWith ( "https://" ) ?? ! ! process . env . VERCEL , cookieName = secureCookie ? "__Secure-next-auth.session-token" : "next-auth.session-token" , raw , decode : _decode = decode , logger = console , } = params ?? { } ; if ( ! req ) throw new Error ( "Must pass `req` to JWT getToken()" ) ; const sessionStore = new SessionStore ( { name : cookieName , options : { secure : secureCookie } } , { cookies : req . cookies , headers : req . headers } , logger ) ; let token = sessionStore . value ; if ( ! token && req . headers . authorization ?. split ( " " ) [ 0 ] === "Bearer" ) { const urlEncodedToken = req . headers . authorization . split ( " " ) [ 1 ] ; token = decodeURIComponent ( urlEncodedToken ) ; } if ( ! token ) return null ; if ( raw ) return token ; try { return await _decode ( { token , ... params } ) ; } catch { return null ; } } async function getDerivedEncryptionKey ( secret ) { return await hkdf ( "sha256" , secret , "" , "NextAuth.js Generated Encryption Key" , 32 ) ; }