[GH-ISSUE #1835] Could not get token from JWT client Plugin (onSuccess headers) #8937

Closed
opened 2026-04-13 04:11:10 -05:00 by GiteaMirror · 8 comments
Owner

Originally created by @xorweak on GitHub (Mar 15, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/1835

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  1. Create Better Auth server and use the jwt plugin.
  2. Create a vue-based frontend that uses better auth client.
  3. use getSession hook and try to read 'set-auth-jwt' header using fetchOptions.onSuccess. (Following the docs)

here's a log of ctx.response.headers.forEach iteration:

getSession.onSuccess.headers:: {key: 'content-length', value: '791'}
getSession.onSuccess.headers:: {key: 'content-type', value: 'application/json'}

Only two headers are available at that point.

Current vs. Expected behavior

Following previous steps, I expected to be able to get the jwt token from the headers, but instead the value is null.

await authClient.getSession({
  fetchOptions: {
    onSuccess: (ctx)=>{
      const jwt = ctx.response.headers.get("set-auth-jwt") // jwt value is null.
    }
  }

ctx.response.headers, does not have the full response headers, only content-type and content-length. I observed the same behavior using onResponse instead of onSuccess.

What version of Better Auth are you using?

1.2.4

Provide environment information

- OS: MacOS 15.3.1 (24D70) Apple Sillicon
- Browser: Google Chrome

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

Client

Auth config (if applicable)

import { inferAdditionalFields, multiSessionClient, twoFactorClient } from 'better-auth/client/plugins'
import { createAuthClient } from 'better-auth/vue'


export const authClient = createAuthClient({
  plugins: [
    twoFactorClient(),
    multiSessionClient(),
    inferAdditionalFields({
      user: {
        _id: {
          required: false,
          type: 'string',
        }
      },
    })
  ],
})

Additional context

I think that the issue may be related to the better-call library.

Originally created by @xorweak on GitHub (Mar 15, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/1835 ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce 1. Create Better Auth server and use the [jwt plugin](https://www.better-auth.com/docs/plugins/jwt). 2. Create a vue-based frontend that uses better auth client. 3. use getSession hook and try to read 'set-auth-jwt' header using fetchOptions.onSuccess. ([Following the docs](https://www.better-auth.com/docs/plugins/jwt)) here's a log of ctx.response.headers.forEach iteration: ```bash getSession.onSuccess.headers:: {key: 'content-length', value: '791'} getSession.onSuccess.headers:: {key: 'content-type', value: 'application/json'} ``` Only two headers are available at that point. ### Current vs. Expected behavior Following previous steps, I expected to be able to get the jwt token from the headers, but instead the value is null. ```javascript await authClient.getSession({ fetchOptions: { onSuccess: (ctx)=>{ const jwt = ctx.response.headers.get("set-auth-jwt") // jwt value is null. } } ``` ctx.response.headers, does not have the full response headers, only `content-type` and `content-length`. I observed the same behavior using `onResponse` instead of `onSuccess`. ### What version of Better Auth are you using? 1.2.4 ### Provide environment information ```bash - OS: MacOS 15.3.1 (24D70) Apple Sillicon - Browser: Google Chrome ``` ### Which area(s) are affected? (Select all that apply) Client ### Auth config (if applicable) ```typescript import { inferAdditionalFields, multiSessionClient, twoFactorClient } from 'better-auth/client/plugins' import { createAuthClient } from 'better-auth/vue' export const authClient = createAuthClient({ plugins: [ twoFactorClient(), multiSessionClient(), inferAdditionalFields({ user: { _id: { required: false, type: 'string', } }, }) ], }) ``` ### Additional context I think that the issue may be related to the [better-call](https://www.npmjs.com/package/better-call) library.
GiteaMirror added the lockedbug labels 2026-04-13 04:11:10 -05:00
Author
Owner

@sixelasacul commented on GitHub (Mar 21, 2025):

Hey, so I recently started using better-auth, so I might not be the best to answer. I ran into a similar issue earlier that led me to this issue, and I manage to fix it. I'm using the react client (with TanStack Start), but I've just setup a quick Nuxt project and ported my configuration and it just works (that's a great thing by the way).

I'm using version 1.2.4 of better-auth. Here's the auth configs that I have:

// auth.ts (server)
import { betterAuth } from "better-auth";
import { anonymous, jwt } from "better-auth/plugins";
import pg from "pg";

export const auth = betterAuth({
  // not super relevant config
  secret: "<secret>",
  database: new pg.Pool({
    connectionString: "<secret>",
  }),
  socialProviders: {
    google: {
      clientId: "<secret>",
      clientSecret: "<secret>",
    },
  },
  // the relevant part (well not the anonymous plugin)
  plugins: [anonymous(), jwt()],
});

Note: For some reasons I thought a database was required for the jwt plugin, but not, it works when I comment out the database configuration.

// auth-client.ts (client)
import { anonymousClient, jwtClient } from "better-auth/client/plugins";
import { createAuthClient } from "better-auth/vue";

export const authClient = createAuthClient({
  plugins: [anonymousClient(), jwtClient()],
});

Note: it seems like jwtClient isn't needed. Also, I've tried adding all the client plugins you're using, and it still works.

And here's how I use it in a page:

<script setup lang="ts">
import { authClient } from "~/lib/auth-client";
const { data } = await useAsyncData(async () => {
  await authClient.getSession({
    fetchOptions: {
      onSuccess: (ctx) => {
        console.log(ctx.response.headers.get("set-auth-jwt"));
      },
    },
  });
});
console.log(data);
</script>

Also, even though it's not written in the docs, once you have enabled the jwtClient() plugin, you can use the authClient.token() method to retrieve the token easily.

Hopefully that can help!

<!-- gh-comment-id:2744510393 --> @sixelasacul commented on GitHub (Mar 21, 2025): Hey, so I recently started using better-auth, so I might not be the best to answer. I ran into a similar issue earlier that led me to this issue, and I manage to fix it. I'm using the `react` client (with TanStack Start), but I've just setup a quick Nuxt project and ported my configuration and it just works (that's a great thing by the way). I'm using version `1.2.4` of `better-auth`. Here's the auth configs that I have: ```ts // auth.ts (server) import { betterAuth } from "better-auth"; import { anonymous, jwt } from "better-auth/plugins"; import pg from "pg"; export const auth = betterAuth({ // not super relevant config secret: "<secret>", database: new pg.Pool({ connectionString: "<secret>", }), socialProviders: { google: { clientId: "<secret>", clientSecret: "<secret>", }, }, // the relevant part (well not the anonymous plugin) plugins: [anonymous(), jwt()], }); ``` > Note: For some reasons I thought a database was required for the `jwt` plugin, but not, it works when I comment out the `database` configuration. ```ts // auth-client.ts (client) import { anonymousClient, jwtClient } from "better-auth/client/plugins"; import { createAuthClient } from "better-auth/vue"; export const authClient = createAuthClient({ plugins: [anonymousClient(), jwtClient()], }); ``` > Note: it seems like `jwtClient` isn't needed. Also, I've tried adding all the client plugins you're using, and it still works. And here's how I use it in a page: ```vue <script setup lang="ts"> import { authClient } from "~/lib/auth-client"; const { data } = await useAsyncData(async () => { await authClient.getSession({ fetchOptions: { onSuccess: (ctx) => { console.log(ctx.response.headers.get("set-auth-jwt")); }, }, }); }); console.log(data); </script> ``` Also, even though it's not written in the docs, once you have enabled the `jwtClient()` plugin, you can use the `authClient.token()` method to retrieve the token easily. Hopefully that can help!
Author
Owner

@moshetanzer commented on GitHub (Mar 25, 2025):

Hey @soknifedev,

Did you manage to solve your issue?

<!-- gh-comment-id:2751794309 --> @moshetanzer commented on GitHub (Mar 25, 2025): Hey @soknifedev, Did you manage to solve your issue?
Author
Owner

@xorweak commented on GitHub (Mar 25, 2025):

Hey @soknifedev,

Did you manage to solve your issue?

Hi @moshetanzer , I haven’t verified yet if the solution proposed by @sixelasacul works, as I’m short on time right now, and I ended up using the Bearer plugin instead of JWT to speed up our development.

However, I checked past commits on our side and saw that jwtClient was not included in the frontend app. I’m not sure if that alone is enough to break the entire onSuccess callback of Better Call.

<!-- gh-comment-id:2752305105 --> @xorweak commented on GitHub (Mar 25, 2025): > Hey [@soknifedev](https://github.com/soknifedev), > > Did you manage to solve your issue? Hi @moshetanzer , I haven’t verified yet if the solution proposed by @sixelasacul works, as I’m short on time right now, and I ended up using the Bearer plugin instead of JWT to speed up our development. However, I checked past commits on our side and saw that jwtClient was not included in the frontend app. I’m not sure if that alone is enough to break the entire onSuccess callback of Better Call.
Author
Owner

@moshetanzer commented on GitHub (Mar 25, 2025):

@soknifedev that was most likely the issue. Thanks. Feel free to close issue. ❤️

<!-- gh-comment-id:2752596447 --> @moshetanzer commented on GitHub (Mar 25, 2025): @soknifedev that was most likely the issue. Thanks. Feel free to close issue. ❤️
Author
Owner

@DenisLug commented on GitHub (Apr 20, 2025):

I'm experiencing the same issue where the context in the onSuccess callback has no value for the "set-auth-jwt" header. According to the documentation this is supposed to work. The suggested solution to use the authClient.token() method has the drawback that it sends an additional request, which isn't necessary when we could make use of the JWT inside the getSession response.

<!-- gh-comment-id:2817231949 --> @DenisLug commented on GitHub (Apr 20, 2025): I'm experiencing the same issue where the context in the onSuccess callback has no value for the "set-auth-jwt" header. According to the documentation this is supposed to work. The suggested solution to use the `authClient.token()` method has the drawback that it sends an additional request, which isn't necessary when we could make use of the JWT inside the `getSession` response.
Author
Owner

@ShubhamVsCode commented on GitHub (Apr 21, 2025):

I got the same issue but we have solved this issue in a different way
Here you can find about it. Hope this helps in getting the token without "set-auth-token"

http://answeroverflow.com/m/1363774710575530096

<!-- gh-comment-id:2818452321 --> @ShubhamVsCode commented on GitHub (Apr 21, 2025): I got the same issue but we have solved this issue in a different way Here you can find about it. Hope this helps in getting the token without "set-auth-token" http://answeroverflow.com/m/1363774710575530096
Author
Owner

@andreitere commented on GitHub (Apr 26, 2025):

Experiencing the same issue when using the session cookieCache setting. set-auth-jwt not even present

cookieCache: {
  enabled: true,
  maxAge: 5 * 60
},
<!-- gh-comment-id:2832021245 --> @andreitere commented on GitHub (Apr 26, 2025): Experiencing the same issue when using the session cookieCache setting. `set-auth-jwt` not even present ```ts cookieCache: { enabled: true, maxAge: 5 * 60 }, ```
Author
Owner

@Diabl0570 commented on GitHub (Jan 19, 2026):

In the default honojs example it returns the exposedHeaders. this overrides the fix Bekacru did to return the headers correctly. So I either need to add "set-auth-jwt" in my honojs exposedHeaders or remove the exposedHeaders all together from my honojs application and let better-auth handle it.

I think this should be the default so I created a PR that updates the docs:
https://github.com/better-auth/better-auth/pull/7462

<!-- gh-comment-id:3767502646 --> @Diabl0570 commented on GitHub (Jan 19, 2026): In the default honojs example it returns the exposedHeaders. this overrides the fix Bekacru did to return the headers correctly. So I either need to add "set-auth-jwt" in my honojs exposedHeaders or remove the exposedHeaders all together from my honojs application and let better-auth handle it. I think this should be the default so I created a PR that updates the docs: https://github.com/better-auth/better-auth/pull/7462
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#8937