Socket
Socket
Sign inDemoInstall

@auth/core

Package Overview
Dependencies
Maintainers
0
Versions
92
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@auth/core - npm Package Compare versions

Comparing version 0.34.2 to 0.35.0

providers/concept2.d.ts

7

index.js

@@ -43,3 +43,3 @@ /**

import renderPage from "./lib/pages/index.js";
import { logger, setLogger } from "./lib/utils/logger.js";
import { setLogger } from "./lib/utils/logger.js";
import { toInternalRequest, toResponse } from "./lib/utils/web.js";

@@ -67,3 +67,3 @@ import { isAuthAction } from "./lib/utils/actions.js";

export async function Auth(request, config) {
setLogger(config.logger, config.debug);
const logger = setLogger(config);
const internalRequest = await toInternalRequest(request, config);

@@ -106,3 +106,4 @@ // There was an error parsing the request

}
return Response.redirect(`${pages.error}?error=Configuration`);
const url = `${internalRequest.url.origin}${pages.error}?error=Configuration`;
return Response.redirect(url);
}

@@ -109,0 +110,0 @@ const isRedirect = request.headers?.has("X-Auth-Return-Redirect");

@@ -44,3 +44,7 @@ /**

export declare function decode<Payload = JWT>(params: JWTDecodeParams): Promise<Payload | null>;
export interface GetTokenParams<R extends boolean = false> extends Pick<JWTDecodeParams, "salt" | "secret"> {
type GetTokenParamsBase = {
secret: JWTDecodeParams["secret"];
salt?: JWTDecodeParams["salt"];
};
export interface GetTokenParams<R extends boolean = false> extends GetTokenParamsBase {
/** The request containing the JWT either in the cookies or in the `Authorization` header. */

@@ -128,2 +132,3 @@ req: Request | {

}
export {};
//# sourceMappingURL=jwt.d.ts.map

@@ -40,3 +40,3 @@ /**

import { EncryptJWT, base64url, calculateJwkThumbprint, jwtDecrypt } from "jose";
import { SessionStore } from "./lib/utils/cookie.js";
import { defaultCookies, SessionStore } from "./lib/utils/cookie.js";
import { MissingSecret } from "./errors.js";

@@ -86,5 +86,3 @@ import { parse } from "cookie";

export async function getToken(params) {
const { secureCookie, cookieName = secureCookie
? "__Secure-authjs.session-token"
: "authjs.session-token", decode: _decode = decode, salt = cookieName, secret, logger = console, raw, req, } = params;
const { secureCookie, cookieName = defaultCookies(secureCookie ?? false).sessionToken.name, decode: _decode = decode, salt = cookieName, secret, logger = console, raw, req, } = params;
if (!req)

@@ -91,0 +89,0 @@ throw new Error("Must pass `req` to JWT getToken()");

@@ -22,3 +22,2 @@ import * as checks from "./checks.js";

// We assume that issuer is always defined as this has been asserted earlier
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const issuer = new URL(provider.issuer);

@@ -25,0 +24,0 @@ const discoveryResponse = await o.discoveryRequest(issuer);

@@ -163,3 +163,2 @@ import * as jose from "jose";

export function handleState(query, provider, isOnRedirectProxy) {
let randomState;
let proxyRedirect;

@@ -170,3 +169,3 @@ if (provider.redirectProxyUrl && !query?.state) {

const state = decodeState(query?.state);
randomState = state?.random;
const randomState = state?.random;
if (isOnRedirectProxy) {

@@ -173,0 +172,0 @@ if (!state?.origin)

@@ -16,3 +16,2 @@ import * as checks from "../callback/oauth/checks.js";

// We check this in assert.ts
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const issuer = new URL(provider.issuer);

@@ -19,0 +18,0 @@ const discoveryResponse = await o.discoveryRequest(issuer);

@@ -7,3 +7,5 @@ import { getLoggedInUser } from "../utils/session.js";

*/
export async function webAuthnOptions(request, options, sessionStore, cookies) {
export async function webAuthnOptions(request, options, sessionStore, cookies
// @ts-expect-error issue with returning from a switch case
) {
// Return an error if the adapter is missing or if the provider

@@ -48,2 +50,3 @@ // is not a webauthn provider.

}
break;
default:

@@ -50,0 +53,0 @@ return {

@@ -7,3 +7,3 @@ import * as jwt from "../jwt.js";

import parseProviders from "./utils/providers.js";
import { logger } from "./utils/logger.js";
import { setLogger } from "./utils/logger.js";
import { merge } from "./utils/merge.js";

@@ -37,2 +37,3 @@ export const defaultCallbacks = {

export async function init({ authOptions, providerId, action, url, cookies: reqCookies, callbackUrl: reqCallbackUrl, csrfToken: reqCsrfToken, csrfDisabled, isPost, }) {
const logger = setLogger(authOptions);
const { providers, provider } = parseProviders({

@@ -39,0 +40,0 @@ providers: authOptions.providers,

@@ -59,7 +59,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "preact/jsx-runtime";

"--provider-dark-bg-hover": `color-mix(in srgb, ${color} 30%, #000)`,
}, tabIndex: 0, children: [logo && (_jsx("img", { loading: "lazy", height: 24, width: 24, id: "provider-logo", src: logo })), _jsxs("span", { style: {
}, tabIndex: 0, children: [_jsxs("span", { style: {
filter: "invert(1) grayscale(1) brightness(1.3) contrast(9000)",
"mix-blend-mode": "luminosity",
opacity: 0.95,
}, children: ["Sign in with ", provider.name] })] })] })) : null, (provider.type === "email" ||
}, children: ["Sign in with ", provider.name] }), logo && _jsx("img", { loading: "lazy", height: 24, src: logo })] })] })) : null, (provider.type === "email" ||
provider.type === "credentials" ||

@@ -66,0 +66,0 @@ provider.type === "webauthn") &&

@@ -1,3 +0,3 @@

