@auth/core
Version:
Authentication for the Web.
135 lines (134 loc) • 5.18 kB
JavaScript
/**
*
* :::warning Experimental
* `@auth/core` is under active development.
* :::
*
* This is the main entry point to the Auth.js library.
*
* Based on the {@link https://developer.mozilla.org/en-US/docs/Web/API/Request Request}
* and {@link https://developer.mozilla.org/en-US/docs/Web/API/Response Response} Web standard APIs.
* Primarily used to implement [framework](https://authjs.dev/concepts/frameworks)-specific packages,
* but it can also be used directly.
*
* ## Installation
*
* ```bash npm2yarn
* npm install @auth/core
* ```
*
* ## Usage
*
* ```ts
* import { Auth } from "@auth/core"
*
* const request = new Request("https://example.com")
* const response = await Auth(request, {...})
*
* console.log(response instanceof Response) // true
* ```
*
* ## Resources
*
* - [Getting started](https://authjs.dev/getting-started/introduction)
* - [Most common use case guides](https://authjs.dev/guides)
*
* @module @auth/core
*/
import { assertConfig } from "./lib/utils/assert.js";
import { AuthError, ErrorPageLoop } from "./errors.js";
import { AuthInternal, raw, skipCSRFCheck } from "./lib/index.js";
import { setEnvDefaults, createActionURL } from "./lib/utils/env.js";
import renderPage from "./lib/pages/index.js";
import { logger, setLogger } from "./lib/utils/logger.js";
import { toInternalRequest, toResponse } from "./lib/utils/web.js";
import { isAuthAction } from "./lib/utils/actions.js";
export { skipCSRFCheck, raw, setEnvDefaults, createActionURL, isAuthAction };
/**
* Core functionality provided by Auth.js.
*
* Receives a standard {@link Request} and returns a {@link Response}.
*
* @example
* ```ts
* import Auth from "@auth/core"
*
* const request = new Request("https://example.com")
* const response = await AuthHandler(request, {
* providers: [...],
* secret: "...",
* trustHost: true,
* })
*```
* @see [Documentation](https://authjs.dev)
*/
export async function Auth(request, config) {
setLogger(config.logger, config.debug);
const internalRequest = await toInternalRequest(request, config);
if (internalRequest instanceof Error) {
logger.error(internalRequest);
return Response.json(`Error: This action with HTTP ${request.method} is not supported.`, { status: 400 });
}
const assertionResult = assertConfig(internalRequest, config);
if (Array.isArray(assertionResult)) {
assertionResult.forEach(logger.warn);
}
else if (assertionResult instanceof Error) {
// Bail out early if there's an error in the user config
logger.error(assertionResult);
const htmlPages = ["signin", "signout", "error", "verify-request"];
if (!htmlPages.includes(internalRequest.action) ||
internalRequest.method !== "GET") {
return Response.json({
message: "There was a problem with the server configuration. Check the server logs for more information.",
}, { status: 500 });
}
const { pages, theme } = config;
const authOnErrorPage = pages?.error &&
internalRequest.url.searchParams
.get("callbackUrl")
?.startsWith(pages.error);
if (!pages?.error || authOnErrorPage) {
if (authOnErrorPage) {
logger.error(new ErrorPageLoop(`The error page ${pages?.error} should not require authentication`));
}
const render = renderPage({ theme });
const page = render.error("Configuration");
return toResponse(page);
}
return Response.redirect(`${pages.error}?error=Configuration`);
}
const isRedirect = request.headers?.has("X-Auth-Return-Redirect");
const isRaw = config.raw === raw;
let response;
try {
const rawResponse = await AuthInternal(internalRequest, config);
if (isRaw)
return rawResponse;
response = await toResponse(rawResponse);
}
catch (e) {
const error = e;
logger.error(error);
const isAuthError = error instanceof AuthError;
if (isAuthError && isRaw && !isRedirect)
throw error;
// If the CSRF check failed for POST/session, return a 400 status code.
// We should not redirect to a page as this is an API route
if (request.method === "POST" && internalRequest.action === "session")
return Response.json(null, { status: 400 });
const type = isAuthError ? error.type : "Configuration";
const page = (isAuthError && error.kind) || "error";
// TODO: Filter out some error types from being sent to the client
const params = new URLSearchParams({ error: type });
const path = config.pages?.[page] ?? `${config.basePath}/${page.toLowerCase()}`;
const url = `${internalRequest.url.origin}${path}?${params}`;
if (isRedirect)
return Response.json({ url });
return Response.redirect(url);
}
const redirect = response.headers.get("Location");
if (!isRedirect || !redirect)
return response;
return Response.json({ url: redirect }, { headers: response.headers });
}