Files
lcbp3/frontend/.ignored_node_modules/next-auth/lib/index.js
2025-11-27 17:08:49 +07:00

188 lines
8.0 KiB
JavaScript

import { Auth, createActionURL } from "@auth/core";
// @ts-expect-error Next.js does not yet correctly use the `package.json#exports` field
import { headers } from "next/headers";
// @ts-expect-error Next.js does not yet correctly use the `package.json#exports` field
import { NextResponse } from "next/server";
import { reqWithEnvURL } from "./env.js";
async function getSession(headers, config) {
const url = createActionURL("session",
// @ts-expect-error `x-forwarded-proto` is not nullable, next.js sets it by default
headers.get("x-forwarded-proto"), headers, process.env, config);
const request = new Request(url, {
headers: { cookie: headers.get("cookie") ?? "" },
});
return Auth(request, {
...config,
callbacks: {
...config.callbacks,
// Since we are server-side, we don't need to filter out the session data
// See https://authjs.dev/getting-started/migrating-to-v5#authenticating-server-side
// TODO: Taint the session data to prevent accidental leakage to the client
// https://react.dev/reference/react/experimental_taintObjectReference
async session(...args) {
const session =
// If the user defined a custom session callback, use that instead
(await config.callbacks?.session?.(...args)) ?? {
...args[0].session,
expires: args[0].session.expires?.toISOString?.() ??
args[0].session.expires,
};
const user = args[0].user ?? args[0].token;
return { user, ...session };
},
},
});
}
function isReqWrapper(arg) {
return typeof arg === "function";
}
export function initAuth(config, onLazyLoad // To set the default env vars
) {
if (typeof config === "function") {
return async (...args) => {
if (!args.length) {
// React Server Components
const _headers = await headers();
const _config = await config(undefined); // Review: Should we pass headers() here instead?
onLazyLoad?.(_config);
return getSession(_headers, _config).then((r) => r.json());
}
if (args[0] instanceof Request) {
// middleware.ts inline
// export { auth as default } from "auth"
const req = args[0];
const ev = args[1];
const _config = await config(req);
onLazyLoad?.(_config);
// args[0] is supposed to be NextRequest but the instanceof check is failing.
return handleAuth([req, ev], _config);
}
if (isReqWrapper(args[0])) {
// middleware.ts wrapper/route.ts
// import { auth } from "auth"
// export default auth((req) => { console.log(req.auth) }})
const userMiddlewareOrRoute = args[0];
return async (...args) => {
const _config = await config(args[0]);
onLazyLoad?.(_config);
return handleAuth(args, _config, userMiddlewareOrRoute);
};
}
// API Routes, getServerSideProps
const request = "req" in args[0] ? args[0].req : args[0];
const response = "res" in args[0] ? args[0].res : args[1];
const _config = await config(request);
onLazyLoad?.(_config);
// @ts-expect-error -- request is NextRequest
return getSession(new Headers(request.headers), _config).then(async (authResponse) => {
const auth = await authResponse.json();
for (const cookie of authResponse.headers.getSetCookie())
if ("headers" in response)
response.headers.append("set-cookie", cookie);
else
response.appendHeader("set-cookie", cookie);
return auth;
});
};
}
return (...args) => {
if (!args.length) {
// React Server Components
return Promise.resolve(headers()).then((h) => getSession(h, config).then((r) => r.json()));
}
if (args[0] instanceof Request) {
// middleware.ts inline
// export { auth as default } from "auth"
const req = args[0];
const ev = args[1];
return handleAuth([req, ev], config);
}
if (isReqWrapper(args[0])) {
// middleware.ts wrapper/route.ts
// import { auth } from "auth"
// export default auth((req) => { console.log(req.auth) }})
const userMiddlewareOrRoute = args[0];
return async (...args) => {
return handleAuth(args, config, userMiddlewareOrRoute).then((res) => {
return res;
});
};
}
// API Routes, getServerSideProps
const request = "req" in args[0] ? args[0].req : args[0];
const response = "res" in args[0] ? args[0].res : args[1];
return getSession(
// @ts-expect-error
new Headers(request.headers), config).then(async (authResponse) => {
const auth = await authResponse.json();
for (const cookie of authResponse.headers.getSetCookie())
if ("headers" in response)
response.headers.append("set-cookie", cookie);
else
response.appendHeader("set-cookie", cookie);
return auth;
});
};
}
async function handleAuth(args, config, userMiddlewareOrRoute) {
const request = reqWithEnvURL(args[0]);
const sessionResponse = await getSession(request.headers, config);
const auth = await sessionResponse.json();
let authorized = true;
if (config.callbacks?.authorized) {
authorized = await config.callbacks.authorized({ request, auth });
}
let response = NextResponse.next?.();
if (authorized instanceof Response) {
// User returned a custom response, like redirecting to a page or 401, respect it
response = authorized;
const redirect = authorized.headers.get("Location");
const { pathname } = request.nextUrl;
// If the user is redirecting to the same NextAuth.js action path as the current request,
// don't allow the redirect to prevent an infinite loop
if (redirect &&
isSameAuthAction(pathname, new URL(redirect).pathname, config)) {
authorized = true;
}
}
else if (userMiddlewareOrRoute) {
// Execute user's middleware/handler with the augmented request
const augmentedReq = request;
augmentedReq.auth = auth;
response =
(await userMiddlewareOrRoute(augmentedReq, args[1])) ??
NextResponse.next();
}
else if (!authorized) {
const signInPage = config.pages?.signIn ?? `${config.basePath}/signin`;
if (request.nextUrl.pathname !== signInPage) {
// Redirect to signin page by default if not authorized
const signInUrl = request.nextUrl.clone();
signInUrl.pathname = signInPage;
signInUrl.searchParams.set("callbackUrl", request.nextUrl.href);
response = NextResponse.redirect(signInUrl);
}
}
const finalResponse = new Response(response?.body, response);
// Preserve cookies from the session response
for (const cookie of sessionResponse.headers.getSetCookie())
finalResponse.headers.append("set-cookie", cookie);
return finalResponse;
}
function isSameAuthAction(requestPath, redirectPath, config) {
const action = redirectPath.replace(`${requestPath}/`, "");
const pages = Object.values(config.pages ?? {});
return ((actions.has(action) || pages.includes(redirectPath)) &&
redirectPath === requestPath);
}
const actions = new Set([
"providers",
"session",
"csrf",
"signin",
"signout",
"callback",
"verify-request",
"error",
]);