Support Multiple Google Client IDs for Cross-Platform Token Verification #1873

Open
opened 2026-03-13 09:09:56 -05:00 by GiteaMirror · 18 comments
Owner

Originally created by @Nishchit14 on GitHub (Sep 7, 2025).

Currently, betterAuth does not support verifying Google tokens from multiple client IDs within a single configuration. This limitation creates issues when building cross-platform applications where each platform (iOS, Android, Web) has its own Google OAuth client ID, but all need to authenticate with the same backend API.

Use Case:

  • iOS app uses Google Client ID: 123-ios.googleusercontent.com
  • Android app uses Google Client ID: 456-android.googleusercontent.com
  • Both apps call the same better-auth API endpoint.

At present, only one client ID can be configured, which causes token verification to fail for other platform client ids.

Expected Behavior:
better-auth should allow configuring an array of Google client IDs and verify tokens against any of the configured client IDs or allow to use dynamic client id option at verification time.

This would enable seamless cross-platform authentication while maintaining security and consistency across apps.

Originally created by @Nishchit14 on GitHub (Sep 7, 2025). Currently, `betterAuth` does not support verifying Google tokens from multiple client IDs within a single configuration. This limitation creates issues when building cross-platform applications where each platform (iOS, Android, Web) has its own Google OAuth client ID, but all need to authenticate with the same backend API. **Use Case:** * iOS app uses Google Client ID: `123-ios.googleusercontent.com` * Android app uses Google Client ID: `456-android.googleusercontent.com` * Both apps call the same `better-auth` API endpoint. At present, only one client ID can be configured, which causes token verification to fail for other platform client ids. **Expected Behavior:** `better-auth` should allow configuring an **array of Google client IDs** and verify tokens against any of the configured client IDs or allow to use dynamic client id option at verification time. This would enable seamless cross-platform authentication while maintaining security and consistency across apps.
GiteaMirror added the enhancement label 2026-03-13 09:09:56 -05:00
Author
Owner

@RikhiSingh commented on GitHub (Sep 11, 2025):

Hi @Nishchit14 , Solved in #4583

@RikhiSingh commented on GitHub (Sep 11, 2025): Hi @Nishchit14 , Solved in #4583
Author
Owner

@Nishchit14 commented on GitHub (Sep 11, 2025):

That's awesome @RikhiSingh , Thank you very much. I am now waiting to get this PR merged.

@Nishchit14 commented on GitHub (Sep 11, 2025): That's awesome @RikhiSingh , Thank you very much. I am now waiting to get this PR merged.
Author
Owner

@amrmelsayed commented on GitHub (Oct 15, 2025):

@RikhiSingh @himself65 I noticed that this PR (support for Multiple Google Client IDs) was closed without merging, are there still plans to add this feature? It's a bit of show stopper for mobile development as we can only attach a single Google client at the moment.

@amrmelsayed commented on GitHub (Oct 15, 2025): @RikhiSingh @himself65 I noticed that this PR (support for Multiple Google Client IDs) was closed without merging, are there still plans to add this feature? It's a bit of show stopper for mobile development as we can only attach a single Google client at the moment.
Author
Owner

@RikhiSingh commented on GitHub (Oct 15, 2025):

@amrmelsayed It was solved in #4583 and later merged through different PR I believe

@RikhiSingh commented on GitHub (Oct 15, 2025): @amrmelsayed It was solved in #4583 and later merged through different PR I believe
Author
Owner

@amrmelsayed commented on GitHub (Oct 16, 2025):

Thanks @RikhiSingh would you know how to configure better-auth with multiple client IDs or can you point me to any code samples? The official documentation still assumes a single google clientId / clientSecret per app https://www.better-auth.com/docs/authentication/google.

@amrmelsayed commented on GitHub (Oct 16, 2025): Thanks @RikhiSingh would you know how to configure better-auth with multiple client IDs or can you point me to any code samples? The official documentation still assumes a single google clientId / clientSecret per app https://www.better-auth.com/docs/authentication/google.
Author
Owner

