[GH-ISSUE #3877] Redirect_uri in google provider config doesn't return google user with a custom callback route #27073

Closed
opened 2026-04-17 17:52:40 -05:00 by GiteaMirror · 2 comments
Owner

Originally created by @SpinBoxx on GitHub (Aug 8, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/3877

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  1. Create a backend
  2. Use Google as provider with a custom redirect_url config
    google: {
      clientId: process.env.GOOGLE_CLIENT_ID as string,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,

      mapProfileToUser: (user) => {
        console.log({ googleUser: user });

        return user;
      },
      redirectURI: process.env.BETTER_AUTH_URL + '/auth/sso/callback',
    },
  1. Add 2 custom routes to signin
@Get('/sso')
  public async loginSSO(@Request() request: express.Request) {
    const _res = await auth.api
      .signInSocial({
        body: {
          provider,
          scopes: [
            'https://www.googleapis.com/auth/userinfo.email',
            'https://www.googleapis.com/auth/userinfo.profile',
            'openid',
          ],
          disableRedirect: true,
        },
        asResponse: true,
        returnHeaders: true,
      })
      .then(async (res) => {
        const data = await res.json();
        return data as { url: string };
      })
      .catch((error) => {
        logger.error(`${this.context} logginSSO failed, ${error}`);
        return error;
      });

    return request.res?.redirect(_res.url);
  }

  @Get('/sso/callback')
  public async loginSsoCallback(@Request() request: express.Request) {
    const params = request.query;

    const { callbackUrl } = params;
    const res = await this.authController
      .loginSSO({
        headers: request.headers,
        cartId: request.session.cartId,
      })
      .catch((error) => {
        logger.error(`${this.context} logginSSO callback failed, catch ${error}`);
        return request.res?.redirect(`${env.ECOM_APP_URL}/${callbackUrl ? `/${callbackUrl}` : ``}`);
      });

    if (!res) {
      logger.error(`${this.context} logginSSO callback failed, no res ${res}`);
      return request.res?.redirect(`${env.ECOM_APP_URL}/${callbackUrl ? `/${callbackUrl}` : ``}`);
    }

    return request.res?.redirect(`${env.ECOM_APP_URL}${callbackUrl ? `/${callbackUrl}` : ``}`);
  }
  1. When you choose a Google account, it returns nothing from Google and auth.api.signInSocial does nothing.

  2. When I comment out the redirect_uri config from auth.ts, it works normally.

  3. I must have custom routes to sign in because I need to do something after I retrieve my user.

Current vs. Expected behavior

When it works (without redirect_uri), signInSocial retrieves my Google user.
When it doesn’t work (with redirect_uri), signInSocial doesn’t retrieve my Google user.

What version of Better Auth are you using?

1.2.12

Provide environment information

-

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

Backend

Auth config (if applicable)

import { betterAuth } from 'better-auth';
import { prismaAdapter } from 'better-auth/adapters/prisma';
import prisma from './authDb';
import { hashPassword, testPassword } from '@cv-erp/common';

export const auth = betterAuth({
  database: prismaAdapter(prisma, {
    provider: 'postgresql',
  }),

  emailAndPassword: {
    enabled: true,
    password: {
      hash: async (password) => {
        const hashedPassword = hashPassword(password);
        return hashedPassword;
      },
      verify: async ({ hash, password }) => {
        const isOK = testPassword(password, hash);
        return isOK;
      },
    },
  },
  socialProviders: {
    google: {
      clientId: process.env.GOOGLE_CLIENT_ID as string,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,

      mapProfileToUser: (user) => {
        console.log({ googleUser: user });

        return user;
      },
      redirectURI: process.env.BETTER_AUTH_URL + '/auth/sso/callback',
    },
  },

  trustedOrigins: ['http://localhost:5173', 'http://localhost:3000', 'https://accounts.google.com'],
  user: {
    additionalFields: {
      cartId: {
        input: false,
        required: false,
        returned: true,
        type: 'string',
      },
      contactId: {
        input: false,
        required: false,
        returned: true,
        type: 'string',
      },
    },
  },
});

Additional context

No response

Originally created by @SpinBoxx on GitHub (Aug 8, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/3877 ### Is this suited for github? - [ ] Yes, this is suited for github ### To Reproduce 1. Create a backend 2. Use Google as provider with a custom redirect_url config ``` google: { clientId: process.env.GOOGLE_CLIENT_ID as string, clientSecret: process.env.GOOGLE_CLIENT_SECRET as string, mapProfileToUser: (user) => { console.log({ googleUser: user }); return user; }, redirectURI: process.env.BETTER_AUTH_URL + '/auth/sso/callback', }, ``` 3. Add 2 custom routes to signin ``` @Get('/sso') public async loginSSO(@Request() request: express.Request) { const _res = await auth.api .signInSocial({ body: { provider, scopes: [ 'https://www.googleapis.com/auth/userinfo.email', 'https://www.googleapis.com/auth/userinfo.profile', 'openid', ], disableRedirect: true, }, asResponse: true, returnHeaders: true, }) .then(async (res) => { const data = await res.json(); return data as { url: string }; }) .catch((error) => { logger.error(`${this.context} logginSSO failed, ${error}`); return error; }); return request.res?.redirect(_res.url); } @Get('/sso/callback') public async loginSsoCallback(@Request() request: express.Request) { const params = request.query; const { callbackUrl } = params; const res = await this.authController .loginSSO({ headers: request.headers, cartId: request.session.cartId, }) .catch((error) => { logger.error(`${this.context} logginSSO callback failed, catch ${error}`); return request.res?.redirect(`${env.ECOM_APP_URL}/${callbackUrl ? `/${callbackUrl}` : ``}`); }); if (!res) { logger.error(`${this.context} logginSSO callback failed, no res ${res}`); return request.res?.redirect(`${env.ECOM_APP_URL}/${callbackUrl ? `/${callbackUrl}` : ``}`); } return request.res?.redirect(`${env.ECOM_APP_URL}${callbackUrl ? `/${callbackUrl}` : ``}`); } ``` 4. When you choose a Google account, it returns nothing from Google and auth.api.signInSocial does nothing. 5. When I comment out the redirect_uri config from auth.ts, it works normally. 6. I must have custom routes to sign in because I need to do something after I retrieve my user. ### Current vs. Expected behavior When it works (without redirect_uri), signInSocial retrieves my Google user. When it doesn’t work (with redirect_uri), signInSocial doesn’t retrieve my Google user. ### What version of Better Auth are you using? 1.2.12 ### Provide environment information ```bash - ``` ### Which area(s) are affected? (Select all that apply) Backend ### Auth config (if applicable) ```typescript import { betterAuth } from 'better-auth'; import { prismaAdapter } from 'better-auth/adapters/prisma'; import prisma from './authDb'; import { hashPassword, testPassword } from '@cv-erp/common'; export const auth = betterAuth({ database: prismaAdapter(prisma, { provider: 'postgresql', }), emailAndPassword: { enabled: true, password: { hash: async (password) => { const hashedPassword = hashPassword(password); return hashedPassword; }, verify: async ({ hash, password }) => { const isOK = testPassword(password, hash); return isOK; }, }, }, socialProviders: { google: { clientId: process.env.GOOGLE_CLIENT_ID as string, clientSecret: process.env.GOOGLE_CLIENT_SECRET as string, mapProfileToUser: (user) => { console.log({ googleUser: user }); return user; }, redirectURI: process.env.BETTER_AUTH_URL + '/auth/sso/callback', }, }, trustedOrigins: ['http://localhost:5173', 'http://localhost:3000', 'https://accounts.google.com'], user: { additionalFields: { cartId: { input: false, required: false, returned: true, type: 'string', }, contactId: { input: false, required: false, returned: true, type: 'string', }, }, }, }); ``` ### Additional context _No response_
GiteaMirror added the locked label 2026-04-17 17:52:40 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Aug 8, 2025):

This is expected behavior in Better Auth v1.2.12: the framework hardcodes the OAuth2 redirect URI for social providers like Google to a default path (e.g., /callback/google), ignoring any custom redirectURI you set in the provider config. If you try to use a custom callback route, the OAuth handshake will break and you won't get the Google user back—this matches what you're seeing. The only supported flow is to let the OAuth callback land on the default /callback/:id endpoint, then perform any custom logic or redirection you need from there (for example, by redirecting to your own route after authentication) [source].

If you need to run custom logic after sign-in, do it in the handler for the default callback route, not by changing the OAuth callback itself. Custom callback endpoints for social sign-in are not supported in this version [source].

To reply, just mention @dosu.


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

<!-- gh-comment-id:3167156096 --> @dosubot[bot] commented on GitHub (Aug 8, 2025): <!-- Answer --> This is expected behavior in Better Auth v1.2.12: the framework hardcodes the OAuth2 redirect URI for social providers like Google to a default path (e.g., `/callback/google`), ignoring any custom `redirectURI` you set in the provider config. If you try to use a custom callback route, the OAuth handshake will break and you won't get the Google user back—this matches what you're seeing. The only supported flow is to let the OAuth callback land on the default `/callback/:id` endpoint, then perform any custom logic or redirection you need from there (for example, by redirecting to your own route after authentication) [[source](https://github.com/better-auth/better-auth/issues/193)]. If you need to run custom logic after sign-in, do it in the handler for the default callback route, not by changing the OAuth callback itself. Custom callback endpoints for social sign-in are not supported in this version [[source](https://github.com/better-auth/better-auth/blob/0fe17704048bca8d52b547eb57a53ca89e84b78c/packages/better-auth/src/api/routes/sign-in.ts)]. <!-- 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/d8e63c9c-7b3d-4074-a22e-dc223db2e17d?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/d8e63c9c-7b3d-4074-a22e-dc223db2e17d?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/d8e63c9c-7b3d-4074-a22e-dc223db2e17d?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/d8e63c9c-7b3d-4074-a22e-dc223db2e17d?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/d8e63c9c-7b3d-4074-a22e-dc223db2e17d?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/d8e63c9c-7b3d-4074-a22e-dc223db2e17d?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/d8e63c9c-7b3d-4074-a22e-dc223db2e17d?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/3877)
Author
Owner

@SpinBoxx commented on GitHub (Aug 8, 2025):

OKaiii thanks it worked properly now :D

<!-- gh-comment-id:3167888160 --> @SpinBoxx commented on GitHub (Aug 8, 2025): OKaiii thanks it worked properly now :D
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#27073