UNPKG

@auth0/nextjs-auth0

Version:
66 lines (65 loc) 2.54 kB
import * as cookies from "./cookies"; const TRANSACTION_COOKIE_PREFIX = "__txn_"; /** * TransactionStore is responsible for storing the state required to successfully complete * an authentication transaction. The store relies on encrypted, stateless cookies to store * the transaction state. */ export class TransactionStore { constructor({ secret, cookieOptions }) { this.secret = secret; this.transactionCookiePrefix = cookieOptions?.prefix ?? TRANSACTION_COOKIE_PREFIX; this.cookieConfig = { httpOnly: true, sameSite: cookieOptions?.sameSite ?? "lax", // required to allow the cookie to be sent on the callback request secure: cookieOptions?.secure ?? false, path: cookieOptions?.path ?? "/", maxAge: 60 * 60 // 1 hour in seconds }; } /** * Returns the name of the cookie used to store the transaction state. * The cookie name is derived from the state parameter to prevent collisions * between different transactions. */ getTransactionCookieName(state) { return `${this.transactionCookiePrefix}${state}`; } /** * Returns the configured prefix for transaction cookies. */ getCookiePrefix() { return this.transactionCookiePrefix; } async save(resCookies, transactionState) { const expiration = Math.floor(Date.now() / 1000 + this.cookieConfig.maxAge); const jwe = await cookies.encrypt(transactionState, this.secret, expiration); if (!transactionState.state) { throw new Error("Transaction state is required"); } resCookies.set(this.getTransactionCookieName(transactionState.state), jwe.toString(), this.cookieConfig); } async get(reqCookies, state) { const cookieName = this.getTransactionCookieName(state); const cookieValue = reqCookies.get(cookieName)?.value; if (!cookieValue) { return null; } return cookies.decrypt(cookieValue, this.secret); } async delete(resCookies, state) { await resCookies.delete(this.getTransactionCookieName(state)); } /** * Deletes all transaction cookies based on the configured prefix. */ async deleteAll(reqCookies, resCookies) { const txnPrefix = this.getCookiePrefix(); reqCookies.getAll().forEach((cookie) => { if (cookie.name.startsWith(txnPrefix)) { resCookies.delete(cookie.name); } }); } }