fix(oauth-provider): redirect missing response_type errors (#10149)

This commit is contained in:
Gustavo Valverde
2026-06-19 08:55:26 -07:00
committed by GitHub
parent a8200b297c
commit 132e293d7a
3 changed files with 55 additions and 3 deletions
@@ -0,0 +1,5 @@
---
"@better-auth/oauth-provider": patch
---
OAuth Provider authorization requests that omit `response_type` now return `invalid_request` to the verified client redirect URI instead of falling back to the provider error page.
+4 -3
View File
@@ -388,10 +388,11 @@ export async function authorizeEndpoint(
}
if (!query.response_type) {
return handleRedirect(
return authorizeRedirectOnError(opts)({
error: "invalid_request",
error_description: "response_type is required",
ctx,
getErrorURL(ctx, "invalid_request", "response_type is required"),
);
});
}
const promptSet = ctx.query?.prompt
@@ -236,6 +236,52 @@ describe("RFC envelope compliance across OAuth endpoints", async () => {
);
});
it("missing response_type with trusted redirect_uri → invalid_request", async () => {
if (!oauthClient?.client_id) throw new Error("beforeAll didn't run");
const state = "missing-response-type";
const qs = new URLSearchParams({
client_id: oauthClient.client_id,
redirect_uri: redirectUri,
state,
}).toString();
const { status, location } = await captureRedirect(
`/oauth2/authorize?${qs}`,
);
expect(status).toBeGreaterThanOrEqual(300);
expect(status).toBeLessThan(400);
const redirectLocation = expectRedirectLocation(location);
expect(redirectLocation.startsWith(redirectUri)).toBe(true);
const errorUrl = new URL(redirectLocation);
expect(errorUrl.searchParams.get("error")).toBe("invalid_request");
expect(errorUrl.searchParams.get("error_description")).toMatch(
/response_type/,
);
expect(errorUrl.searchParams.get("state")).toBe(state);
expect(errorUrl.searchParams.get("iss")).toBeTruthy();
});
it("missing response_type with unregistered redirect_uri → server error page", async () => {
if (!oauthClient?.client_id) throw new Error("beforeAll didn't run");
const qs = new URLSearchParams({
client_id: oauthClient.client_id,
redirect_uri: "https://evil.example.com/callback",
state: "s",
}).toString();
const { status, location } = await captureRedirect(
`/oauth2/authorize?${qs}`,
);
expect(status).toBeGreaterThanOrEqual(300);
expect(status).toBeLessThan(400);
const redirectLocation = expectRedirectLocation(location);
expect(redirectLocation.startsWith(redirectUri)).toBe(false);
expect(redirectLocation).not.toContain("evil.example.com");
const errorUrl = new URL(redirectLocation);
expect(errorUrl.searchParams.get("error")).toBe("invalid_request");
expect(errorUrl.searchParams.get("error_description")).toMatch(
/response_type/,
);
});
it("missing client_id → server error page with invalid_request (no RP to trust)", async () => {
const qs = new URLSearchParams({
redirect_uri: redirectUri,