UNPKG

@auth/core

Version:

Authentication for the Web.

137 lines (136 loc) 5.93 kB
import { renderToString } from "preact-render-to-string"; import ErrorPage from "./error.js"; import SigninPage from "./signin.js"; import SignoutPage from "./signout.js"; import css from "./styles.js"; import VerifyRequestPage from "./verify-request.js"; import { UnknownAction } from "../../errors.js"; function send({ html, title, status, cookies, theme, headTags, }) { return { cookies, status, headers: { "Content-Type": "text/html" }, body: `<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><style>${css}</style><title>${title}</title>${headTags ?? ""}</head><body class="__next-auth-theme-${theme?.colorScheme ?? "auto"}"><div class="page">${renderToString(html)}</div></body></html>`, }; } /** * Unless the user defines their [own pages](https://authjs.dev/reference/core#pages), * we render a set of default ones, using Preact SSR. */ export default function renderPage(params) { const { url, theme, query, cookies, pages, providers } = params; return { csrf(skip, options, cookies) { if (!skip) { return { headers: { "Content-Type": "application/json", "Cache-Control": "private, no-cache, no-store", Expires: "0", Pragma: "no-cache", }, body: { csrfToken: options.csrfToken }, cookies, }; } options.logger.warn("csrf-disabled"); cookies.push({ name: options.cookies.csrfToken.name, value: "", options: { ...options.cookies.csrfToken.options, maxAge: 0 }, }); return { status: 404, cookies }; }, providers(providers) { return { headers: { "Content-Type": "application/json" }, body: providers.reduce((acc, { id, name, type, signinUrl, callbackUrl }) => { acc[id] = { id, name, type, signinUrl, callbackUrl }; return acc; }, {}), }; }, signin(providerId, error) { if (providerId) throw new UnknownAction("Unsupported action"); if (pages?.signIn) { let signinUrl = `${pages.signIn}${pages.signIn.includes("?") ? "&" : "?"}${new URLSearchParams({ callbackUrl: params.callbackUrl ?? "/" })}`; if (error) signinUrl = `${signinUrl}&${new URLSearchParams({ error })}`; return { redirect: signinUrl, cookies }; } // If we have a webauthn provider with conditional UI and // a simpleWebAuthnBrowserScript is defined, we need to // render the script in the page. const webauthnProvider = providers?.find((p) => p.type === "webauthn" && p.enableConditionalUI && !!p.simpleWebAuthnBrowserVersion); let simpleWebAuthnBrowserScript = ""; if (webauthnProvider) { const { simpleWebAuthnBrowserVersion } = webauthnProvider; simpleWebAuthnBrowserScript = `<script src="https://unpkg.com/@simplewebauthn/browser@${simpleWebAuthnBrowserVersion}/dist/bundle/index.umd.min.js" crossorigin="anonymous"></script>`; } return send({ cookies, theme, html: SigninPage({ csrfToken: params.csrfToken, // We only want to render providers providers: params.providers?.filter((provider) => // Always render oauth and email type providers ["email", "oauth", "oidc"].includes(provider.type) || // Only render credentials type provider if credentials are defined (provider.type === "credentials" && provider.credentials) || // Only render webauthn type provider if formFields are defined (provider.type === "webauthn" && provider.formFields) || // Don't render other provider types false), callbackUrl: params.callbackUrl, theme: params.theme, error, ...query, }), title: "Sign In", headTags: simpleWebAuthnBrowserScript, }); }, signout() { if (pages?.signOut) return { redirect: pages.signOut, cookies }; return send({ cookies, theme, html: SignoutPage({ csrfToken: params.csrfToken, url, theme }), title: "Sign Out", }); }, verifyRequest(props) { if (pages?.verifyRequest) return { redirect: `${pages.verifyRequest}${url?.search ?? ""}`, cookies, }; return send({ cookies, theme, html: VerifyRequestPage({ url, theme, ...props }), title: "Verify Request", }); }, error(error) { if (pages?.error) { return { redirect: `${pages.error}${pages.error.includes("?") ? "&" : "?"}error=${error}`, cookies, }; } return send({ cookies, theme, // @ts-expect-error fix error type ...ErrorPage({ url, theme, error }), title: "Error", }); }, }; }