UNPKG

payload-auth-plugin-fix

Version:
133 lines (131 loc) 4.34 kB
// src/core/session/payload.ts import { getCookieExpiration } from "payload"; import { UserNotFound } from "../errors/consoleErrors.js"; import jwt from "jsonwebtoken"; import { hashCode } from "../utils/hash.js"; class PayloadSession { #collections; #successPath; #allowSignUp; #redirectFunctions; constructor(collections, allowSignUp, successPath, redirectFunctions) { this.#collections = collections; this.#allowSignUp = !!allowSignUp; this.#successPath = successPath; this.#redirectFunctions = redirectFunctions ?? {}; } async#upsertAccount(accountInfo, scope, issuerName, payload) { let userID; const userQueryResults = await payload.find({ collection: "customers", where: { email: { equals: accountInfo.email } } }); if (userQueryResults.docs.length === 0) { if (!this.#allowSignUp) { throw new UserNotFound; } const newUser = await payload.create({ collection: "customers", data: { email: accountInfo.email, emailVerified: true, password: hashCode(accountInfo.email + payload.secret).toString() } }); userID = newUser.id; } else { userID = userQueryResults.docs[0].id; } const accounts = await payload.find({ collection: this.#collections.accountsCollectionSlug, where: { sub: { equals: accountInfo.sub } } }); const data = { scope, name: accountInfo.name, picture: accountInfo.picture }; if (issuerName === "Passkey" && accountInfo.passKey) { data["passkey"] = { ...accountInfo.passKey }; } if (accounts.docs.length > 0) { await payload.update({ collection: this.#collections.accountsCollectionSlug, where: { id: { equals: accounts.docs[0].id } }, data }); } else { data["sub"] = accountInfo.sub; data["issuerName"] = issuerName; data["user"] = userID; await payload.create({ collection: this.#collections.accountsCollectionSlug, data }); } return userID; } async createSession(accountInfo, scope, issuerName, payload) { let redirectResult = { success: true, redirect: "" }; if (accountInfo.redirect_action && this.#redirectFunctions[accountInfo.redirect_action]) { redirectResult = await this.#redirectFunctions[accountInfo.redirect_action](accountInfo.redirect_context ?? "", accountInfo); if (!redirectResult.success) { throw new Error("Redirect function failed"); } } const userID = await this.#upsertAccount(accountInfo, scope, issuerName, payload); const fieldsToSign = { id: userID, email: accountInfo.email, collection: this.#collections.customersCollectionSlug }; const cookieExpiration = getCookieExpiration({ seconds: 7200 }); const token = jwt.sign(fieldsToSign, payload.secret, { expiresIn: new Date(cookieExpiration).getTime() }); const cookies = []; cookies.push(`${payload.config.cookiePrefix}-token=${token};Path=/;HttpOnly;SameSite=lax;Expires=${cookieExpiration.toString()}`); const expired = "Thu, 01 Jan 1970 00:00:00 GMT"; cookies.push(`__session-oauth-state=; Path=/; HttpOnly; SameSite=Lax; Expires=${expired}`); cookies.push(`__session-oauth-nonce=; Path=/; HttpOnly; SameSite=Lax; Expires=${expired}`); cookies.push(`__session-code-verifier=; Path=/; HttpOnly; SameSite=Lax; Expires=${expired}`); cookies.push(`__session-webpk-challenge=; Path=/; HttpOnly; SameSite=Lax; Expires=${expired}`); let redirectURL = payload.getAdminURL(); if (redirectResult.redirect) { const newURL = new URL(payload.getAdminURL()); newURL.pathname = redirectResult.redirect; redirectURL = newURL.toString(); } else if (this.#successPath) { const newURL = new URL(payload.getAdminURL()); newURL.pathname = this.#successPath; redirectURL = newURL.toString(); } const res = new Response(null, { status: 302, headers: { Location: redirectURL } }); cookies.forEach((cookie) => { res.headers.append("Set-Cookie", cookie); }); return res; } } export { PayloadSession };