@RikhiSingh commented on GitHub (Oct 17, 2025):

@amrmelsayed

export const auth = betterAuth({
  socialProviders: {
    google: {
      clientId: [
        "123-ios.googleusercontent.com",
        "456-android.googleusercontent.com", 
        "789-web.googleusercontent.com"
      ],
      clientSecret: "your-client-secret",
    },
  },
});
@RikhiSingh commented on GitHub (Oct 17, 2025): @amrmelsayed ```typescript export const auth = betterAuth({ socialProviders: { google: { clientId: [ "123-ios.googleusercontent.com", "456-android.googleusercontent.com", "789-web.googleusercontent.com" ], clientSecret: "your-client-secret", }, }, }); ```
Author
Owner

@WilliamDrmrd commented on GitHub (Oct 28, 2025):

Hi @amrmelsayed did you make this work ?

@WilliamDrmrd commented on GitHub (Oct 28, 2025): Hi @amrmelsayed did you make this work ?
Author
Owner

@Vashishta-Mithra-Reddy commented on GitHub (Nov 2, 2025):

Stuck for the past 3 days trying to find a workaround, What is the current status of this I am still not able to use an array of client id's

@Vashishta-Mithra-Reddy commented on GitHub (Nov 2, 2025): Stuck for the past 3 days trying to find a workaround, What is the current status of this I am still not able to use an array of client id's
Author
Owner

@better-auth-agent[bot] commented on GitHub (Nov 2, 2025):

The latest update now supports multiple Google client IDs. You should be able to configure your Google provider with an array of client IDs instead of a single string. This means if your iOS app uses "123-ios.googleusercontent.com" and your Android app uses "456-android.googleusercontent.com," both tokens will be accepted during verification.

Next steps:
• Ensure you upgrade to the latest version of betterAuth where multiple client ID support has been merged.
• Update your configuration so that the Google provider’s clientId is defined as an array (or, if using the dynamic client ID option, pass it in the sign-in request).
• Verify that your tokens’ aud values match one of the IDs in your configured array.

If you’re still experiencing issues after updating, double-check that the provider configuration is correctly applied and consider reaching out with reproduction details. This enhancement was designed to enable seamless cross-platform sign-in without breaking existing setups [1], [2].

DiagramDiscordGitHub

Diagram Join Star

