Issue with set-auth-token acquisition not working on OnSuccess behavior #1385

Open
opened 2026-03-13 08:36:15 -05:00 by GiteaMirror · 10 comments
Owner

Originally created by @EasyDevv on GitHub (Jun 19, 2025).

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

Create a function for each login on the frontend to test behavior

Current vs. Expected behavior

Only authClient.signIn.email can get the bearer token properly and,
Not obtained when using authClient.getSession, authClient.signIn.social, or createAuthClient.

What version of Better Auth are you using?

1.2.9

Provide environment information

- Windows11
- Chrome
- Astrojs + Svelte5

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
  },
  socialProviders: {
        google: {
            prompt: "consent",
            clientId: process.env.GOOGLE_CLIENT_ID!,
            clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
        },
    },
  plugins: [bearer()]
});

Additional context

Successful code

import { authClient } from "@lib/auth-client";

let bearerToken = null

authClient.signIn.email(
    {
        email: email,
        password: password,
    },
    {
        onSuccess:  (ctx) => {
            bearerToken = ctx.response.headers.get("set-auth-token");
            localStorage.setItem("bearer_token", bearerToken ?? "");
        },
    }
);

Failed code

result is null

import { authClient } from "@lib/auth-client";

let bearerToken = null

authClient.getSession({
    fetchOptions: {
        onSuccess: (ctx) => {
            bearerToken = ctx.response.headers.get("set-auth-token");
            localStorage.setItem("bearer_token", bearerToken ?? "");
        },
    },
});

authClient.signIn.social(
        {
            provider: "google",
        },
        {
            onSuccess: (ctx) => {
                bearerToken = ctx.response.headers.get("set-auth-token");
                localStorage.setItem("bearer_token", bearerToken ?? "");
            },
        },
    );
export const authClient = createAuthClient({
    fetchOptions: {
        onSuccess: (ctx) => {
            const authToken = ctx.response.headers.get("set-auth-token") // get the token from the response headers
            // Store the token securely (e.g., in localStorage)
            if (authToken) {
                localStorage.setItem("bearer_token", authToken);
            }
        }
    }
})
Originally created by @EasyDevv on GitHub (Jun 19, 2025). ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce Create a function for each login on the frontend to test behavior ### Current vs. Expected behavior Only authClient.signIn.email can get the bearer token properly and, Not obtained when using authClient.getSession, authClient.signIn.social, or createAuthClient. ### What version of Better Auth are you using? 1.2.9 ### Provide environment information ```bash - Windows11 - Chrome - Astrojs + Svelte5 ``` ### 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 }, socialProviders: { google: { prompt: "consent", clientId: process.env.GOOGLE_CLIENT_ID!, clientSecret: process.env.GOOGLE_CLIENT_SECRET!, }, }, plugins: [bearer()] }); ``` ### Additional context ## ✅ Successful code ```ts import { authClient } from "@lib/auth-client"; let bearerToken = null authClient.signIn.email( { email: email, password: password, }, { onSuccess: (ctx) => { bearerToken = ctx.response.headers.get("set-auth-token"); localStorage.setItem("bearer_token", bearerToken ?? ""); }, } ); ``` ## ❌ Failed code result is `null` ```ts import { authClient } from "@lib/auth-client"; let bearerToken = null authClient.getSession({ fetchOptions: { onSuccess: (ctx) => { bearerToken = ctx.response.headers.get("set-auth-token"); localStorage.setItem("bearer_token", bearerToken ?? ""); }, }, }); authClient.signIn.social( { provider: "google", }, { onSuccess: (ctx) => { bearerToken = ctx.response.headers.get("set-auth-token"); localStorage.setItem("bearer_token", bearerToken ?? ""); }, }, ); ``` ```ts export const authClient = createAuthClient({ fetchOptions: { onSuccess: (ctx) => { const authToken = ctx.response.headers.get("set-auth-token") // get the token from the response headers // Store the token securely (e.g., in localStorage) if (authToken) { localStorage.setItem("bearer_token", authToken); } } } }) ```
Author
Owner

@pauldemarco commented on GitHub (Jun 29, 2025):

I am also getting this issue.

Why would the response header not be included in the client wide fetchOptions onSuccess context?

@pauldemarco commented on GitHub (Jun 29, 2025): I am also getting this issue. Why would the response header not be included in the client wide fetchOptions onSuccess context?
Author
Owner

@DanielBoxer commented on GitHub (Aug 2, 2025):

I’m running into this too with a cross-domain setup. Could the social redirect be clearing all headers?

Maybe a workaround is to pass the auth token in the redirect url, but I’m not sure how to implement that with better-auth hooks.

