mirror of
https://github.com/better-auth/better-auth.git
synced 2026-10-19 23:53:17 -05:00
fix(oauth-provider): redirect missing response_type errors (#10149)
This commit is contained in:
@@ -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.
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user