mirror of
https://github.com/better-auth/better-auth.git
synced 2026-05-27 01:16:55 -05:00
fix(oauth-provider): improve allowed paths for oauth_query for client plugin (#8320)
This commit is contained in:
@@ -33,24 +33,14 @@ export const oauthProviderClient = () => {
|
|||||||
: safeJSONParse<Record<string, unknown>>(ctx.body ?? "{}")
|
: safeJSONParse<Record<string, unknown>>(ctx.body ?? "{}")
|
||||||
: ctx.body;
|
: ctx.body;
|
||||||
if (body?.oauth_query) return;
|
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 (
|
if (
|
||||||
pathname.endsWith("/sign-in/email") ||
|
typeof window !== "undefined" &&
|
||||||
pathname.endsWith("/sign-in/social") ||
|
window?.location?.search &&
|
||||||
pathname.endsWith("/sign-in/oauth2") ||
|
!(ctx.method === "GET" || ctx.method === "DELETE")
|
||||||
pathname.endsWith("/oauth2/consent") ||
|
|
||||||
pathname.endsWith("/oauth2/continue")
|
|
||||||
) {
|
) {
|
||||||
ctx.body = JSON.stringify({
|
ctx.body = JSON.stringify({
|
||||||
...body,
|
...body,
|
||||||
oauth_query:
|
oauth_query: parseSignedQuery(window.location.search),
|
||||||
typeof window !== "undefined"
|
|
||||||
? parseSignedQuery(window?.location?.search)
|
|
||||||
: undefined,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -447,6 +447,7 @@ describe("oauth - prompt", async () => {
|
|||||||
const scopes = ["openid", "profile", "email", "offline_access", "read:posts"];
|
const scopes = ["openid", "profile", "email", "offline_access", "read:posts"];
|
||||||
let enableSelectAccount = false;
|
let enableSelectAccount = false;
|
||||||
let enablePostLogin = false;
|
let enablePostLogin = false;
|
||||||
|
let selectedPostLogin = false;
|
||||||
let isUserRegistered = true;
|
let isUserRegistered = true;
|
||||||
const {
|
const {
|
||||||
auth: authorizationServer,
|
auth: authorizationServer,
|
||||||
@@ -481,10 +482,12 @@ describe("oauth - prompt", async () => {
|
|||||||
page: "/select-organization",
|
page: "/select-organization",
|
||||||
shouldRedirect({ session }) {
|
shouldRedirect({ session }) {
|
||||||
if (!enablePostLogin) return false;
|
if (!enablePostLogin) return false;
|
||||||
|
if (selectedPostLogin) return false;
|
||||||
return !session?.activeOrganizationId;
|
return !session?.activeOrganizationId;
|
||||||
},
|
},
|
||||||
consentReferenceId({ session }) {
|
consentReferenceId({ session }) {
|
||||||
if (!enablePostLogin) return undefined;
|
if (!enablePostLogin) return undefined;
|
||||||
|
if (selectedPostLogin) return undefined;
|
||||||
const activeOrganizationId = (session?.activeOrganizationId ??
|
const activeOrganizationId = (session?.activeOrganizationId ??
|
||||||
undefined) as string | undefined;
|
undefined) as string | undefined;
|
||||||
if (!activeOrganizationId)
|
if (!activeOrganizationId)
|
||||||
@@ -1426,6 +1429,84 @@ describe("oauth - prompt", async () => {
|
|||||||
enableSelectAccount = false;
|
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 ({
|
it("shall allow user to select an organization/team post login and consent", async ({
|
||||||
onTestFinished,
|
onTestFinished,
|
||||||
}) => {
|
}) => {
|
||||||
@@ -1487,6 +1568,7 @@ describe("oauth - prompt", async () => {
|
|||||||
vi.unstubAllGlobals();
|
vi.unstubAllGlobals();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let consentRedirectUri = "";
|
||||||
// Select Account and continue auth flow
|
// Select Account and continue auth flow
|
||||||
await serverClient.organization.setActive(
|
await serverClient.organization.setActive(
|
||||||
{
|
{
|
||||||
@@ -1495,22 +1577,12 @@ describe("oauth - prompt", async () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
headers,
|
headers,
|
||||||
throw: true,
|
onResponse(context) {
|
||||||
onResponse: cookieSetter(headers),
|
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(`/consent`);
|
||||||
expect(consentRedirectUri).toContain(`client_id=${oauthClient.client_id}`);
|
expect(consentRedirectUri).toContain(`client_id=${oauthClient.client_id}`);
|
||||||
expect(consentRedirectUri).toContain(`scope=`);
|
expect(consentRedirectUri).toContain(`scope=`);
|
||||||
|
|||||||
Reference in New Issue
Block a user