fix(expo): support wildcard trusted origins in deep link cookie injection (#8013)

(cherry picked from commit 2468a2d918)
This commit is contained in:
Taesu
2026-02-18 22:31:37 +08:00
committed by Alex Yang
parent 17407ba327
commit 7153e1b6d0
2 changed files with 88 additions and 11 deletions
+15 -9
View File
@@ -66,12 +66,19 @@ export const expo = (options?: ExpoOptions | undefined) => {
if (isProxyURL) {
return;
}
const trustedOrigins = ctx.context.trustedOrigins.filter(
(origin: string) => !origin.startsWith("http"),
);
const isTrustedOrigin = trustedOrigins.some((origin: string) =>
location?.startsWith(origin),
);
let redirectURL: URL;
try {
redirectURL = new URL(location);
} catch {
return;
}
const isHttpRedirect =
redirectURL.protocol === "http:" ||
redirectURL.protocol === "https:";
if (isHttpRedirect) {
return;
}
const isTrustedOrigin = ctx.context.isTrustedOrigin(location);
if (!isTrustedOrigin) {
return;
}
@@ -79,9 +86,8 @@ export const expo = (options?: ExpoOptions | undefined) => {
if (!cookie) {
return;
}
const url = new URL(location);
url.searchParams.set("cookie", cookie);
ctx.setHeader("location", url.toString());
redirectURL.searchParams.set("cookie", cookie);
ctx.setHeader("location", redirectURL.toString());
}),
},
],
+73 -2
View File
@@ -789,6 +789,7 @@ describe("expo deep link cookie injection", async () => {
callbackURL: "myapp:///dashboard",
});
let redirectHandled = false;
const { error } = await client.magicLink.verify({
query: {
token: magicLinkToken,
@@ -796,6 +797,7 @@ describe("expo deep link cookie injection", async () => {
},
fetchOptions: {
onError(context) {
redirectHandled = true;
expect(context.response.status).toBe(302);
const location = context.response.headers.get("location");
expect(location).toContain("myapp://");
@@ -807,7 +809,73 @@ describe("expo deep link cookie injection", async () => {
},
},
});
expect(error).toBeDefined();
expect(redirectHandled).toBe(true);
expect(error?.status).toBe(302);
});
});
/**
* @see https://github.com/better-auth/better-auth/issues/6810
*/
describe("expo deep link cookie injection with wildcard trustedOrigins", async () => {
let magicLinkToken = "";
const storage = new Map<string, string>();
const { client } = await getTestInstance(
{
plugins: [
expo(),
magicLink({
async sendMagicLink({ token }) {
magicLinkToken = token;
},
}),
],
trustedOrigins: ["myapp://*"],
},
{
clientOptions: {
plugins: [
expoClient({
storage: {
getItem: (key) => storage.get(key) || null,
setItem: async (key, value) => storage.set(key, value),
},
}),
magicLinkClient(),
],
},
},
);
it("should inject cookie into deep link for wildcard trusted origin", async () => {
await client.signIn.magicLink({
email: "wildcard-test@example.com",
callbackURL: "myapp:///dashboard",
});
let redirectHandled = false;
const { error } = await client.magicLink.verify({
query: {
token: magicLinkToken,
callbackURL: "myapp:///dashboard",
},
fetchOptions: {
onError(context) {
redirectHandled = true;
expect(context.response.status).toBe(302);
const location = context.response.headers.get("location");
expect(location).toContain("myapp://");
const url = new URL(location!);
const cookie = url.searchParams.get("cookie");
expect(cookie).toBeDefined();
expect(cookie).toContain("better-auth.session_token");
},
},
});
expect(redirectHandled).toBe(true);
expect(error?.status).toBe(302);
});
});
@@ -853,6 +921,7 @@ describe("expo deep link cookie injection for verify-email", async () => {
expect(verificationToken).toBeTruthy();
let redirectHandled = false;
const { error } = await client.verifyEmail(
{
query: {
@@ -862,6 +931,7 @@ describe("expo deep link cookie injection for verify-email", async () => {
},
{
onError(context) {
redirectHandled = true;
expect(context.response.status).toBe(302);
const location = context.response.headers.get("location");
expect(location).toContain("myapp://");
@@ -873,7 +943,8 @@ describe("expo deep link cookie injection for verify-email", async () => {
},
},
);
expect(error).toBeDefined();
expect(redirectHandled).toBe(true);
expect(error?.status).toBe(302);
});
});