declare const _default: ":root {\n --border-width: 1px;\n --border-radius: 0.5rem;\n --color-error: #c94b4b;\n --color-info: #157efb;\n --color-info-hover: #0f6ddb;\n --color-info-text: #fff;\n}\n\n.__next-auth-theme-auto,\n.__next-auth-theme-light {\n --color-background: #ececec;\n --color-background-hover: rgba(236, 236, 236, 0.8);\n --color-background-card: #fff;\n --color-text: #000;\n --color-primary: #444;\n --color-control-border: #bbb;\n --color-button-active-background: #f9f9f9;\n --color-button-active-border: #aaa;\n --color-separator: #ccc;\n}\n\n.__next-auth-theme-dark {\n --color-background: #161b22;\n --color-background-hover: rgba(22, 27, 34, 0.8);\n --color-background-card: #0d1117;\n --color-text: #fff;\n --color-primary: #ccc;\n --color-control-border: #555;\n --color-button-active-background: #060606;\n --color-button-active-border: #666;\n --color-separator: #444;\n}\n\n@media (prefers-color-scheme: dark) {\n .__next-auth-theme-auto {\n --color-background: #161b22;\n --color-background-hover: rgba(22, 27, 34, 0.8);\n --color-background-card: #0d1117;\n --color-text: #fff;\n --color-primary: #ccc;\n --color-control-border: #555;\n --color-button-active-background: #060606;\n --color-button-active-border: #666;\n --color-separator: #444;\n }\n\n button,\n a.button {\n color: var(--provider-dark-color, var(--color-primary)) !important;\n background-color: var(\n --provider-dark-bg,\n var(--color-background)\n ) !important;\n }\n\n :is(button,a.button):hover {\n background-color: var(\n --provider-dark-bg-hover,\n var(--color-background-hover)\n ) !important;\n }\n\n :is(button,a.button) span {\n color: var(--provider-dark-bg) !important;\n }\n}\n\nhtml {\n box-sizing: border-box;\n}\n\n*,\n*:before,\n*:after {\n box-sizing: inherit;\n margin: 0;\n padding: 0;\n}\n\nbody {\n background-color: var(--color-background);\n margin: 0;\n padding: 0;\n font-family:\n ui-sans-serif,\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n \"Segoe UI\",\n Roboto,\n \"Helvetica Neue\",\n Arial,\n \"Noto Sans\",\n sans-serif,\n \"Apple Color Emoji\",\n \"Segoe UI Emoji\",\n \"Segoe UI Symbol\",\n \"Noto Color Emoji\";\n}\n\nh1 {\n margin-bottom: 1.5rem;\n padding: 0 1rem;\n font-weight: 400;\n color: var(--color-text);\n}\n\np {\n margin-bottom: 1.5rem;\n padding: 0 1rem;\n color: var(--color-text);\n}\n\nform {\n margin: 0;\n padding: 0;\n}\n\nlabel {\n font-weight: 500;\n text-align: left;\n margin-bottom: 0.25rem;\n display: block;\n color: var(--color-text);\n}\n\ninput[type] {\n box-sizing: border-box;\n display: block;\n width: 100%;\n padding: 0.5rem 1rem;\n border: var(--border-width) solid var(--color-control-border);\n background: var(--color-background-card);\n font-size: 1rem;\n border-radius: var(--border-radius);\n color: var(--color-text);\n}\n\np {\n font-size: 1.1rem;\n line-height: 2rem;\n}\n\na.button {\n text-decoration: none;\n line-height: 1rem;\n}\n\na.button:link,\n a.button:visited {\n background-color: var(--color-background);\n color: var(--color-primary);\n }\n\nbutton span {\n flex-grow: 1;\n}\n\nbutton,\na.button {\n padding: 0.75rem 1rem;\n color: var(--provider-color, var(--color-primary));\n background-color: var(--provider-bg, var(--color-background));\n border: 1px solid #00000031;\n font-size: 0.9rem;\n height: 50px;\n border-radius: var(--border-radius);\n transition: background-color 250ms ease-in-out;\n font-weight: 300;\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n:is(button,a.button):hover {\n background-color: var(--provider-bg-hover, var(--color-background-hover));\n cursor: pointer;\n }\n\n:is(button,a.button):active {\n cursor: pointer;\n }\n\n:is(button,a.button) span {\n color: #fff;\n }\n\n:is(button,a.button) #provider-logo {\n width: 25px;\n display: block;\n }\n\n#submitButton {\n color: var(--button-text-color, var(--color-info-text));\n background-color: var(--brand-color, var(--color-info));\n width: 100%;\n}\n\n#submitButton:hover {\n background-color: var(\n --button-hover-bg,\n var(--color-info-hover)\n ) !important;\n }\n\na.site {\n color: var(--color-primary);\n text-decoration: none;\n font-size: 1rem;\n line-height: 2rem;\n}\n\na.site:hover {\n text-decoration: underline;\n }\n\n.page {\n position: absolute;\n width: 100%;\n height: 100%;\n display: grid;\n place-items: center;\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n}\n\n.page > div {\n text-align: center;\n }\n\n.error a.button {\n padding-left: 2rem;\n padding-right: 2rem;\n margin-top: 0.5rem;\n }\n\n.error .message {\n margin-bottom: 1.5rem;\n }\n\n.signin input[type=\"text\"] {\n margin-left: auto;\n margin-right: auto;\n display: block;\n }\n\n.signin hr {\n display: block;\n border: 0;\n border-top: 1px solid var(--color-separator);\n margin: 2rem auto 1rem auto;\n overflow: visible;\n }\n\n.signin hr::before {\n content: \"or\";\n background: var(--color-background-card);\n color: #888;\n padding: 0 0.4rem;\n position: relative;\n top: -0.7rem;\n }\n\n.signin .error {\n background: #f5f5f5;\n font-weight: 500;\n border-radius: 0.3rem;\n background: var(--color-error);\n }\n\n.signin .error p {\n text-align: left;\n padding: 0.5rem 1rem;\n font-size: 0.9rem;\n line-height: 1.2rem;\n color: var(--color-info-text);\n }\n\n.signin > div,\n .signin form {\n display: block;\n }\n\n.signin > div input[type], .signin form input[type] {\n margin-bottom: 0.5rem;\n }\n\n.signin > div button, .signin form button {\n width: 100%;\n }\n\n.signin .provider + .provider {\n margin-top: 1rem;\n }\n\n.logo {\n display: inline-block;\n max-width: 150px;\n margin: 1.25rem 0;\n max-height: 70px;\n}\n\n.card {\n background-color: var(--color-background-card);\n border-radius: 1rem;\n padding: 1.25rem 2rem;\n}\n\n.card .header {\n color: var(--color-primary);\n }\n\n.card input[type]::-moz-placeholder {\n color: color-mix(\n in srgb,\n var(--color-text) 20%,\n var(--color-button-active-background)\n );\n }\n\n.card input[type]::placeholder {\n color: color-mix(\n in srgb,\n var(--color-text) 20%,\n var(--color-button-active-background)\n );\n }\n\n.card input[type] {\n background: color-mix(in srgb, var(--color-background-card) 95%, black);\n }\n\n.section-header {\n color: var(--color-text);\n}\n\n@media screen and (min-width: 450px) {\n .card {\n margin: 2rem 0;\n width: 368px;\n }\n}\n\n@media screen and (max-width: 450px) {\n .card {\n margin: 1rem 0;\n width: 343px;\n }\n}\n";
declare const _default: ":root {\n --border-width: 1px;\n --border-radius: 0.5rem;\n --color-error: #c94b4b;\n --color-info: #157efb;\n --color-info-hover: #0f6ddb;\n --color-info-text: #fff;\n}\n\n.__next-auth-theme-auto,\n.__next-auth-theme-light {\n --color-background: #ececec;\n --color-background-hover: rgba(236, 236, 236, 0.8);\n --color-background-card: #fff;\n --color-text: #000;\n --color-primary: #444;\n --color-control-border: #bbb;\n --color-button-active-background: #f9f9f9;\n --color-button-active-border: #aaa;\n --color-separator: #ccc;\n}\n\n.__next-auth-theme-dark {\n --color-background: #161b22;\n --color-background-hover: rgba(22, 27, 34, 0.8);\n --color-background-card: #0d1117;\n --color-text: #fff;\n --color-primary: #ccc;\n --color-control-border: #555;\n --color-button-active-background: #060606;\n --color-button-active-border: #666;\n --color-separator: #444;\n}\n\n@media (prefers-color-scheme: dark) {\n .__next-auth-theme-auto {\n --color-background: #161b22;\n --color-background-hover: rgba(22, 27, 34, 0.8);\n --color-background-card: #0d1117;\n --color-text: #fff;\n --color-primary: #ccc;\n --color-control-border: #555;\n --color-button-active-background: #060606;\n --color-button-active-border: #666;\n --color-separator: #444;\n }\n\n button,\n a.button {\n color: var(--provider-dark-color, var(--color-primary)) !important;\n background-color: var(\n --provider-dark-bg,\n var(--color-background)\n ) !important;\n }\n\n :is(button,a.button):hover {\n background-color: var(\n --provider-dark-bg-hover,\n var(--color-background-hover)\n ) !important;\n }\n\n :is(button,a.button) span {\n color: var(--provider-dark-bg) !important;\n }\n}\n\nhtml {\n box-sizing: border-box;\n}\n\n*,\n*:before,\n*:after {\n box-sizing: inherit;\n margin: 0;\n padding: 0;\n}\n\nbody {\n background-color: var(--color-background);\n margin: 0;\n padding: 0;\n font-family:\n ui-sans-serif,\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n \"Segoe UI\",\n Roboto,\n \"Helvetica Neue\",\n Arial,\n \"Noto Sans\",\n sans-serif,\n \"Apple Color Emoji\",\n \"Segoe UI Emoji\",\n \"Segoe UI Symbol\",\n \"Noto Color Emoji\";\n}\n\nh1 {\n margin-bottom: 1.5rem;\n padding: 0 1rem;\n font-weight: 400;\n color: var(--color-text);\n}\n\np {\n margin-bottom: 1.5rem;\n padding: 0 1rem;\n color: var(--color-text);\n}\n\nform {\n margin: 0;\n padding: 0;\n}\n\nlabel {\n font-weight: 500;\n text-align: left;\n margin-bottom: 0.25rem;\n display: block;\n color: var(--color-text);\n}\n\ninput[type] {\n box-sizing: border-box;\n display: block;\n width: 100%;\n padding: 0.5rem 1rem;\n border: var(--border-width) solid var(--color-control-border);\n background: var(--color-background-card);\n font-size: 1rem;\n border-radius: var(--border-radius);\n color: var(--color-text);\n}\n\np {\n font-size: 1.1rem;\n line-height: 2rem;\n}\n\na.button {\n text-decoration: none;\n line-height: 1rem;\n}\n\na.button:link,\n a.button:visited {\n background-color: var(--color-background);\n color: var(--color-primary);\n }\n\nbutton,\na.button {\n padding: 0.75rem 1rem;\n color: var(--provider-color, var(--color-primary));\n background-color: var(--provider-bg, var(--color-background));\n border: 1px solid #00000031;\n font-size: 0.9rem;\n height: 50px;\n border-radius: var(--border-radius);\n transition: background-color 250ms ease-in-out;\n font-weight: 300;\n position: relative;\n display: flex;\n align-items: center;\n justify-content: space-between;\n}\n\n:is(button,a.button):hover {\n background-color: var(--provider-bg-hover, var(--color-background-hover));\n cursor: pointer;\n }\n\n:is(button,a.button):active {\n cursor: pointer;\n }\n\n:is(button,a.button) span {\n color: #fff;\n }\n\n#submitButton {\n color: var(--button-text-color, var(--color-info-text));\n background-color: var(--brand-color, var(--color-info));\n width: 100%;\n}\n\n#submitButton:hover {\n background-color: var(\n --button-hover-bg,\n var(--color-info-hover)\n ) !important;\n }\n\na.site {\n color: var(--color-primary);\n text-decoration: none;\n font-size: 1rem;\n line-height: 2rem;\n}\n\na.site:hover {\n text-decoration: underline;\n }\n\n.page {\n position: absolute;\n width: 100%;\n height: 100%;\n display: grid;\n place-items: center;\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n}\n\n.page > div {\n text-align: center;\n }\n\n.error a.button {\n padding-left: 2rem;\n padding-right: 2rem;\n margin-top: 0.5rem;\n }\n\n.error .message {\n margin-bottom: 1.5rem;\n }\n\n.signin input[type=\"text\"] {\n margin-left: auto;\n margin-right: auto;\n display: block;\n }\n\n.signin hr {\n display: block;\n border: 0;\n border-top: 1px solid var(--color-separator);\n margin: 2rem auto 1rem auto;\n overflow: visible;\n }\n\n.signin hr::before {\n content: \"or\";\n background: var(--color-background-card);\n color: #888;\n padding: 0 0.4rem;\n position: relative;\n top: -0.7rem;\n }\n\n.signin .error {\n background: #f5f5f5;\n font-weight: 500;\n border-radius: 0.3rem;\n background: var(--color-error);\n }\n\n.signin .error p {\n text-align: left;\n padding: 0.5rem 1rem;\n font-size: 0.9rem;\n line-height: 1.2rem;\n color: var(--color-info-text);\n }\n\n.signin > div,\n .signin form {\n display: block;\n }\n\n.signin > div input[type], .signin form input[type] {\n margin-bottom: 0.5rem;\n }\n\n.signin > div button, .signin form button {\n width: 100%;\n }\n\n.signin .provider + .provider {\n margin-top: 1rem;\n }\n\n.logo {\n display: inline-block;\n max-width: 150px;\n margin: 1.25rem 0;\n max-height: 70px;\n}\n\n.card {\n background-color: var(--color-background-card);\n border-radius: 1rem;\n padding: 1.25rem 2rem;\n}\n\n.card .header {\n color: var(--color-primary);\n }\n\n.card input[type]::-moz-placeholder {\n color: color-mix(\n in srgb,\n var(--color-text) 20%,\n var(--color-button-active-background)\n );\n }\n\n.card input[type]::placeholder {\n color: color-mix(\n in srgb,\n var(--color-text) 20%,\n var(--color-button-active-background)\n );\n }\n\n.card input[type] {\n background: color-mix(in srgb, var(--color-background-card) 95%, black);\n }\n\n.section-header {\n color: var(--color-text);\n}\n\n@media screen and (min-width: 450px) {\n .card {\n margin: 2rem 0;\n width: 368px;\n }\n}\n\n@media screen and (max-width: 450px) {\n .card {\n margin: 1rem 0;\n width: 343px;\n }\n}\n";
export default _default;
//# sourceMappingURL=styles.d.ts.map

