better-auth
Version:
The most comprehensive authentication library for TypeScript.
202 lines (196 loc) • 7.16 kB
JavaScript
;
const z = require('zod/v4');
require('better-call');
const socialProviders_index = require('../../shared/better-auth.Bafolo-S.cjs');
const env = require('../../shared/better-auth.DiSjtgs9.cjs');
require('@better-auth/utils/base64');
require('@better-auth/utils/hmac');
const url = require('../../shared/better-auth.C-R0J0n1.cjs');
require('@better-auth/utils/binary');
require('../../shared/better-auth.BIMq4RPW.cjs');
require('../../shared/better-auth.CXhVNgXP.cjs');
require('defu');
const crypto_index = require('../../crypto/index.cjs');
require('../../shared/better-auth.C1hdVENX.cjs');
require('@better-auth/utils/hash');
require('@better-fetch/fetch');
require('jose');
require('@noble/ciphers/chacha');
require('@noble/ciphers/utils');
require('@noble/ciphers/webcrypto');
require('@noble/hashes/scrypt');
require('@better-auth/utils');
require('@better-auth/utils/hex');
require('@noble/hashes/utils');
require('../../shared/better-auth.CYeOI8C-.cjs');
require('@better-auth/utils/random');
require('../../cookies/index.cjs');
require('../../shared/better-auth.ANpbi45u.cjs');
require('../../shared/better-auth.D3mtHEZg.cjs');
require('jose/errors');
function _interopNamespaceCompat(e) {
if (e && typeof e === 'object' && 'default' in e) return e;
const n = Object.create(null);
if (e) {
for (const k in e) {
n[k] = e[k];
}
}
n.default = e;
return n;
}
const z__namespace = /*#__PURE__*/_interopNamespaceCompat(z);
function getVenderBaseURL() {
const vercel = env.env.VERCEL_URL ? `https://${env.env.VERCEL_URL}` : void 0;
const netlify = env.env.NETLIFY_URL;
const render = env.env.RENDER_URL;
const aws = env.env.AWS_LAMBDA_FUNCTION_NAME;
const google = env.env.GOOGLE_CLOUD_FUNCTION_NAME;
const azure = env.env.AZURE_FUNCTION_NAME;
return vercel || netlify || render || aws || google || azure;
}
const oAuthProxy = (opts) => {
const resolveCurrentURL = (ctx) => {
return new URL(
opts?.currentURL || ctx.request?.url || getVenderBaseURL() || ctx.context.baseURL
);
};
return {
id: "oauth-proxy",
endpoints: {
oAuthProxy: socialProviders_index.createAuthEndpoint(
"/oauth-proxy-callback",
{
method: "GET",
query: z__namespace.object({
callbackURL: z__namespace.string().meta({
description: "The URL to redirect to after the proxy"
}),
cookies: z__namespace.string().meta({
description: "The cookies to set after the proxy"
})
}),
use: [socialProviders_index.originCheck((ctx) => ctx.query.callbackURL)],
metadata: {
openapi: {
description: "OAuth Proxy Callback",
parameters: [
{
in: "query",
name: "callbackURL",
required: true,
description: "The URL to redirect to after the proxy"
},
{
in: "query",
name: "cookies",
required: true,
description: "The cookies to set after the proxy"
}
],
responses: {
302: {
description: "Redirect",
headers: {
Location: {
description: "The URL to redirect to",
schema: {
type: "string"
}
}
}
}
}
}
}
},
async (ctx) => {
const cookies = ctx.query.cookies;
const decryptedCookies = await crypto_index.symmetricDecrypt({
key: ctx.context.secret,
data: cookies
}).catch((e) => {
ctx.context.logger.error(e);
return null;
});
const error = ctx.context.options.onAPIError?.errorURL || `${ctx.context.options.baseURL}/api/auth/error`;
if (!decryptedCookies) {
throw ctx.redirect(
`${error}?error=OAuthProxy - Invalid cookies or secret`
);
}
const isSecureContext = resolveCurrentURL(ctx).protocol === "https:";
const prefix = ctx.context.options.advanced?.cookiePrefix || "better-auth";
const cookieToSet = isSecureContext ? decryptedCookies : decryptedCookies.replace("Secure;", "").replace(`__Secure-${prefix}`, prefix);
ctx.setHeader("set-cookie", cookieToSet);
throw ctx.redirect(ctx.query.callbackURL);
}
)
},
hooks: {
after: [
{
matcher(context) {
return context.path?.startsWith("/callback") || context.path?.startsWith("/oauth2/callback");
},
handler: socialProviders_index.createAuthMiddleware(async (ctx) => {
const headers = ctx.context.responseHeaders;
const location = headers?.get("location");
if (location?.includes("/oauth-proxy-callback?callbackURL")) {
if (!location.startsWith("http")) {
return;
}
const locationURL = new URL(location);
const origin = locationURL.origin;
if (origin === url.getOrigin(ctx.context.baseURL)) {
const newLocation = locationURL.searchParams.get("callbackURL");
if (!newLocation) {
return;
}
ctx.setHeader("location", newLocation);
return;
}
const setCookies = headers?.get("set-cookie");
if (!setCookies) {
return;
}
const encryptedCookies = await crypto_index.symmetricEncrypt({
key: ctx.context.secret,
data: setCookies
});
const locationWithCookies = `${location}&cookies=${encodeURIComponent(
encryptedCookies
)}`;
ctx.setHeader("location", locationWithCookies);
}
})
}
],
before: [
{
matcher(context) {
return context.path?.startsWith("/sign-in/social") || context.path?.startsWith("/sign-in/oauth2");
},
handler: socialProviders_index.createAuthMiddleware(async (ctx) => {
const skipProxy = ctx.request?.headers.get("x-skip-oauth-proxy");
if (skipProxy) {
return;
}
const url = resolveCurrentURL(ctx);
const productionURL = opts?.productionURL || env.env.BETTER_AUTH_URL;
if (productionURL === ctx.context.options.baseURL) {
return;
}
ctx.body.callbackURL = `${url.origin}${ctx.context.options.basePath || "/api/auth"}/oauth-proxy-callback?callbackURL=${encodeURIComponent(
ctx.body.callbackURL || ctx.context.baseURL
)}`;
return {
context: ctx
};
})
}
]
}
};
};
exports.oAuthProxy = oAuthProxy;