#Astro Action + Better Auth: Cookies Not Persisting in Client Island

4 messages · Page 1 of 1 (latest)

river badge
#

I'm using a client-side React island to call a Better Auth signInEmail function via an Astro Action. The sign-in succeeds, but cookies (e.g. session) are not being set.
Here’s the defineAction I'm using:

signInWithEmail: defineAction({
  accept: 'json',
  input: signInSchema,
  handler: async ({ email, password }, context) => {
    try {
      const res = await auth.api.signInEmail({
        body: { email, password, rememberMe: true },
        headers: context.request.headers,
      });

      return { success: true, message: 'Sign in success' };
    } catch (error) {
      throw new ActionError({ code: 'BAD_REQUEST', message: 'Sign in failed' });
    }
  },
});

And this is how I’m calling it from the React island:

async function onSubmit(payload: SignInSchema) {
  form.clearErrors();
  setError('');

  startTransition(async () => {
    const { data, error } = await actions.authAction.signInWithEmail(payload);

    if (isInputError(error)) {
      Object.entries(error.fields).forEach(([field, messages]) => {
        form.setError(field as any, {
          type: 'manual',
          message: messages[0],
        });
      });
    } else if (error) {
      setError(error.message);
    }
  });
}

How can I make sure the cookies (set-cookie header) are properly persisted in this setup?

round glenBOT
#

Hi @river badge. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

The issue you're encountering—where cookies (such as session cookies) set by your Astro Action are not being persisted in the browser when calling the action from a client-side React island—is a common one when dealing with client-side fetch requests and authentication flows.

Why This Happens

When you call an Astro Action from a client-side island (e.g., using actions.authAction.signInWithEmail(payload)), the request is made via fetch from the browser. By default, fetch does not send or accept cookies unless you explicitly set the credentials option. This means any Set-Cookie headers sent by your action handler will be ignored by the browser unless you configure this properly.

Solution

You need to ensure that your client-side fetch includes credentials. In the context of Astro Actions, this means you must call the action with { credentials: 'include' } so that cookies are sent and received.

However, the knowledge sources do not provide a direct example of how to configure Astro Actions to automatically include credentials when called from a client-side island. They do explain how cookies are set and managed in Astro, and that cookies are available in the context of API endpoints and actions, but do not cover the client-side fetch configuration in detail [Astro cookies API reference].

What You Can Do

#
  • Check how your action is being called on the client. If you are using a custom fetch or the default Astro Actions client, ensure that it is configured to use credentials: 'include'.
  • If you are using your own fetch:
    fetch('/_actions/authAction.signInWithEmail', {
      method: 'POST',
      body: JSON.stringify(payload),
      headers: { 'Content-Type': 'application/json' },
      credentials: 'include', // This is crucial!
    });
    
  • If you are using a helper provided by Astro or Better Auth:
    The knowledge sources do not specify if these helpers automatically set credentials: 'include'. You may need to check their documentation or implementation.

Additional Notes

  • CORS: If your API endpoint is on a different origin, you must also ensure CORS is configured to allow credentials.
  • Astro Action Handler: Your action handler is correctly setting cookies using the context, but the browser will only persist them if the fetch request is configured as above.

Summary

To ensure cookies set by your Astro Action are persisted in the browser when called from a client-side React island, you must make sure the client-side fetch includes credentials: 'include'. The knowledge sources do not provide a direct example for Astro Actions, but this is standard browser behavior for cookies and fetch [Astro cookies API reference].

If you need more specific guidance for Astro Actions' client-side helpers, you may need to consult the Better Auth or Astro Actions documentation directly, as the provided knowledge sources do not cover this detail.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: