mirror of
https://github.com/better-auth/better-auth.git
synced 2026-10-19 11:24:57 -05:00
fix: handle skipOriginCheck array (#8582)
This commit is contained in:
@@ -537,6 +537,61 @@ describe("origin check middleware", async () => {
|
||||
);
|
||||
expect(sampleInternalEndpointInvalid.error?.status).toBe(403);
|
||||
});
|
||||
|
||||
it("should skip origin check for matched paths when skipOriginCheck is set to an array", async () => {
|
||||
const { client } = await getTestInstance({
|
||||
trustedOrigins: ["https://trusted-site.com"],
|
||||
advanced: {
|
||||
disableOriginCheck: false,
|
||||
},
|
||||
plugins: [
|
||||
{
|
||||
id: "test",
|
||||
init() {
|
||||
return {
|
||||
context: {
|
||||
skipOriginCheck: ["/public/data"],
|
||||
},
|
||||
};
|
||||
},
|
||||
endpoints: {
|
||||
publicEndpoint: createAuthEndpoint(
|
||||
"/public/data",
|
||||
{
|
||||
method: "GET",
|
||||
query: z.object({
|
||||
callbackURL: z.string(),
|
||||
}),
|
||||
use: [originCheck((c) => c.query.callbackURL)],
|
||||
},
|
||||
async (c) => c.query.callbackURL,
|
||||
),
|
||||
protectedEndpoint: createAuthEndpoint(
|
||||
"/protected/data",
|
||||
{
|
||||
method: "GET",
|
||||
query: z.object({
|
||||
callbackURL: z.string(),
|
||||
}),
|
||||
use: [originCheck((c) => c.query.callbackURL)],
|
||||
},
|
||||
async (c) => c.query.callbackURL,
|
||||
),
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const skipped = await client.$fetch(
|
||||
"/public/data?callbackURL=https://malicious.com",
|
||||
);
|
||||
expect(skipped.data).toBe("https://malicious.com");
|
||||
|
||||
const blocked = await client.$fetch(
|
||||
"/protected/data?callbackURL=https://malicious.com",
|
||||
);
|
||||
expect(blocked.error?.status).toBe(403);
|
||||
});
|
||||
});
|
||||
|
||||
describe("trusted origins with baseURL inferred from request", async () => {
|
||||
|
||||
@@ -18,6 +18,29 @@ function shouldSkipCSRFForBackwardCompat(ctx: GenericEndpointContext): boolean {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the origin check should be skipped for the current request.
|
||||
* Handles both boolean (skip all) and array (skip specific paths) configurations.
|
||||
*/
|
||||
function shouldSkipOriginCheck(ctx: GenericEndpointContext): boolean {
|
||||
const skipOriginCheck = ctx.context.skipOriginCheck;
|
||||
if (skipOriginCheck === true) {
|
||||
return true;
|
||||
}
|
||||
if (Array.isArray(skipOriginCheck) && ctx.request) {
|
||||
try {
|
||||
const basePath = new URL(ctx.context.baseURL).pathname;
|
||||
const currentPath = normalizePathname(ctx.request.url, basePath);
|
||||
return skipOriginCheck.some((skipPath) =>
|
||||
currentPath.startsWith(skipPath),
|
||||
);
|
||||
} catch {
|
||||
//
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs deprecation warning for users relying on coupled behavior.
|
||||
* Only logs if user explicitly set disableOriginCheck (not test environment default).
|
||||
@@ -45,7 +68,7 @@ export const originCheckMiddleware = createAuthMiddleware(async (ctx) => {
|
||||
}
|
||||
await validateOrigin(ctx);
|
||||
|
||||
if (ctx.context.skipOriginCheck) {
|
||||
if (shouldSkipOriginCheck(ctx)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -117,7 +140,7 @@ export const originCheck = (
|
||||
if (!ctx.request) {
|
||||
return;
|
||||
}
|
||||
if (ctx.context.skipOriginCheck) {
|
||||
if (shouldSkipOriginCheck(ctx)) {
|
||||
return;
|
||||
}
|
||||
const callbackURL = getValue(ctx);
|
||||
@@ -199,20 +222,8 @@ async function validateOrigin(
|
||||
return;
|
||||
}
|
||||
|
||||
const skipOriginCheck = ctx.context.skipOriginCheck;
|
||||
if (Array.isArray(skipOriginCheck)) {
|
||||
try {
|
||||
const basePath = new URL(ctx.context.baseURL).pathname;
|
||||
const currentPath = normalizePathname(ctx.request.url, basePath);
|
||||
const shouldSkipPath = skipOriginCheck.some((skipPath) =>
|
||||
currentPath.startsWith(skipPath),
|
||||
);
|
||||
if (shouldSkipPath) {
|
||||
return;
|
||||
}
|
||||
} catch {
|
||||
// If parsing fails, don't skip - continue with validation
|
||||
}
|
||||
if (shouldSkipOriginCheck(ctx)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const shouldValidate = forceValidate || useCookies;
|
||||
|
||||
Reference in New Issue
Block a user