fix(oauth-provider): improve allowed paths for oauth_query for client plugin (#8320)

This commit is contained in:
Dylan Vanmali
2026-03-18 09:55:12 -07:00
committed by GitHub
parent 40b5e23b3b
commit 40e7676155
2 changed files with 90 additions and 28 deletions

View File

@@ -33,24 +33,14 @@ export const oauthProviderClient = () => {
: safeJSONParse<Record<string, unknown>>(ctx.body ?? "{}")
: ctx.body;
if (body?.oauth_query) return;
const pathname =
typeof ctx.url === "string"
? new URL(ctx.url).pathname
: ctx.url.pathname;
// Should only need to run for /sign-in/email, /sign-in/social, /sign-in/oauth2, /oauth2/consent, /oauth2/continue
if (
pathname.endsWith("/sign-in/email") ||
pathname.endsWith("/sign-in/social") ||
pathname.endsWith("/sign-in/oauth2") ||
pathname.endsWith("/oauth2/consent") ||
pathname.endsWith("/oauth2/continue")
typeof window !== "undefined" &&
window?.location?.search &&
!(ctx.method === "GET" || ctx.method === "DELETE")
) {
ctx.body = JSON.stringify({
...body,
oauth_query:
typeof window !== "undefined"
? parseSignedQuery(window?.location?.search)
: undefined,
oauth_query: parseSignedQuery(window.location.search),
});
}
},

View File

@@ -447,6 +447,7 @@ describe("oauth - prompt", async () => {
const scopes = ["openid", "profile", "email", "offline_access", "read:posts"];
let enableSelectAccount = false;
let enablePostLogin = false;
let selectedPostLogin = false;
let isUserRegistered = true;
const {
auth: authorizationServer,
@@ -481,10 +482,12 @@ describe("oauth - prompt", async () => {
page: "/select-organization",
shouldRedirect({ session }) {
if (!enablePostLogin) return false;
if (selectedPostLogin) return false;
return !session?.activeOrganizationId;
},
consentReferenceId({ session }) {
if (!enablePostLogin) return undefined;
if (selectedPostLogin) return undefined;
const activeOrganizationId = (session?.activeOrganizationId ??
undefined) as string | undefined;
if (!activeOrganizationId)
@@ -1426,6 +1429,84 @@ describe("oauth - prompt", async () => {
enableSelectAccount = false;
});
it("shall allow user to post login via continue", async ({
onTestFinished,
}) => {
if (!oauthClient?.client_id || !oauthClient?.client_secret) {
throw Error("beforeAll not run properly");
}
enablePostLogin = true;
const { customFetchImpl: customFetchImplRP, cookieSetter } =
await createTestInstance();
const client = createAuthClient({
plugins: [genericOAuthClient(), organization()],
baseURL: rpBaseUrl,
fetchOptions: {
customFetchImpl: customFetchImplRP,
},
});
// Generate authorize url
const oauthHeaders = new Headers();
const data = await client.signIn.oauth2(
{
providerId,
callbackURL: "/success",
},
{
headers,
throw: true,
onSuccess: cookieSetter(oauthHeaders),
},
);
expect(data.url).toContain(
`${authServerBaseUrl}/api/auth/oauth2/authorize`,
);
expect(data.url).toContain(`client_id=${oauthClient.client_id}`);
// Check for redirection to /select-organization
let selectOrgRedirectUri = "";
await serverClient.$fetch(data.url, {
method: "GET",
headers,
onError(context) {
selectOrgRedirectUri = context.response.headers.get("Location") || "";
cookieSetter(headers)(context);
},
});
expect(selectOrgRedirectUri).toContain(`/select-organization`);
expect(selectOrgRedirectUri).toContain(
`client_id=${oauthClient.client_id}`,
);
expect(selectOrgRedirectUri).toContain(`scope=`);
expect(selectOrgRedirectUri).toContain(`state=`);
vi.stubGlobal("window", {
location: {
search: new URL(selectOrgRedirectUri, authServerBaseUrl).search,
},
});
onTestFinished(() => {
vi.unstubAllGlobals();
});
selectedPostLogin = true;
const continueRes = await serverClient.oauth2.continue(
{
postLogin: true,
},
{
headers,
throw: true,
onResponse: cookieSetter(headers),
},
);
expect(continueRes.url).toContain(redirectUri);
expect(continueRes.url).toContain(`code=`);
selectedPostLogin = false;
enablePostLogin = false;
});
it("shall allow user to select an organization/team post login and consent", async ({
onTestFinished,
}) => {
@@ -1487,6 +1568,7 @@ describe("oauth - prompt", async () => {
vi.unstubAllGlobals();
});
let consentRedirectUri = "";
// Select Account and continue auth flow
await serverClient.organization.setActive(
{
@@ -1495,22 +1577,12 @@ describe("oauth - prompt", async () => {
},
{
headers,
throw: true,
onResponse: cookieSetter(headers),
onResponse(context) {
consentRedirectUri = context.response.headers.get("Location") || "";
cookieSetter(headers)(context);
},
},
);
const selectedAccountRes = await serverClient.oauth2.continue(
{
postLogin: true,
},
{
headers,
throw: true,
onResponse: cookieSetter(headers),
},
);
expect(selectedAccountRes.redirect).toBeTruthy();
const consentRedirectUri = selectedAccountRes?.url;
expect(consentRedirectUri).toContain(`/consent`);
expect(consentRedirectUri).toContain(`client_id=${oauthClient.client_id}`);
expect(consentRedirectUri).toContain(`scope=`);