ctx.response is empty in onSuccess #1841

Closed
opened 2026-03-13 09:07:29 -05:00 by GiteaMirror · 2 comments
Owner

Originally created by @rinarakaki on GitHub (Sep 4, 2025).

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

N/A

Current vs. Expected behavior

auth-config.ts

import { createAuthClient } from "better-auth/react";

export const authClient = createAuthClient({
  fetchOptions: {
    onSuccess: (ctx) => {
      console.log(ctx.response.headers);  // Headers {}
      const authToken = ctx.response.headers.get("set-auth-token");
      if (authToken) {
        localStorage.setItem("bearer_token", authToken);
      }
    },
  },
});

but the response headers returned when calling authClient.useSession() definitely contains Set-Auth-Jwt.

Image

What version of Better Auth are you using?

1.3.7

System info

N/A

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

Client

Auth config (if applicable)

import { betterAuth } from "better-auth"
export const auth = betterAuth({
  emailAndPassword: {  
    enabled: true
  },
});

Additional context

No response

Originally created by @rinarakaki on GitHub (Sep 4, 2025). ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce N/A ### Current vs. Expected behavior auth-config.ts ```ts import { createAuthClient } from "better-auth/react"; export const authClient = createAuthClient({ fetchOptions: { onSuccess: (ctx) => { console.log(ctx.response.headers); // Headers {} const authToken = ctx.response.headers.get("set-auth-token"); if (authToken) { localStorage.setItem("bearer_token", authToken); } }, }, }); ``` but the response headers returned when calling `authClient.useSession()` definitely contains Set-Auth-Jwt. <img width="528" height="708" alt="Image" src="https://github.com/user-attachments/assets/98613e16-19d3-4300-b468-cf84181b9ce7" /> ### What version of Better Auth are you using? 1.3.7 ### System info ```bash N/A ``` ### Which area(s) are affected? (Select all that apply) Client ### Auth config (if applicable) ```typescript import { betterAuth } from "better-auth" export const auth = betterAuth({ emailAndPassword: { enabled: true }, }); ``` ### Additional context _No response_
GiteaMirror added the bug label 2026-03-13 09:07:29 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Sep 4, 2025):

This looks like a CORS or fetch response handling issue, not a bug in better-auth itself. The implementation of createAuthClient and fetchOptions.onSuccess does not intentionally filter or remove response headers before passing them to your callback—ctx.response.headers should be a Headers instance with all accessible headers by default. If the Set-Auth-Jwt header is missing in onSuccess, it's likely due to browser CORS restrictions or how the fetch handler serializes the response, rather than anything in better-auth's code.

Recent fixes addressed cases where some sign-in endpoints (like social logins or magic links) did not provide the set-auth-token header in the response, causing the client to miss the bearer token. If you're using those flows, make sure you're on the latest patch after August 26, 2025, as this was resolved in a merged PR (source).

If your backend is sending the header and you see it in the network tab but not in ctx.response.headers, double-check that your server is exposing the header via Access-Control-Expose-Headers and that your frontend is making requests with credentials if needed (source).

There are no documented workarounds in better-auth/react for this—it's a platform-level fetch/CORS issue. If you need to access custom headers, ensure your backend explicitly exposes them and your frontend fetch is configured correctly.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Chat with Dosu Join Discord Share on X

@dosubot[bot] commented on GitHub (Sep 4, 2025): <!-- Answer --> This looks like a CORS or fetch response handling issue, not a bug in better-auth itself. The implementation of createAuthClient and fetchOptions.onSuccess does not intentionally filter or remove response headers before passing them to your callback—ctx.response.headers should be a Headers instance with all accessible headers by default. If the Set-Auth-Jwt header is missing in onSuccess, it's likely due to browser CORS restrictions or how the fetch handler serializes the response, rather than anything in better-auth's code. Recent fixes addressed cases where some sign-in endpoints (like social logins or magic links) did not provide the set-auth-token header in the response, causing the client to miss the bearer token. If you're using those flows, make sure you're on the latest patch after August 26, 2025, as this was resolved in a merged PR ([source](https://github.com/better-auth/better-auth/pull/4123)). If your backend is sending the header and you see it in the network tab but not in ctx.response.headers, double-check that your server is exposing the header via Access-Control-Expose-Headers and that your frontend is making requests with credentials if needed ([source](https://github.com/better-auth/better-auth/issues/4343)). There are no documented workarounds in better-auth/react for this—it's a platform-level fetch/CORS issue. If you need to access custom headers, ensure your backend explicitly exposes them and your frontend fetch is configured correctly. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/e903f64a-39e7-4560-816f-3ef7266582de?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/e903f64a-39e7-4560-816f-3ef7266582de?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/e903f64a-39e7-4560-816f-3ef7266582de?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/e903f64a-39e7-4560-816f-3ef7266582de?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/e903f64a-39e7-4560-816f-3ef7266582de?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/e903f64a-39e7-4560-816f-3ef7266582de?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/e903f64a-39e7-4560-816f-3ef7266582de?feedback_type=other)</sup>&nbsp;&nbsp;[![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/better-auth/better-auth/issues/4425)
Author
Owner

@rinarakaki commented on GitHub (Sep 4, 2025):

Sorry, I should have checked set-auth-jwt instead of set-auth-token.

@rinarakaki commented on GitHub (Sep 4, 2025): Sorry, I should have checked `set-auth-jwt` instead of `set-auth-token`.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#1841