@DanielBoxer commented on GitHub (Aug 2, 2025): I’m running into this too with a cross-domain setup. Could the social redirect be clearing all headers? Maybe a workaround is to pass the auth token in the redirect url, but I’m not sure how to implement that with better-auth hooks.
Author
Owner

@agentic-com commented on GitHub (Aug 5, 2025):

I'm also facing the same issue

@agentic-com commented on GitHub (Aug 5, 2025): I'm also facing the same issue
Author
Owner

@subasshrestha commented on GitHub (Aug 11, 2025):

I created a custom plugin to enable Bearer token authentication with Social Auth

// server/plugins/socialBearer.ts
import { BetterAuthPlugin } from 'better-auth';

export const socialBearer = () => {
  return {
    id: 'social-bearer',
    onResponse: async (response) => {
      const authToken = response.headers.get('set-auth-token');
      if (authToken) {
        const location = response.headers.get('location');
        if (location) {
          response.headers.set(
            'location',
            `${location}?authToken=${authToken}`,
          );
        }
      }
    },
  } satisfies BetterAuthPlugin;
};
// server/auth.ts
export const auth = betterAuth({
  ...,
  plugins: [
    bearer(),
    socialBearer(),
  ],
});
// client/callback-page.tsx
const url = new URL(window.location.href);
const authToken = url.searchParams.get('authToken');
if (authToken) {
  localStorage.setItem('bearer_token', encodeURIComponent(authToken));
  url.searchParams.delete('authToken');
  window.history.replaceState({}, document.title, url);
}```
@subasshrestha commented on GitHub (Aug 11, 2025): I created a custom plugin to enable Bearer token authentication with Social Auth ```ts // server/plugins/socialBearer.ts import { BetterAuthPlugin } from 'better-auth'; export const socialBearer = () => { return { id: 'social-bearer', onResponse: async (response) => { const authToken = response.headers.get('set-auth-token'); if (authToken) { const location = response.headers.get('location'); if (location) { response.headers.set( 'location', `${location}?authToken=${authToken}`, ); } } }, } satisfies BetterAuthPlugin; }; ``` ```ts // server/auth.ts export const auth = betterAuth({ ..., plugins: [ bearer(), socialBearer(), ], }); ``` ```ts // client/callback-page.tsx const url = new URL(window.location.href); const authToken = url.searchParams.get('authToken'); if (authToken) { localStorage.setItem('bearer_token', encodeURIComponent(authToken)); url.searchParams.delete('authToken'); window.history.replaceState({}, document.title, url); }```
Author
Owner

@DanielBoxer commented on GitHub (Aug 20, 2025):

@subasshrestha Thanks, I have it working now with your plugin!

For anyone else trying to get this working, I also had to remove the cookie header in my server for it to use the bearer_token:

const headers = new Headers(c.req.raw.headers)
headers.delete('cookie')
const session = await getAuth(c.env).api.getSession({ headers })
@DanielBoxer commented on GitHub (Aug 20, 2025): @subasshrestha Thanks, I have it working now with your plugin! For anyone else trying to get this working, I also had to remove the cookie header in my server for it to use the bearer_token: ```js const headers = new Headers(c.req.raw.headers) headers.delete('cookie') const session = await getAuth(c.env).api.getSession({ headers }) ```
Author
Owner

@himself65 commented on GitHub (Sep 2, 2025):

https://github.com/better-auth/better-auth/pull/4330

@himself65 commented on GitHub (Sep 2, 2025): https://github.com/better-auth/better-auth/pull/4330
Author
Owner

@rohityadav-sas commented on GitHub (Oct 2, 2025):

Thanks, @subasshrestha. It is working now

@rohityadav-sas commented on GitHub (Oct 2, 2025): Thanks, @subasshrestha. It is working now
Author
Owner

@jorgedanisc commented on GitHub (Nov 10, 2025):

#4330

Hey, was this merged on any published version? Using the latest beta, but it does not seem to fix this issue or have the newly introduced bearerClient from the mentioned PR yet

@jorgedanisc commented on GitHub (Nov 10, 2025): > [#4330](https://github.com/better-auth/better-auth/pull/4330) Hey, was this merged on any published version? Using the latest beta, but it does not seem to fix this issue or have the newly introduced `bearerClient` from the mentioned PR yet
Author
Owner

@ping-maxwell commented on GitHub (Nov 10, 2025):

It's not resolved yet, I don't think.
cc @jorgedanisc

@ping-maxwell commented on GitHub (Nov 10, 2025): It's not resolved yet, I don't think. cc @jorgedanisc
Author
Owner

@kylecampbell commented on GitHub (Dec 13, 2025):

blocked by this

@kylecampbell commented on GitHub (Dec 13, 2025): blocked by this
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#1385