zerobyte/app/server/lib/auth/middlewares/validate-sso-callback-urls.ts
Nico 7a3932f969
feat: OIDC (#564)
* feat: oidc

feat: organization switcher

refactor: org context

feat: invitations

GLM

* feat: link current account

* refactor: own page for sso registration

* feat: per-user account management

* refactor: code style

* refactor: user existing check

* refactor: restrict provider configuration to super admins only

* refactor: cleanup / pr review

* chore: fix lint issues

* chore: pr feedbacks

* test(e2e): automated tests for OIDC

* fix: check url first for sso provider identification

* fix: prevent oidc provider to be named "credential"
2026-02-27 23:13:54 +01:00

36 lines
1 KiB
TypeScript

import { APIError } from "better-auth/api";
import type { AuthMiddlewareContext } from "~/server/lib/auth";
function isValidCallbackPath(value: string): boolean {
if (!value.startsWith("/") || value.startsWith("//") || value.includes("\\")) {
return false;
}
if (value.startsWith("/sso/callback/") || value.startsWith("/sso/saml2/")) {
return false;
}
return true;
}
export const validateSsoCallbackUrls = async (ctx: AuthMiddlewareContext) => {
if (ctx.path !== "/sign-in/sso") {
return;
}
const sources = [ctx.body, ctx.query].filter((s) => s && typeof s === "object");
for (const source of sources) {
const payload = source as Record<string, unknown>;
for (const field of ["callbackURL", "errorCallbackURL", "newUserCallbackURL"]) {
const value = payload[field];
if (value !== undefined && (typeof value !== "string" || !isValidCallbackPath(value))) {
throw new APIError("BAD_REQUEST", {
message: `Invalid ${field}. Only relative paths like /login are allowed.`,
});
}
}
}
};