@better-auth-agent[bot] commented on GitHub (Nov 2, 2025): The latest update now supports multiple Google client IDs. You should be able to configure your Google provider with an array of client IDs instead of a single string. This means if your iOS app uses "123-ios.googleusercontent.com" and your Android app uses "456-android.googleusercontent.com," both tokens will be accepted during verification. Next steps: • Ensure you upgrade to the latest version of betterAuth where multiple client ID support has been merged. • Update your configuration so that the Google provider’s clientId is defined as an array (or, if using the dynamic client ID option, pass it in the sign-in request). • Verify that your tokens’ aud values match one of the IDs in your configured array. If you’re still experiencing issues after updating, double-check that the provider configuration is correctly applied and consider reaching out with reproduction details. This enhancement was designed to enable seamless cross-platform sign-in without breaking existing setups [[1]](https://github.com/better-auth/better-auth/issues/4498), [[2]](https://github.com/better-auth/better-auth/pull/4583). <!-- bot:webhook reply v1 --> [Diagram](https://repodiagrams.s3.eu-north-1.amazonaws.com/better-auth_ultra_detailed_interactive.html) • [Discord](https://discord.gg/better-auth) • [GitHub](https://github.com/better-auth/better-auth) [![Diagram](https://img.shields.io/badge/Diagram-2b3137?style=flat-square)](https://repodiagrams.s3.eu-north-1.amazonaws.com/better-auth_ultra_detailed_interactive.html) [![Join](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&style=flat-square)](https://discord.gg/better-auth) [![Star](https://img.shields.io/badge/star-181717?logo=github&logoColor=white&style=flat-square)](https://github.com/better-auth/better-auth)
Author
Owner

@Vashishta-Mithra-Reddy commented on GitHub (Nov 2, 2025):

I updated to the latest version but I still see this error Type 'string[]' is not assignable to type 'string'.ts(2322)
(property) GoogleOptions.clientId: string
The client ID of your application.

This is usually a string but can be any type depending on the provider. and it is still a string here right? interface GoogleOptions extends ProviderOptions {

clientId: string;

Am I doing something wrong?

@Vashishta-Mithra-Reddy commented on GitHub (Nov 2, 2025): I updated to the latest version but I still see this error Type 'string[]' is not assignable to type 'string'.ts(2322) (property) GoogleOptions.clientId: string The client ID of your application. This is usually a string but can be any type depending on the provider. and it is still a string here right? interface GoogleOptions extends ProviderOptions<GoogleProfile> { clientId: string; Am I doing something wrong?
Author
Owner

@better-auth-agent[bot] commented on GitHub (Nov 2, 2025):

It sounds like your runtime has been updated to support multiple client IDs, but your TypeScript types still expect a string. Make sure you’re using the latest version of both the runtime and its type definitions. In recent updates the Google provider was changed so that the configuration accepts an array of strings for the clientId, but if your project’s TypeScript types haven’t updated you may see that error [1].

Next steps:

  1. Verify that your package.json is pointing to the latest version of better-auth, and that no older type definitions are lingering (try deleting your node_modules and reinstalling).
  2. Check if there’s an updated declaration file (*.d.ts) for the Google provider. Sometimes the runtime update isn’t immediately reflected in the exported types, so you may need to override the type locally or use a type assertion (e.g., cast your clientId as string | string[]).
  3. If the error persists, consult the release notes or documentation for any migration steps regarding TypeScript users, as there may be a new configuration property or a different option name (for example, some updates also allow a dynamic or separate property for an array of client IDs) [2].

These steps should help match the runtime behavior with your type expectations and resolve the error.

DiagramDiscordGitHub

Diagram Join Star

@better-auth-agent[bot] commented on GitHub (Nov 2, 2025): It sounds like your runtime has been updated to support multiple client IDs, but your TypeScript types still expect a string. Make sure you’re using the latest version of both the runtime and its type definitions. In recent updates the Google provider was changed so that the configuration accepts an array of strings for the clientId, but if your project’s TypeScript types haven’t updated you may see that error [[1]](https://github.com/better-auth/better-auth/issues/4498). Next steps: 1. Verify that your package.json is pointing to the latest version of better-auth, and that no older type definitions are lingering (try deleting your node_modules and reinstalling). 2. Check if there’s an updated declaration file (*.d.ts) for the Google provider. Sometimes the runtime update isn’t immediately reflected in the exported types, so you may need to override the type locally or use a type assertion (e.g., cast your clientId as string | string[]). 3. If the error persists, consult the release notes or documentation for any migration steps regarding TypeScript users, as there may be a new configuration property or a different option name (for example, some updates also allow a dynamic or separate property for an array of client IDs) [[2]](https://github.com/better-auth/better-auth/pull/4583). These steps should help match the runtime behavior with your type expectations and resolve the error. <!-- bot:webhook reply v1 --> [Diagram](https://repodiagrams.s3.eu-north-1.amazonaws.com/better-auth_ultra_detailed_interactive.html) • [Discord](https://discord.gg/better-auth) • [GitHub](https://github.com/better-auth/better-auth) [![Diagram](https://img.shields.io/badge/Diagram-2b3137?style=flat-square)](https://repodiagrams.s3.eu-north-1.amazonaws.com/better-auth_ultra_detailed_interactive.html) [![Join](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&style=flat-square)](https://discord.gg/better-auth) [![Star](https://img.shields.io/badge/star-181717?logo=github&logoColor=white&style=flat-square)](https://github.com/better-auth/better-auth)
Author
Owner

@MemerGamer commented on GitHub (Nov 6, 2025):

This is still not working, tried casting the array to fix the issue temporarily but that did not work. It would be nice to have some solution for this, even if its a bit hacky

@amrmelsayed

export const auth = betterAuth({
socialProviders: {
google: {
clientId: [
"123-ios.googleusercontent.com",
"456-android.googleusercontent.com",
"789-web.googleusercontent.com"
],
clientSecret: "your-client-secret",
},
},
});

@MemerGamer commented on GitHub (Nov 6, 2025): This is still not working, tried casting the array to fix the issue temporarily but that did not work. It would be nice to have some solution for this, even if its a bit hacky > [@amrmelsayed](https://github.com/amrmelsayed) > > export const auth = betterAuth({ > socialProviders: { > google: { > clientId: [ > "123-ios.googleusercontent.com", > "456-android.googleusercontent.com", > "789-web.googleusercontent.com" > ], > clientSecret: "your-client-secret", > }, > }, > });
Author
Owner

@MemerGamer commented on GitHub (Nov 6, 2025):

Hi @Nishchit14 , Solved in #4583

This in fact was not solved the PR is closed NOT merged

@MemerGamer commented on GitHub (Nov 6, 2025): > Hi [@Nishchit14](https://github.com/Nishchit14) , Solved in [#4583](https://github.com/better-auth/better-auth/pull/4583) This in fact was not solved the PR is closed NOT merged
Author
Owner

@Sriketk commented on GitHub (Dec 10, 2025):

Is there an update regarding this? client id still only takes a string, not an array?

@Sriketk commented on GitHub (Dec 10, 2025): Is there an update regarding this? client id still only takes a string, not an array?
Author
Owner

@KingDoxik commented on GitHub (Dec 15, 2025):

This is a real blocker for mobile apps. Is there any workaround?

@KingDoxik commented on GitHub (Dec 15, 2025): This is a real blocker for mobile apps. Is there any workaround?
Author
Owner

@Sriketk commented on GitHub (Dec 15, 2025):

This is a real blocker for mobile apps. Is there any workaround?

Yup. Someone from the better auth team helped me out. https://discord.com/channels/1288403910284935179/1448130769674567820.

Its in this thread.

@Sriketk commented on GitHub (Dec 15, 2025): > This is a real blocker for mobile apps. Is there any workaround? Yup. Someone from the better auth team helped me out. https://discord.com/channels/1288403910284935179/1448130769674567820. Its in this thread.
Author
Owner

@Nishchit14 commented on GitHub (Dec 16, 2025):

This is a real blocker for mobile apps. Is there any workaround?

Yup. Someone from the better auth team helped me out. https://discord.com/channels/1288403910284935179/1448130769674567820.

Its in this thread.

For quick read

import { betterAuth } from "better-auth";
import { createAuthMiddleware } from "better-auth/api";
import { google } from "better-auth/social-providers";

export const auth = betterAuth({
  socialProviders: {
    google: {
      clientId: process.env.GOOGLE_CLIENT_ID!,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
      disableImplicitSignUp: true,
    },
  },
  hooks: {
    before: createAuthMiddleware(async (ctx) => {
      ctx.context.socialProviders = [
        ...ctx.context.socialProviders,
        {
          ...google({
            clientId: process.env.GOOGLE_IOS_CLIENT_ID!,
            clientSecret: process.env.GOOGLE_IOS_CLIENT_SECRET!,
            disableImplicitSignUp: true, // This does NOT work and will NOT toggle disableImplicitSignUp setting
          }),
          id: "google_ios",
        },
        {
          ...google({
            clientId: process.env.GOOGLE_ANDROID_CLIENT_ID!,
            clientSecret: process.env.GOOGLE_ANDROID_CLIENT_SECRET!,
          }),
          id: "google_android",
          disableImplicitSignUp: true, // This does work and will toggle disableImplicitSignUp setting
        },
      ];
    }),
  },
});
@Nishchit14 commented on GitHub (Dec 16, 2025): > > This is a real blocker for mobile apps. Is there any workaround? > > Yup. Someone from the better auth team helped me out. https://discord.com/channels/1288403910284935179/1448130769674567820. > > Its in this thread. For quick read ```ts import { betterAuth } from "better-auth"; import { createAuthMiddleware } from "better-auth/api"; import { google } from "better-auth/social-providers"; export const auth = betterAuth({ socialProviders: { google: { clientId: process.env.GOOGLE_CLIENT_ID!, clientSecret: process.env.GOOGLE_CLIENT_SECRET!, disableImplicitSignUp: true, }, }, hooks: { before: createAuthMiddleware(async (ctx) => { ctx.context.socialProviders = [ ...ctx.context.socialProviders, { ...google({ clientId: process.env.GOOGLE_IOS_CLIENT_ID!, clientSecret: process.env.GOOGLE_IOS_CLIENT_SECRET!, disableImplicitSignUp: true, // This does NOT work and will NOT toggle disableImplicitSignUp setting }), id: "google_ios", }, { ...google({ clientId: process.env.GOOGLE_ANDROID_CLIENT_ID!, clientSecret: process.env.GOOGLE_ANDROID_CLIENT_SECRET!, }), id: "google_android", disableImplicitSignUp: true, // This does work and will toggle disableImplicitSignUp setting }, ]; }), }, }); ```
Author
Owner

@Sriketk commented on GitHub (Dec 16, 2025):

additional context for those that want to implement this. you have to use the native google sdk in your mobile app first to connect to google. Upon successful sign in, the api will return a access token and an id token. Then either using better auths open api endpoints or using your custom endpoint(to use the better auth sdk), you pass those tokens over.

This is an example of your custom endpoint.

const result = await auth.api.signInSocial({
      body: {
        provider: "google_ios",
        idToken: {
          token: idToken,
          accessToken: accessToken,
        },
      },
      headers: req.headers,
    });

This is an example of using the openapi endpoint in swift

guard let url = URL(string: "https://www.try-cobalt.com/api/auth/sign-in/social")
            else { throw MobileAuthError.authenticationFailed("Invalid API URL") }

            let requestBody = GoogleAuthPayload(
                provider: "google_ios",
                idToken: GoogleIDToken(
                    token: idToken,
                    accessToken: accessToken
                )
            )

If you get a 200, you are successfully authenticated, and you can very easily and securely call any your business logic apis.

Also make sure your provider aligns with id in the auth.ts file.

@Sriketk commented on GitHub (Dec 16, 2025): additional context for those that want to implement this. you have to use the native google sdk in your mobile app first to connect to google. Upon successful sign in, the api will return a access token and an id token. Then either using better auths open api endpoints or using your custom endpoint(to use the better auth sdk), you pass those tokens over. This is an example of your custom endpoint. ```js const result = await auth.api.signInSocial({ body: { provider: "google_ios", idToken: { token: idToken, accessToken: accessToken, }, }, headers: req.headers, }); ``` This is an example of using the openapi endpoint in swift ```swift guard let url = URL(string: "https://www.try-cobalt.com/api/auth/sign-in/social") else { throw MobileAuthError.authenticationFailed("Invalid API URL") } let requestBody = GoogleAuthPayload( provider: "google_ios", idToken: GoogleIDToken( token: idToken, accessToken: accessToken ) ) ``` If you get a 200, you are successfully authenticated, and you can very easily and securely call any your business logic apis. Also make sure your provider aligns with id in the auth.ts file.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#1873