[GH-ISSUE #1058] [expo plugin] fails social login and magic link login due to modification of immutable header #8571

Closed
opened 2026-04-13 03:41:23 -05:00 by GiteaMirror · 3 comments
Owner

Originally created by @brookewaters on GitHub (Dec 28, 2024).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/1058

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  1. Create a backend with the expo() plugin
  2. Attempt social login from the front-end.

Current vs. Expected behavior

Using the expo plugin on the server should work. Instead of working, a social login or magic login gives the following error message:

"TypeError: Can't modify immutable headers.",

This would be from the API/route: (it does the same thing for social login with google)

POST /api/auth/sign-in/magic-link

The culprit appears to be this line:

https://github.com/better-auth/better-auth/blob/main/packages/expo/src/index.ts#L28

I overrode that function (by writing my own plugin) with the following code:

    async onRequest(request) {
      // If the request has an "origin" header, do nothing
      if (request.headers.get("origin")) {
        return;
      }
    
      const expoOrigin = request.headers.get("expo-origin");
      // If there's no "expo-origin" header, do nothing
      if (!expoOrigin) {
        return;
      }
    
      // Clone the request to safely reuse the body
      const newHeaders = new Headers(request.headers);
      newHeaders.set("origin", expoOrigin);
    
      // Create a new Request object with updated headers and the cloned body
      const updatedRequest = new Request(request.clone() as Request<unknown, CfProperties<unknown>>, {
        headers: newHeaders,
      });
    
      console.log("created new request");
      return {
        request: updatedRequest,
      };
    },    

This seemingly resolves the issue (though I still haven't gotten social or magic link login to work from the iOS simulator).

What version of Better Auth are you using?

1.1.4

Provide environment information

Server: CloudFlare Workers, Hono, Drizzle, D1.
Client: iOS simulator with Expo/React Native

Which area(s) are affected? (Select all that apply)

Backend

Auth config (if applicable)

betterAuth({
    secret: params.BETTER_AUTH_SECRET,
    advanced: {
      defaultCookieAttributes: {
        secure: true,
        sameSite: "none",
        path: "/",
      },
      useSecureCookies: false,
      cookieOptions: {
        sameSite: "none",
      },
    },
    user: {
      modelName: "users",
      additionalFields: {
        first_name: {
          type: "string",
          required: true,
          input: true,
        },
        last_name: {
          type: "string",
          required: true,
          input: true,
        },
        phone_number: {
          type: "string",
          required: false,
          input: true,
        },
      },
    },
    plugins: [
      expo(),
      magicLink({
        sendMagicLink: async ({ email, token, url }, request) => {
          try {
            const sesClient = new SESClient({
              region: params.AWS_DEFAULT_REGION || "us-east-1",
              credentials: {
                accessKeyId: params.AWS_ACCESS_KEY_ID || "",
                secretAccessKey: params.AWS_SECRET_ACCESS_KEY || "",
              },
            });

            const subject = "Your Magic Link";
            const fromAddress = "mailer@<redacted>.com";

            // Log the magic link information
            log(Level.INFO, "Sending magic link", {
              email,
              token,
              url,
            });

            // Use sendSignupEmail to send the email
            await sendSignupEmail({
              sesClient,
              toAddress: email,
              subject,
              fromAddress,
              url,
            });

            console.log(
              `Magic link email sent to ${email} with token ${token}`,
            );
          } catch (error) {
            console.error("Error sending magic link:", error);
            throw new Error("Failed to send magic link");
          }
        },
      }),
    ],
    trustedOrigins: ["http://localhost:8081", "exp://"],
    socialProviders: {
      google: {
        clientId: params.GOOGLE_CLIENT_ID,
        clientSecret: params.GOOGLE_CLIENT_SECRET,
      },
    },
    database: drizzleAdapter(drizzle(db, { schema }), {
      provider: "sqlite",
      schema: {
        ...schema,
        user: schema.users,
      },
      usePlural: true,
    }),
    emailAndPassword: {
      enabled: false,
    },
  });

Additional context

That is all

Originally created by @brookewaters on GitHub (Dec 28, 2024). Original GitHub issue: https://github.com/better-auth/better-auth/issues/1058 ### Is this suited for github? - [X] Yes, this is suited for github ### To Reproduce 1. Create a backend with the expo() plugin 2. Attempt social login from the front-end. ### Current vs. Expected behavior Using the `expo` plugin on the server should work. Instead of working, a social login or magic login gives the following error message: ``` "TypeError: Can't modify immutable headers.", ``` This would be from the API/route: (it does the same thing for social login with google) ``` POST /api/auth/sign-in/magic-link ``` The culprit appears to be this line: https://github.com/better-auth/better-auth/blob/main/packages/expo/src/index.ts#L28 I overrode that function (by writing my own plugin) with the following code: ``` async onRequest(request) { // If the request has an "origin" header, do nothing if (request.headers.get("origin")) { return; } const expoOrigin = request.headers.get("expo-origin"); // If there's no "expo-origin" header, do nothing if (!expoOrigin) { return; } // Clone the request to safely reuse the body const newHeaders = new Headers(request.headers); newHeaders.set("origin", expoOrigin); // Create a new Request object with updated headers and the cloned body const updatedRequest = new Request(request.clone() as Request<unknown, CfProperties<unknown>>, { headers: newHeaders, }); console.log("created new request"); return { request: updatedRequest, }; }, ``` This seemingly resolves the issue (though I still haven't gotten social or magic link login to work from the iOS simulator). ### What version of Better Auth are you using? 1.1.4 ### Provide environment information ```bash Server: CloudFlare Workers, Hono, Drizzle, D1. Client: iOS simulator with Expo/React Native ``` ### Which area(s) are affected? (Select all that apply) Backend ### Auth config (if applicable) ```typescript betterAuth({ secret: params.BETTER_AUTH_SECRET, advanced: { defaultCookieAttributes: { secure: true, sameSite: "none", path: "/", }, useSecureCookies: false, cookieOptions: { sameSite: "none", }, }, user: { modelName: "users", additionalFields: { first_name: { type: "string", required: true, input: true, }, last_name: { type: "string", required: true, input: true, }, phone_number: { type: "string", required: false, input: true, }, }, }, plugins: [ expo(), magicLink({ sendMagicLink: async ({ email, token, url }, request) => { try { const sesClient = new SESClient({ region: params.AWS_DEFAULT_REGION || "us-east-1", credentials: { accessKeyId: params.AWS_ACCESS_KEY_ID || "", secretAccessKey: params.AWS_SECRET_ACCESS_KEY || "", }, }); const subject = "Your Magic Link"; const fromAddress = "mailer@<redacted>.com"; // Log the magic link information log(Level.INFO, "Sending magic link", { email, token, url, }); // Use sendSignupEmail to send the email await sendSignupEmail({ sesClient, toAddress: email, subject, fromAddress, url, }); console.log( `Magic link email sent to ${email} with token ${token}`, ); } catch (error) { console.error("Error sending magic link:", error); throw new Error("Failed to send magic link"); } }, }), ], trustedOrigins: ["http://localhost:8081", "exp://"], socialProviders: { google: { clientId: params.GOOGLE_CLIENT_ID, clientSecret: params.GOOGLE_CLIENT_SECRET, }, }, database: drizzleAdapter(drizzle(db, { schema }), { provider: "sqlite", schema: { ...schema, user: schema.users, }, usePlural: true, }), emailAndPassword: { enabled: false, }, }); ``` ### Additional context That is all
GiteaMirror added the lockedbug labels 2026-04-13 03:41:23 -05:00
Author
Owner

@rohanskalkat commented on GitHub (Jan 1, 2025):

+1

I have experienced the same issue with pretty much the same environment, with the only change being that I use a Postgres DB. Even after cloning the request I get either Please restart the process error or Internal server error (if I have a middleware) from the cloudflare worker and I am not redirected back to the app, @brookewaters are you experiencing similar issues or do you have no issues logging in after cloning the request?

Currently I am using expo-apple-authentication and @react-native-google-signin/google-signin and logging in using id token to get around this.

<!-- gh-comment-id:2566768406 --> @rohanskalkat commented on GitHub (Jan 1, 2025): +1 I have experienced the same issue with pretty much the same environment, with the only change being that I use a Postgres DB. Even after cloning the request I get either `Please restart the process` error or `Internal server error` (if I have a middleware) from the cloudflare worker and I am not redirected back to the app, @brookewaters are you experiencing similar issues or do you have no issues logging in after cloning the request? Currently I am using expo-apple-authentication and @react-native-google-signin/google-signin and logging in using id token to get around this.
Author
Owner

@jackbcodes commented on GitHub (Jan 5, 2025):

+1 same here

<!-- gh-comment-id:2571644849 --> @jackbcodes commented on GitHub (Jan 5, 2025): +1 same here
Author
Owner

@darrenbutcher commented on GitHub (Jan 8, 2025):

Hey @brookewaters thanks for pointing me in the right direction, was having the similar issue:
ref in https://github.com/better-auth/better-auth/issues/1143. @rohanskalkat I have only tested email/password flow and in local dev mode, but have not experienced any issues redirecting after signup or login. I'll report back when I get to implementing social auth.

<!-- gh-comment-id:2576532796 --> @darrenbutcher commented on GitHub (Jan 8, 2025): Hey @brookewaters thanks for pointing me in the right direction, was having the similar issue: ref in https://github.com/better-auth/better-auth/issues/1143. @rohanskalkat I have only tested email/password flow and in local dev mode, but have not experienced any issues redirecting after signup or login. I'll report back when I get to implementing social auth.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#8571