@@ -157,6 +157,2 @@ // Generated by `pnpm css`

button span {
flex-grow: 1;
}
button,

@@ -176,3 +172,3 @@ a.button {

align-items: center;
justify-content: center;
justify-content: space-between;
}

@@ -193,7 +189,2 @@

:is(button,a.button) #provider-logo {
width: 25px;
display: block;
}
#submitButton {

@@ -200,0 +191,0 @@ color: var(--button-text-color, var(--color-info-text));

@@ -129,3 +129,3 @@ import { defaultCookies } from "./cookie.js";

const { adapter, session } = options;
let requiredMethods = [];
const requiredMethods = [];
if (hasEmail ||

@@ -132,0 +132,0 @@ session?.strategy === "database" ||

@@ -12,5 +12,3 @@ /**

const escapedHost = host.replace(/\./g, "&#8203;.");
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
const brandColor = theme.brandColor || "#346df1";
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
const buttonText = theme.buttonText || "#fff";

@@ -17,0 +15,0 @@ const color = {

import type { AuthAction } from "../../types.js";
import type { AuthConfig } from "../../index.js";
/** Set default env variables on the config object */
export declare function setEnvDefaults(envObject: any, config: AuthConfig): void;
export declare function createActionURL(action: AuthAction, protocol: string, headers: Headers, envObject: any, basePath?: string): URL;
/**
* Set default env variables on the config object
* @param suppressWarnings intended for framework authors.
*/
export declare function setEnvDefaults(envObject: any, config: AuthConfig, suppressBasePathWarning?: boolean): void;
export declare function createActionURL(action: AuthAction, protocol: string, headers: Headers, envObject: any, config: Pick<AuthConfig, "basePath" | "logger">): URL;
//# sourceMappingURL=env.d.ts.map

@@ -1,10 +0,24 @@

import { logger } from "./logger.js";
/** Set default env variables on the config object */
export function setEnvDefaults(envObject, config) {
import { setLogger } from "./logger.js";
/**
* Set default env variables on the config object
* @param suppressWarnings intended for framework authors.
*/
export function setEnvDefaults(envObject, config, suppressBasePathWarning = false) {
try {
const url = envObject.AUTH_URL;
if (url && !config.basePath)
config.basePath = new URL(url).pathname;
if (url) {
if (config.basePath) {
if (!suppressBasePathWarning) {
const logger = setLogger(config);
logger.warn("env-url-basepath-redundant");
}
}
else {
config.basePath = new URL(url).pathname;
}
}
}
catch {
// Catching and swallowing potential URL parsing errors, we'll fall
// back to `/auth` below.
}

@@ -31,14 +45,19 @@ finally {

envObject.NODE_ENV !== "production"));
config.providers = config.providers.map((p) => {
const finalProvider = typeof p === "function" ? p({}) : p;
const ID = finalProvider.id.toUpperCase().replace(/-/g, "_");
config.providers = config.providers.map((provider) => {
const { id } = typeof provider === "function" ? provider({}) : provider;
const ID = id.toUpperCase().replace(/-/g, "_");
const clientId = envObject[`AUTH_${ID}_ID`];
const clientSecret = envObject[`AUTH_${ID}_SECRET`];
const issuer = envObject[`AUTH_${ID}_ISSUER`];
const apiKey = envObject[`AUTH_${ID}_KEY`];
const finalProvider = typeof provider === "function"
? provider({ clientId, clientSecret, issuer, apiKey })
: provider;
if (finalProvider.type === "oauth" || finalProvider.type === "oidc") {
finalProvider.clientId ?? (finalProvider.clientId = envObject[`AUTH_${ID}_ID`]);
finalProvider.clientSecret ?? (finalProvider.clientSecret = envObject[`AUTH_${ID}_SECRET`]);
if (finalProvider.type === "oidc") {
finalProvider.issuer ?? (finalProvider.issuer = envObject[`AUTH_${ID}_ISSUER`]);
}
finalProvider.clientId ?? (finalProvider.clientId = clientId);
finalProvider.clientSecret ?? (finalProvider.clientSecret = clientSecret);
finalProvider.issuer ?? (finalProvider.issuer = issuer);
}
else if (finalProvider.type === "email") {
finalProvider.apiKey ?? (finalProvider.apiKey = envObject[`AUTH_${ID}_KEY`]);
finalProvider.apiKey ?? (finalProvider.apiKey = apiKey);
}

@@ -48,4 +67,5 @@ return finalProvider;

}
export function createActionURL(action, protocol, headers, envObject, basePath) {
let envUrl = envObject.AUTH_URL ?? envObject.NEXTAUTH_URL;
export function createActionURL(action, protocol, headers, envObject, config) {
const basePath = config?.basePath;
const envUrl = envObject.AUTH_URL ?? envObject.NEXTAUTH_URL;
let url;

@@ -55,5 +75,6 @@ if (envUrl) {

if (basePath && basePath !== "/" && url.pathname !== "/") {
logger.warn(url.pathname === basePath
? "env-url-basepath-redundant"
: "env-url-basepath-mismatch");
if (url.pathname !== basePath) {
const logger = setLogger(config);
logger.warn("env-url-basepath-mismatch");
}
url.pathname = "/";

@@ -60,0 +81,0 @@ }

@@ -0,1 +1,2 @@

import type { AuthConfig } from "../../index.js";
export type WarningCode = "debug-enabled" | "csrf-disabled" | "experimental-webauthn" | "env-url-basepath-redundant" | "env-url-basepath-mismatch";

@@ -12,3 +13,2 @@ /**

}
export declare const logger: LoggerInstance;
/**

@@ -18,3 +18,3 @@ * Override the built-in logger with user's implementation.

*/
export declare function setLogger(newLogger?: Partial<LoggerInstance>, debug?: boolean): void;
export declare function setLogger(config: Pick<AuthConfig, "logger" | "debug">): LoggerInstance;
//# sourceMappingURL=logger.d.ts.map

@@ -6,3 +6,3 @@ import { AuthError } from "../../errors.js";

const reset = "\x1b[0m";
export const logger = {
const defaultLogger = {
error(error) {

@@ -36,12 +36,17 @@ const name = error instanceof AuthError ? error.type : error.name;

*/
export function setLogger(newLogger = {}, debug) {
export function setLogger(config) {
const newLogger = {
...defaultLogger,
};
// Turn off debug logging if `debug` isn't set to `true`
if (!debug)
logger.debug = () => { };
if (newLogger.error)
logger.error = newLogger.error;
if (newLogger.warn)
logger.warn = newLogger.warn;
if (newLogger.debug)
logger.debug = newLogger.debug;
if (!config.debug)
newLogger.debug = () => { };
if (config.logger?.error)
newLogger.error = config.logger.error;
if (config.logger?.warn)
newLogger.warn = config.logger.warn;
if (config.logger?.debug)
newLogger.debug = config.logger.debug;
config.logger ?? (config.logger = newLogger);
return newLogger;
}

@@ -1,3 +0,3 @@

/** Deep merge two objects */
export declare function merge(target: any, ...sources: any[]): any;
/** Deep merge two or more objects */
export declare function merge<T extends Record<string, unknown>>(target: T, ...sources: Array<Record<string, unknown> | undefined>): T & Record<string, unknown>;
//# sourceMappingURL=merge.d.ts.map

@@ -1,7 +0,5 @@

// Source: https://stackoverflow.com/a/34749873/5364135
/** Simple object check */
function isObject(item) {
return item && typeof item === "object" && !Array.isArray(item);
return item !== null && typeof item === "object";
}
/** Deep merge two objects */
/** Deep merge two or more objects */
export function merge(target, ...sources) {

@@ -14,9 +12,10 @@ if (!sources.length)

if (isObject(source[key])) {
if (!target[key])
Object.assign(target, { [key]: {} });
if (!isObject(target[key]))
target[key] = Array.isArray(source[key])
? []
: {};
merge(target[key], source[key]);
}
else {
Object.assign(target, { [key]: source[key] });
}
else if (source[key] !== undefined)
target[key] = source[key];
}

@@ -23,0 +22,0 @@ }

@@ -93,4 +93,6 @@ import { merge } from "./merge.js";

const result = {};
for (let [k, v] of Object.entries(o))
v !== undefined && (result[k] = v);
for (const [k, v] of Object.entries(o)) {
if (v !== undefined)
result[k] = v;
}
return result;

@@ -114,4 +116,5 @@ }

for (let [key, value] of Object.entries(e.params)) {
if (key === "claims")
if (key === "claims") {
value = JSON.stringify(value);
}
url.searchParams.set(key, String(value));

@@ -118,0 +121,0 @@ }

import { parse as parseCookie, serialize } from "cookie";
import { UnknownAction } from "../../errors.js";
import { logger } from "./logger.js";
import { setLogger } from "./logger.js";
import { isAuthAction } from "./actions.js";

@@ -38,2 +38,3 @@ async function getBody(req) {

catch (e) {
const logger = setLogger(config);
logger.error(e);

@@ -67,3 +68,3 @@ logger.debug("request", req);

body = new URLSearchParams(res.body).toString();
const status = res.redirect ? 302 : res.status ?? 200;
const status = res.redirect ? 302 : (res.status ?? 200);
const response = new Response(body, { headers, status });

@@ -70,0 +71,0 @@ if (res.redirect)

{
"name": "@auth/core",
"version": "0.34.2",
"version": "0.35.0",
"description": "Authentication for the Web.",

@@ -112,3 +112,2 @@ "keywords": [

"dev": "pnpm css && pnpm providers && tsc -w",
"test:e2e": "playwright test -c ../utils/playwright.config.ts",
"test": "vitest run -c ../utils/vitest.config.ts",

@@ -115,0 +114,0 @@ "test:watch": "vitest -c ../utils/vitest.config.ts",

@@ -113,2 +113,9 @@ /**

*
*
* Apple requires the client secret to be a JWT. You can generate one using the following script:
* https://bal.so/apple-gen-secret
*
* Read more: [Creating the Client Secret
](https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens#3262048)
*
* ### Resources

@@ -133,12 +140,3 @@ *

*/
export default function Apple<P extends AppleProfile>(options: Omit<OAuthUserConfig<P>, "clientSecret"> & {
/**
* Apple requires the client secret to be a JWT. You can generate one using the following script:
* https://bal.so/apple-gen-secret
*
* Read more: [Creating the Client Secret
](https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens#3262048)
*/
clientSecret: string;
}): OAuthConfig<P>;
export default function Apple<P extends AppleProfile>(options: OAuthUserConfig<P>): OAuthConfig<P>;
//# sourceMappingURL=apple.d.ts.map

@@ -37,2 +37,9 @@ /**

*
*
* Apple requires the client secret to be a JWT. You can generate one using the following script:
* https://bal.so/apple-gen-secret
*
* Read more: [Creating the Client Secret
](https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens#3262048)
*
* ### Resources

@@ -66,9 +73,4 @@ *

},
profile(profile) {
return {
id: profile.sub,
name: profile.name,
email: profile.email,
image: null,
};
client: {
token_endpoint_auth_method: "client_secret_post",
},

@@ -75,0 +77,0 @@ style: {

@@ -89,3 +89,3 @@ /**

id: "azure-ad-b2c",
name: "Azure Active Directory B2C",
name: "Azure AD B2C",
type: "oidc",

@@ -92,0 +92,0 @@ profile(profile) {

@@ -122,7 +122,11 @@ /**

// https://docs.microsoft.com/en-us/graph/api/profilephoto-get?view=graph-rest-1.0#examples
const response = await fetch(`https://graph.microsoft.com/v1.0/me/photos/${profilePhotoSize}x${profilePhotoSize}/$value`, { headers: { Authorization: `Bearer ${tokens.access_token}` } });
let response = null;
try {
response = await fetch(`https://graph.microsoft.com/v1.0/me/photos/${profilePhotoSize}x${profilePhotoSize}/$value`, { headers: { Authorization: `Bearer ${tokens.access_token}` } });
}
catch { }
// Confirm that profile photo was returned
let image;
let image = null;
// TODO: Do this without Buffer
if (response.ok && typeof Buffer !== "undefined") {
if (response && response.ok && typeof Buffer !== "undefined") {
try {

@@ -129,0 +133,0 @@ const pictureBuffer = await response.arrayBuffer();

@@ -50,10 +50,3 @@ /**

* const request = new Request(origin)
* const response = await Auth(request, {
* providers: [
* Descope({
* clientId: DESCOPE_ID,
* clientSecret: DESCOPE_SECRET,
* }),
* ],
* })
* const response = await Auth(request, { providers: [Descope({ clientId: AUTH_DESCOPE_ID, clientSecret: AUTH_DESCOPE_SECRET, issuer: AUTH_DESCOPE_ISSUER })] })
* ```

@@ -72,4 +65,5 @@ *

* ```
* DESCOPE_ID="<Descope Issuer's last url segment>" # Descope's Issuer can be found in "Authentication Methods > SSO > Identity Provider" (Can also be taken from "Project > Project ID")
* DESCOPE_SECRET="<Descope Access Key>" # Manage > Access Keys
* AUTH_DESCOPE_ID="<Descope Issuer's last url segment>" # Descope's Issuer can be found in "Authentication Methods > SSO > Identity Provider" (Can also be taken from "Project > Project ID")
* AUTH_DESCOPE_SECRET="<Descope Access Key>" # Manage > Access Keys
* AUTH_DESCOPE_ISSUER="<Descope Issuer URL>" # Applications -> OIDC Application -> Issuer
* ```

@@ -76,0 +70,0 @@ *

@@ -28,10 +28,3 @@ /**

* const request = new Request(origin)
* const response = await Auth(request, {
* providers: [
* Descope({
* clientId: DESCOPE_ID,
* clientSecret: DESCOPE_SECRET,
* }),
* ],
* })
* const response = await Auth(request, { providers: [Descope({ clientId: AUTH_DESCOPE_ID, clientSecret: AUTH_DESCOPE_SECRET, issuer: AUTH_DESCOPE_ISSUER })] })
* ```

@@ -50,4 +43,5 @@ *

* ```
* DESCOPE_ID="<Descope Issuer's last url segment>" # Descope's Issuer can be found in "Authentication Methods > SSO > Identity Provider" (Can also be taken from "Project > Project ID")
* DESCOPE_SECRET="<Descope Access Key>" # Manage > Access Keys
* AUTH_DESCOPE_ID="<Descope Issuer's last url segment>" # Descope's Issuer can be found in "Authentication Methods > SSO > Identity Provider" (Can also be taken from "Project > Project ID")
* AUTH_DESCOPE_SECRET="<Descope Access Key>" # Manage > Access Keys
* AUTH_DESCOPE_ISSUER="<Descope Issuer URL>" # Applications -> OIDC Application -> Issuer
* ```

@@ -77,2 +71,3 @@ *

export default function Descope(config) {
config.issuer ?? (config.issuer = `https://api.descope.com/${config.clientId}`);
return {

@@ -82,9 +77,6 @@ id: "descope",

type: "oidc",
issuer: `https://api.descope.com/${config.clientId}`,
style: {
bg: "#1C1C23",
text: "#ffffff",
},
style: { bg: "#1C1C23", text: "#ffffff" },
checks: ["pkce", "state"],
options: config,
};
}

@@ -58,5 +58,21 @@ /**

type: "oauth",
authorization: "https://www.dropbox.com/oauth2/authorize?token_access_type=offline&scope=account_info.read",
authorization: {
url: "https://www.dropbox.com/oauth2/authorize",
params: {
access_type: "offline",
scope: "account_info.read",
},
},
token: "https://api.dropboxapi.com/oauth2/token",
userinfo: "https://api.dropboxapi.com/2/users/get_current_account",
userinfo: {
url: "https://api.dropboxapi.com/2/users/get_current_account",
async request({ tokens, provider }) {
return await fetch(provider.userinfo?.url, {
method: "POST",
headers: {
Authorization: `Bearer ${tokens.access_token}`,
},
}).then(async (res) => await res.json());
},
},
profile(profile) {

@@ -63,0 +79,0 @@ return {

@@ -17,4 +17,4 @@ import type { CommonProviderOptions } from "./index.js";

name: string;
from: string;
maxAge: number;
from?: string;
maxAge?: number;
sendVerificationRequest: (params: {

@@ -37,5 +37,5 @@ identifier: string;

normalizeIdentifier?: (identifier: string) => string;
options: EmailUserConfig;
options?: EmailUserConfig;
}
export type EmailUserConfig = Omit<Partial<EmailConfig>, "options" | "type">;
//# sourceMappingURL=email.d.ts.map

@@ -67,4 +67,6 @@ /**

url: `https://api.foursquare.com/v2/users/self?v=${apiVersion}`,
request({ tokens, provider }) {
const url = new URL(provider.userinfo?.url);
async request({ tokens, provider }) {
if (!provider.userinfo)
return;
const url = new URL(provider.userinfo.url);
url.searchParams.append("oauth_token", tokens.access_token);

@@ -71,0 +73,0 @@ return fetch(url).then((res) => res.json());

@@ -64,3 +64,3 @@ /**

return {
id: profile.id.toString(),
id: profile.sub?.toString(),
name: profile.name ?? profile.username,

@@ -67,0 +67,0 @@ email: profile.email,

@@ -5,4 +5,4 @@ import type { Transport, TransportOptions } from "nodemailer";

import * as SESTransport from "nodemailer/lib/ses-transport/index.js";
import * as SMTPPool from "nodemailer/lib/smtp-pool/index.js";
import * as SMTPTransport from "nodemailer/lib/smtp-transport/index.js";
import * as SMTPPool from "nodemailer/lib/smtp-pool/index.js";
import * as StreamTransport from "nodemailer/lib/stream-transport/index.js";

@@ -23,3 +23,3 @@ import type { Awaitable, Theme } from "../types.js";

}) => Awaitable<void>;
options: NodemailerUserConfig;
options?: NodemailerUserConfig;
}

@@ -26,0 +26,0 @@ export type NodemailerUserConfig = Omit<Partial<NodemailerConfig>, "options" | "type">;

import { createTransport } from "nodemailer";
import { AuthError } from "../errors.js";
import { html, text } from "../lib/utils/email.js";
import { AuthError } from "../errors.js";
export default function Nodemailer(config) {

@@ -5,0 +5,0 @@ if (!config.server)

@@ -99,3 +99,3 @@ /**

},
async profile(profile, tokens) {
async profile(profile) {
return {

@@ -102,0 +102,0 @@ id: profile.id,

@@ -1,2 +0,2 @@

export type OAuthProviderType = "42-school" | "apple" | "asgardeo" | "auth0" | "authentik" | "azure-ad-b2c" | "azure-ad" | "azure-devops" | "bankid-no" | "battlenet" | "beyondidentity" | "box" | "boxyhq-saml" | "bungie" | "click-up" | "cognito" | "coinbase" | "descope" | "discord" | "dribbble" | "dropbox" | "duende-identity-server6" | "eveonline" | "facebook" | "faceit" | "foursquare" | "freshbooks" | "fusionauth" | "github" | "gitlab" | "google" | "hubspot" | "identity-server4" | "instagram" | "kakao" | "keycloak" | "line" | "linkedin" | "mailchimp" | "mailru" | "mastodon" | "mattermost" | "medium" | "microsoft-entra-id" | "naver" | "netlify" | "netsuite" | "nodemailer" | "notion" | "okta" | "onelogin" | "ory-hydra" | "osso" | "osu" | "passage" | "passkey" | "patreon" | "pinterest" | "pipedrive" | "postmark" | "reddit" | "resend" | "salesforce" | "sendgrid" | "simplelogin" | "slack" | "spotify" | "strava" | "threads" | "tiktok" | "todoist" | "trakt" | "twitch" | "twitter" | "united-effects" | "vk" | "webauthn" | "webex" | "wikimedia" | "wordpress" | "workos" | "yandex" | "zitadel" | "zoho" | "zoom";
export type OAuthProviderType = "42-school" | "apple" | "asgardeo" | "auth0" | "authentik" | "azure-ad-b2c" | "azure-ad" | "azure-devops" | "bankid-no" | "battlenet" | "beyondidentity" | "box" | "boxyhq-saml" | "bungie" | "click-up" | "cognito" | "coinbase" | "concept2" | "descope" | "discord" | "dribbble" | "dropbox" | "duende-identity-server6" | "eventbrite" | "eveonline" | "facebook" | "faceit" | "forwardemail" | "foursquare" | "freshbooks" | "fusionauth" | "github" | "gitlab" | "google" | "hubspot" | "identity-server4" | "instagram" | "kakao" | "keycloak" | "kinde" | "line" | "linkedin" | "mailchimp" | "mailgun" | "mailru" | "mastodon" | "mattermost" | "medium" | "microsoft-entra-id" | "naver" | "netlify" | "netsuite" | "nextcloud" | "nodemailer" | "notion" | "okta" | "onelogin" | "ory-hydra" | "osso" | "osu" | "passage" | "passkey" | "patreon" | "ping-id" | "pinterest" | "pipedrive" | "postmark" | "reddit" | "resend" | "roblox" | "salesforce" | "sendgrid" | "simplelogin" | "slack" | "spotify" | "strava" | "threads" | "tiktok" | "todoist" | "trakt" | "twitch" | "twitter" | "united-effects" | "vipps" | "vk" | "webauthn" | "webex" | "wechat" | "wikimedia" | "wordpress" | "workos" | "yandex" | "zitadel" | "zoho" | "zoom";
//# sourceMappingURL=oauth-types.d.ts.map

@@ -57,3 +57,3 @@ /**

*
* `issuer` should be the fully qualified domain – e.g. `demo.ossoapp.com`
* `issuer` should be the fully qualified domain e.g. `demo.ossoapp.com`
*

@@ -60,0 +60,0 @@ * :::

@@ -46,3 +46,3 @@ /**

*
* `issuer` should be the fully qualified domain – e.g. `demo.ossoapp.com`
* `issuer` should be the fully qualified domain e.g. `demo.ossoapp.com`
*

@@ -49,0 +49,0 @@ * :::

@@ -84,4 +84,5 @@ /**

token: {
url: "https://open.tiktokapis.com/v2/oauth/token/",
async request({ params, provider }) {
const res = await fetch(`https://open.tiktokapis.com/v2/oauth/token/`, {
const res = await fetch(provider.token?.url, {
method: "POST",

@@ -127,3 +128,3 @@ headers: {

image: profile.data.user.avatar_url,
email: profile.data.user.email || null,
email: profile.data.user.email || profile.data.user.username || null,
};

@@ -130,0 +131,0 @@ },

@@ -49,3 +49,3 @@ /**

import renderPage from "./lib/pages/index.js"
import { logger, setLogger, type LoggerInstance } from "./lib/utils/logger.js"
import { setLogger, type LoggerInstance } from "./lib/utils/logger.js"
import { toInternalRequest, toResponse } from "./lib/utils/web.js"

@@ -105,3 +105,3 @@

): Promise<Response | ResponseInternal> {
setLogger(config.logger, config.debug)
const logger = setLogger(config)

@@ -158,3 +158,4 @@ const internalRequest = await toInternalRequest(request, config)

return Response.redirect(`${pages.error}?error=Configuration`)
const url = `${internalRequest.url.origin}${pages.error}?error=Configuration`
return Response.redirect(url)
}

@@ -161,0 +162,0 @@

@@ -41,3 +41,3 @@ /**

import { EncryptJWT, base64url, calculateJwkThumbprint, jwtDecrypt } from "jose"
import { SessionStore } from "./lib/utils/cookie.js"
import { defaultCookies, SessionStore } from "./lib/utils/cookie.js"
import { Awaitable } from "./types.js"

@@ -111,4 +111,9 @@ import type { LoggerInstance } from "./lib/utils/logger.js"

type GetTokenParamsBase = {
secret: JWTDecodeParams["secret"]
salt?: JWTDecodeParams["salt"]
}
export interface GetTokenParams<R extends boolean = false>
extends Pick<JWTDecodeParams, "salt" | "secret"> {
extends GetTokenParamsBase {
/** The request containing the JWT either in the cookies or in the `Authorization` header. */

@@ -145,5 +150,3 @@ req: Request | { headers: Headers | Record<string, string> }

secureCookie,
cookieName = secureCookie
? "__Secure-authjs.session-token"
: "authjs.session-token",
cookieName = defaultCookies(secureCookie ?? false).sessionToken.name,
decode: _decode = decode,

@@ -150,0 +153,0 @@ salt = cookieName,

@@ -46,3 +46,3 @@ import * as checks from "./checks.js"

// We assume that issuer is always defined as this has been asserted earlier
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const issuer = new URL(provider.issuer!)

@@ -49,0 +49,0 @@ const discoveryResponse = await o.discoveryRequest(issuer)

@@ -247,3 +247,2 @@ import * as jose from "jose"

) {
let randomState: string | undefined
let proxyRedirect: string | undefined

@@ -258,3 +257,3 @@

const state = decodeState(query?.state)
randomState = state?.random
const randomState = state?.random

@@ -261,0 +260,0 @@ if (isOnRedirectProxy) {

@@ -25,3 +25,3 @@ import * as checks from "../callback/oauth/checks.js"

// We check this in assert.ts
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const issuer = new URL(provider.issuer!)

@@ -28,0 +28,0 @@ const discoveryResponse = await o.discoveryRequest(issuer)

@@ -25,2 +25,3 @@ import type {

cookies: Cookie[]
// @ts-expect-error issue with returning from a switch case
): Promise<ResponseInternal> {

@@ -89,2 +90,3 @@ // Return an error if the adapter is missing or if the provider

}
break
default:

@@ -91,0 +93,0 @@ return {

@@ -8,3 +8,3 @@ import * as jwt from "../jwt.js"

import parseProviders from "./utils/providers.js"
import { logger, type LoggerInstance } from "./utils/logger.js"
import { setLogger, type LoggerInstance } from "./utils/logger.js"
import { merge } from "./utils/merge.js"

@@ -69,2 +69,3 @@

}> {
const logger = setLogger(authOptions)
const { providers, provider } = parseProviders({

@@ -71,0 +72,0 @@ providers: authOptions.providers,

@@ -157,6 +157,2 @@ // Generated by `pnpm css`

button span {
flex-grow: 1;
}
button,

@@ -176,3 +172,3 @@ a.button {

align-items: center;
justify-content: center;
justify-content: space-between;
}

@@ -193,7 +189,2 @@

:is(button,a.button) #provider-logo {
width: 25px;
display: block;
}
#submitButton {

@@ -200,0 +191,0 @@ color: var(--button-text-color, var(--color-info-text));

@@ -211,3 +211,3 @@ import { defaultCookies } from "./cookie.js"

let requiredMethods: (keyof Adapter)[] = []
const requiredMethods: (keyof Adapter)[] = []

@@ -214,0 +214,0 @@ if (

@@ -16,5 +16,4 @@ import type { Theme } from "../../types.js"

// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
const brandColor = theme.brandColor || "#346df1"
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
const buttonText = theme.buttonText || "#fff"

@@ -21,0 +20,0 @@

import type { AuthAction } from "../../types.js"
import { MissingSecret } from "../../errors.js"
import { logger } from "./logger.js"
import type { AuthConfig } from "../../index.js"
import { setLogger } from "./logger.js"
/** Set default env variables on the config object */
export function setEnvDefaults(envObject: any, config: AuthConfig) {
/**
* Set default env variables on the config object
* @param suppressWarnings intended for framework authors.
*/
export function setEnvDefaults(
envObject: any,
config: AuthConfig,
suppressBasePathWarning = false
) {
try {
const url = envObject.AUTH_URL
if (url && !config.basePath) config.basePath = new URL(url).pathname
if (url) {
if (config.basePath) {
if (!suppressBasePathWarning) {
const logger = setLogger(config)
logger.warn("env-url-basepath-redundant")
}
} else {
config.basePath = new URL(url).pathname
}
}
} catch {
// Catching and swallowing potential URL parsing errors, we'll fall
// back to `/auth` below.
} finally {

@@ -34,13 +51,19 @@ config.basePath ??= `/auth`

)
config.providers = config.providers.map((p) => {
const finalProvider = typeof p === "function" ? p({}) : p
const ID = finalProvider.id.toUpperCase().replace(/-/g, "_")
config.providers = config.providers.map((provider) => {
const { id } = typeof provider === "function" ? provider({}) : provider
const ID = id.toUpperCase().replace(/-/g, "_")
const clientId = envObject[`AUTH_${ID}_ID`]
const clientSecret = envObject[`AUTH_${ID}_SECRET`]
const issuer = envObject[`AUTH_${ID}_ISSUER`]
const apiKey = envObject[`AUTH_${ID}_KEY`]
const finalProvider =
typeof provider === "function"
? provider({ clientId, clientSecret, issuer, apiKey })
: provider
if (finalProvider.type === "oauth" || finalProvider.type === "oidc") {
finalProvider.clientId ??= envObject[`AUTH_${ID}_ID`]
finalProvider.clientSecret ??= envObject[`AUTH_${ID}_SECRET`]
if (finalProvider.type === "oidc") {
finalProvider.issuer ??= envObject[`AUTH_${ID}_ISSUER`]
}
finalProvider.clientId ??= clientId
finalProvider.clientSecret ??= clientSecret
finalProvider.issuer ??= issuer
} else if (finalProvider.type === "email") {
finalProvider.apiKey ??= envObject[`AUTH_${ID}_KEY`]
finalProvider.apiKey ??= apiKey
}

@@ -56,5 +79,6 @@ return finalProvider

envObject: any,
basePath?: string
config: Pick<AuthConfig, "basePath" | "logger">
): URL {
let envUrl = envObject.AUTH_URL ?? envObject.NEXTAUTH_URL
const basePath = config?.basePath
const envUrl = envObject.AUTH_URL ?? envObject.NEXTAUTH_URL

@@ -65,7 +89,6 @@ let url: URL

if (basePath && basePath !== "/" && url.pathname !== "/") {
logger.warn(
url.pathname === basePath
? "env-url-basepath-redundant"
: "env-url-basepath-mismatch"
)
if (url.pathname !== basePath) {
const logger = setLogger(config)
logger.warn("env-url-basepath-mismatch")
}
url.pathname = "/"

@@ -72,0 +95,0 @@ }

import { AuthError } from "../../errors.js"
import type { AuthConfig } from "../../index.js"

@@ -15,2 +16,3 @@ export type WarningCode =

*/
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
export interface LoggerInstance extends Record<string, Function> {

@@ -27,3 +29,3 @@ warn: (code: WarningCode) => void

export const logger: LoggerInstance = {
const defaultLogger: LoggerInstance = {
error(error) {

@@ -66,11 +68,17 @@ const name = error instanceof AuthError ? error.type : error.name

export function setLogger(
newLogger: Partial<LoggerInstance> = {},
debug?: boolean
) {
config: Pick<AuthConfig, "logger" | "debug">
): LoggerInstance {
const newLogger: LoggerInstance = {
...defaultLogger,
}
// Turn off debug logging if `debug` isn't set to `true`
if (!debug) logger.debug = () => {}
if (!config.debug) newLogger.debug = () => {}
if (newLogger.error) logger.error = newLogger.error
if (newLogger.warn) logger.warn = newLogger.warn
if (newLogger.debug) logger.debug = newLogger.debug
if (config.logger?.error) newLogger.error = config.logger.error
if (config.logger?.warn) newLogger.warn = config.logger.warn
if (config.logger?.debug) newLogger.debug = config.logger.debug
config.logger ??= newLogger
return newLogger
}

@@ -1,10 +0,10 @@

// Source: https://stackoverflow.com/a/34749873/5364135
/** Simple object check */
function isObject(item: any): boolean {
return item && typeof item === "object" && !Array.isArray(item)
function isObject(item: unknown): item is object {
return item !== null && typeof item === "object"
}
/** Deep merge two objects */
export function merge(target: any, ...sources: any[]): any {
/** Deep merge two or more objects */
export function merge<T extends Record<string, unknown>>(
target: T,
...sources: Array<Record<string, unknown> | undefined>
): T & Record<string, unknown> {
if (!sources.length) return target

@@ -16,7 +16,12 @@ const source = sources.shift()

if (isObject(source[key])) {
if (!target[key]) Object.assign(target, { [key]: {} })
merge(target[key], source[key])
} else {
Object.assign(target, { [key]: source[key] })
}
if (!isObject(target[key]))
(target as Record<string, unknown>)[key] = Array.isArray(source[key])
? []
: {}
merge(
(target as Record<string, unknown>)[key] as T,
source[key] as Record<string, unknown>
)
} else if (source[key] !== undefined)
(target as Record<string, unknown>)[key] = source[key]
}

@@ -23,0 +28,0 @@ }

@@ -44,6 +44,6 @@ import { merge } from "./merge.js"

merged.redirectProxyUrl ??= options.redirectProxyUrl
return normalizeOAuth(merged)
return normalizeOAuth(merged) as InternalProvider
}
return merged
return merged as InternalProvider
})

@@ -61,3 +61,3 @@

c: OAuthConfig<any> | OAuthUserConfig<any>
): OAuthConfigInternal<any> | {} {
): OAuthConfigInternal<any> | object {
if (c.issuer) c.wellKnown ??= `${c.issuer}/.well-known/openid-configuration`

@@ -130,3 +130,5 @@

const result = {} as any
for (let [k, v] of Object.entries(o)) v !== undefined && (result[k] = v)
for (const [k, v] of Object.entries(o)) {
if (v !== undefined) result[k] = v
}
return result as T

@@ -153,3 +155,5 @@ }

for (let [key, value] of Object.entries(e.params)) {
if (key === "claims") value = JSON.stringify(value)
if (key === "claims") {
value = JSON.stringify(value)
}
url.searchParams.set(key, String(value))

@@ -156,0 +160,0 @@ }

import { parse as parseCookie, serialize } from "cookie"
import { UnknownAction } from "../../errors.js"
import { logger } from "./logger.js"
import { setLogger } from "./logger.js"

@@ -55,2 +55,3 @@ import type {

} catch (e) {
const logger = setLogger(config)
logger.error(e as Error)

@@ -89,3 +90,3 @@ logger.debug("request", req)

const status = res.redirect ? 302 : res.status ?? 200
const status = res.redirect ? 302 : (res.status ?? 200)
const response = new Response(body, { headers, status })

@@ -92,0 +93,0 @@

@@ -123,2 +123,9 @@ /**

*
*
* Apple requires the client secret to be a JWT. You can generate one using the following script:
* https://bal.so/apple-gen-secret
*
* Read more: [Creating the Client Secret
](https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens#3262048)
*
* ### Resources

@@ -144,12 +151,3 @@ *

export default function Apple<P extends AppleProfile>(
options: Omit<OAuthUserConfig<P>, "clientSecret"> & {
/**
* Apple requires the client secret to be a JWT. You can generate one using the following script:
* https://bal.so/apple-gen-secret
*
* Read more: [Creating the Client Secret
](https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens#3262048)
*/
clientSecret: string
}
options: OAuthUserConfig<P>
): OAuthConfig<P> {

@@ -164,9 +162,4 @@ return {

},
profile(profile) {
return {
id: profile.sub,
name: profile.name,
email: profile.email,
image: null,
}
client: {
token_endpoint_auth_method: "client_secret_post",
},

@@ -173,0 +166,0 @@ style: {

@@ -115,3 +115,3 @@ /**

id: "azure-ad-b2c",
name: "Azure Active Directory B2C",
name: "Azure AD B2C",
type: "oidc",

@@ -118,0 +118,0 @@ profile(profile) {

@@ -152,11 +152,15 @@ /**

// https://docs.microsoft.com/en-us/graph/api/profilephoto-get?view=graph-rest-1.0#examples
const response = await fetch(
`https://graph.microsoft.com/v1.0/me/photos/${profilePhotoSize}x${profilePhotoSize}/$value`,
{ headers: { Authorization: `Bearer ${tokens.access_token}` } }
)
let response = null
try {
response = await fetch(
`https://graph.microsoft.com/v1.0/me/photos/${profilePhotoSize}x${profilePhotoSize}/$value`,
{ headers: { Authorization: `Bearer ${tokens.access_token}` } }
)
} catch {}
// Confirm that profile photo was returned
let image
let image = null
// TODO: Do this without Buffer
if (response.ok && typeof Buffer !== "undefined") {
if (response && response.ok && typeof Buffer !== "undefined") {
try {

@@ -163,0 +167,0 @@ const pictureBuffer = await response.arrayBuffer()

@@ -53,10 +53,3 @@ /**

* const request = new Request(origin)
* const response = await Auth(request, {
* providers: [
* Descope({
* clientId: DESCOPE_ID,
* clientSecret: DESCOPE_SECRET,
* }),
* ],
* })
* const response = await Auth(request, { providers: [Descope({ clientId: AUTH_DESCOPE_ID, clientSecret: AUTH_DESCOPE_SECRET, issuer: AUTH_DESCOPE_ISSUER })] })
* ```

@@ -75,4 +68,5 @@ *

* ```
* DESCOPE_ID="<Descope Issuer's last url segment>" # Descope's Issuer can be found in "Authentication Methods > SSO > Identity Provider" (Can also be taken from "Project > Project ID")
* DESCOPE_SECRET="<Descope Access Key>" # Manage > Access Keys
* AUTH_DESCOPE_ID="<Descope Issuer's last url segment>" # Descope's Issuer can be found in "Authentication Methods > SSO > Identity Provider" (Can also be taken from "Project > Project ID")
* AUTH_DESCOPE_SECRET="<Descope Access Key>" # Manage > Access Keys
* AUTH_DESCOPE_ISSUER="<Descope Issuer URL>" # Applications -> OIDC Application -> Issuer
* ```

@@ -104,2 +98,3 @@ *

): OIDCConfig<DescopeProfile> {
config.issuer ??= `https://api.descope.com/${config.clientId}`
return {

@@ -109,9 +104,6 @@ id: "descope",

type: "oidc",
issuer: `https://api.descope.com/${config.clientId}`,
style: {
bg: "#1C1C23",
text: "#ffffff",
},
style: { bg: "#1C1C23", text: "#ffffff" },
checks: ["pkce", "state"],
options: config,
}
}

@@ -72,6 +72,21 @@ /**

type: "oauth",
authorization:
"https://www.dropbox.com/oauth2/authorize?token_access_type=offline&scope=account_info.read",
authorization: {
url: "https://www.dropbox.com/oauth2/authorize",
params: {
access_type: "offline",
scope: "account_info.read",
},
},
token: "https://api.dropboxapi.com/oauth2/token",
userinfo: "https://api.dropboxapi.com/2/users/get_current_account",
userinfo: {
url: "https://api.dropboxapi.com/2/users/get_current_account",
async request({ tokens, provider }) {
return await fetch(provider.userinfo?.url as URL, {
method: "POST",
headers: {
Authorization: `Bearer ${tokens.access_token}`,
},
}).then(async (res) => await res.json())
},
},
profile(profile) {

@@ -78,0 +93,0 @@ return {

@@ -33,4 +33,4 @@ import type { CommonProviderOptions } from "./index.js"

name: string
from: string
maxAge: number
from?: string
maxAge?: number
sendVerificationRequest: (params: {

@@ -53,5 +53,5 @@ identifier: string

normalizeIdentifier?: (identifier: string) => string
options: EmailUserConfig
options?: EmailUserConfig
}
export type EmailUserConfig = Omit<Partial<EmailConfig>, "options" | "type">

@@ -81,4 +81,6 @@ /**

url: `https://api.foursquare.com/v2/users/self?v=${apiVersion}`,
request({ tokens, provider }) {
const url = new URL(provider.userinfo?.url!)
async request({ tokens, provider }) {
if (!provider.userinfo) return
const url = new URL(provider.userinfo.url)
url.searchParams.append("oauth_token", tokens.access_token!)

@@ -85,0 +87,0 @@ return fetch(url).then((res) => res.json())

@@ -123,3 +123,3 @@ /**

return {
id: profile.id.toString(),
id: profile.sub?.toString(),
name: profile.name ?? profile.username,

@@ -126,0 +126,0 @@ email: profile.email,

import { createTransport } from "nodemailer"
import { AuthError } from "../errors.js"
import { html, text } from "../lib/utils/email.js"
import { AuthError } from "../errors.js"

@@ -9,4 +9,4 @@ import type { Transport, TransportOptions } from "nodemailer"

import * as SESTransport from "nodemailer/lib/ses-transport/index.js"
import * as SMTPPool from "nodemailer/lib/smtp-pool/index.js"
import * as SMTPTransport from "nodemailer/lib/smtp-transport/index.js"
import * as SMTPPool from "nodemailer/lib/smtp-pool/index.js"
import * as StreamTransport from "nodemailer/lib/stream-transport/index.js"

@@ -44,3 +44,3 @@ import type { Awaitable, Theme } from "../types.js"

}) => Awaitable<void>
options: NodemailerUserConfig
options?: NodemailerUserConfig
}

@@ -47,0 +47,0 @@

@@ -155,3 +155,3 @@ /**

async profile(profile, tokens) {
async profile(profile) {
return {

@@ -158,0 +158,0 @@ id: profile.id,

@@ -21,2 +21,3 @@

| "coinbase"
| "concept2"
| "descope"

@@ -27,5 +28,7 @@ | "discord"

| "duende-identity-server6"
| "eventbrite"
| "eveonline"
| "facebook"
| "faceit"
| "forwardemail"
| "foursquare"

@@ -42,5 +45,7 @@ | "freshbooks"

| "keycloak"
| "kinde"
| "line"
| "linkedin"
| "mailchimp"
| "mailgun"
| "mailru"

@@ -54,2 +59,3 @@ | "mastodon"

| "netsuite"
| "nextcloud"
| "nodemailer"

@@ -65,2 +71,3 @@ | "notion"

| "patreon"
| "ping-id"
| "pinterest"

@@ -71,2 +78,3 @@ | "pipedrive"

| "resend"
| "roblox"
| "salesforce"

@@ -85,5 +93,7 @@ | "sendgrid"

| "united-effects"
| "vipps"
| "vk"
| "webauthn"
| "webex"
| "wechat"
| "wikimedia"

@@ -90,0 +100,0 @@ | "wordpress"

@@ -58,3 +58,3 @@ /**

*
* `issuer` should be the fully qualified domain – e.g. `demo.ossoapp.com`
* `issuer` should be the fully qualified domain e.g. `demo.ossoapp.com`
*

@@ -61,0 +61,0 @@ * :::

@@ -215,4 +215,5 @@ /**

token: {
url: "https://open.tiktokapis.com/v2/oauth/token/",
async request({ params, provider }) {
const res = await fetch(`https://open.tiktokapis.com/v2/oauth/token/`, {
const res = await fetch(provider.token?.url as unknown as string, {
method: "POST",

@@ -259,3 +260,3 @@ headers: {

image: profile.data.user.avatar_url,
email: profile.data.user.email || null,
email: profile.data.user.email || profile.data.user.username || null,
}

@@ -262,0 +263,0 @@ },

@@ -122,3 +122,3 @@ /**

export interface Account extends Partial<OpenIDTokenEndpointResponse> {
/** Provider's id for this account. Eg.: "google" */
/** Provider's id for this account. E.g. "google". See the full list at https://authjs.dev/reference/core/providers */
provider: string

@@ -125,0 +125,0 @@ /**

@@ -95,3 +95,3 @@ /**

export interface Account extends Partial<OpenIDTokenEndpointResponse> {
/** Provider's id for this account. Eg.: "google" */
/** Provider's id for this account. E.g. "google". See the full list at https://authjs.dev/reference/core/providers */
provider: string;

@@ -98,0 +98,0 @@ /**

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc