mirror of
https://github.com/LukeHagar/better-auth.git
synced 2025-12-10 12:27:44 +00:00
feat: wildcard matching for trusted origins
This commit is contained in:
@@ -4,7 +4,11 @@ import { createAuthClient } from "../../client";
|
|||||||
|
|
||||||
describe("Origin Check", async (it) => {
|
describe("Origin Check", async (it) => {
|
||||||
const { customFetchImpl, testUser } = await getTestInstance({
|
const { customFetchImpl, testUser } = await getTestInstance({
|
||||||
trustedOrigins: ["http://localhost:5000", "https://trusted.com"],
|
trustedOrigins: [
|
||||||
|
"http://localhost:5000",
|
||||||
|
"https://trusted.com",
|
||||||
|
"*.my-site.com",
|
||||||
|
],
|
||||||
emailAndPassword: {
|
emailAndPassword: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
async sendResetPassword(url, user) {},
|
async sendResetPassword(url, user) {},
|
||||||
@@ -166,4 +170,21 @@ describe("Origin Check", async (it) => {
|
|||||||
});
|
});
|
||||||
expect(res2.data?.session).toBeDefined();
|
expect(res2.data?.session).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should work with wildcard trusted origins", async (ctx) => {
|
||||||
|
const client = createAuthClient({
|
||||||
|
baseURL: "https://sub-domain.my-site.com",
|
||||||
|
fetchOptions: {
|
||||||
|
customFetchImpl,
|
||||||
|
headers: {
|
||||||
|
origin: "https://sub-domain.my-site.com",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const res = await client.forgetPassword({
|
||||||
|
email: testUser.email,
|
||||||
|
redirectTo: "https://sub-domain.my-site.com/reset-password",
|
||||||
|
});
|
||||||
|
expect(res.data?.status).toBeTruthy();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,16 +12,29 @@ export const originCheckMiddleware = createAuthMiddleware(async (ctx) => {
|
|||||||
const { body, query, context } = ctx;
|
const { body, query, context } = ctx;
|
||||||
const originHeader =
|
const originHeader =
|
||||||
ctx.headers?.get("origin") || ctx.headers?.get("referer") || "";
|
ctx.headers?.get("origin") || ctx.headers?.get("referer") || "";
|
||||||
const callbackURL = body?.callbackURL;
|
const callbackURL = body?.callbackURL || query?.callbackURL;
|
||||||
const redirectURL = body?.redirectTo;
|
const redirectURL = body?.redirectTo;
|
||||||
const currentURL = query?.currentURL;
|
const currentURL = query?.currentURL;
|
||||||
const trustedOrigins = context.trustedOrigins;
|
const trustedOrigins = context.trustedOrigins;
|
||||||
const usesCookies = ctx.headers?.has("cookie");
|
const usesCookies = ctx.headers?.has("cookie");
|
||||||
|
|
||||||
|
const matchesPattern = (url: string, pattern: string): boolean => {
|
||||||
|
if (pattern.includes("*")) {
|
||||||
|
const regex = new RegExp(
|
||||||
|
"^" + pattern.replace(/\*/g, "[^/]+").replace(/\./g, "\\.") + "$",
|
||||||
|
);
|
||||||
|
return regex.test(url);
|
||||||
|
}
|
||||||
|
return url.startsWith(pattern);
|
||||||
|
};
|
||||||
const validateURL = (url: string | undefined, label: string) => {
|
const validateURL = (url: string | undefined, label: string) => {
|
||||||
|
if (!url) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const isTrustedOrigin = trustedOrigins.some(
|
const isTrustedOrigin = trustedOrigins.some(
|
||||||
(origin) =>
|
(origin) =>
|
||||||
url?.startsWith(origin) || (url?.startsWith("/") && label !== "origin"),
|
matchesPattern(url, origin) ||
|
||||||
|
(url?.startsWith("/") && label !== "origin" && !url.includes(":")),
|
||||||
);
|
);
|
||||||
if (!isTrustedOrigin) {
|
if (!isTrustedOrigin) {
|
||||||
logger.error(`Invalid ${label}: ${url}`);
|
logger.error(`Invalid ${label}: ${url}`);
|
||||||
|
|||||||
Reference in New Issue
Block a user