[GH-ISSUE #1745] Social signin from an API endpoint is connecting a social account to already existing user #8896

Closed
opened 2026-04-13 04:08:40 -05:00 by GiteaMirror · 3 comments
Owner

Originally created by @DimitarY on GitHub (Mar 9, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/1745

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

Register with credentials provider and then try to log in with social provider.

Current vs. Expected behavior

When users register with a credentials provider, it is possible to signin with a social provider that is using the same email without connecting the provider to their user profile

The expected behavior is that the sighin should be canceled because user don't have a connection to this social provider.

What version of Better Auth are you using?

1.2.3

Provide environment information

OS: Rocky Linux 9.5
Browser: Firefox

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

Backend

Auth config (if applicable)

import { db } from "@/db";
import { account } from "@/db/schema/account";
import { session } from "@/db/schema/session";
import { user } from "@/db/schema/user";
import { verification } from "@/db/schema/verification";
import { env } from "@/env";
import { sendMagicLink, sendVerificationRequest } from "@/lib/authSendRequest";
import { createEnumObject } from "@/lib/utils";
import { betterAuth, User as User_Original } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { nextCookies } from "better-auth/next-js";
import { admin, magicLink } from "better-auth/plugins";

export const auth = betterAuth({
  trustedOrigins: [env.NEXT_PUBLIC_BASE_URL],
  database: drizzleAdapter(db, {
    provider: "pg",
    schema: {
      user: user,
      session: session,
      account: account,
      verification: verification,
    },
  }),
  emailAndPassword: {
    enabled: true,
    autoSignIn: false,
  },
  emailVerification: {
    expiresIn: env.EMAIL_VERIFICATION_EXPIRES_IN_SECONDS,
    sendVerificationEmail: async ({ user, url }) => {
      await sendVerificationRequest({
        identifier: user.email,
        url: url,
      });
    },
  },
  socialProviders: {
    // FIXME: Block user from signing in with social providers if there is an credential account with the same email
    google: {
      clientId: env.BETTER_AUTH_GOOGLE_CLIENT_ID,
      clientSecret: env.BETTER_AUTH_GOOGLE_CLIENT_SECRET,
    },
    github: {
      clientId: env.BETTER_AUTH_GITHUB_CLIENT_ID,
      clientSecret: env.BETTER_AUTH_GITHUB_CLIENT_SECRET,
    },
  },
  account: {
    accountLinking: {
      enabled: true,
      allowMultipleAccounts: true,
      allowDifferentEmails: true,
    },
  },
  plugins: [
    admin({
      defaultRole: "user",
      adminRole: "admin",
    }),
    magicLink({
      expiresIn: env.MAGIC_LINK_EXPIRES_IN_SECONDS,
      sendMagicLink: async ({ email, url }) => {
        await sendMagicLink({
          identifier: email,
          url,
        });
      },
    }),
    nextCookies(), // make sure nextCookies is the last plugin in the array
  ],
});

// Same as admin plugin roles
export const UserRole = createEnumObject(["user", "admin"]);

export type User = User_Original & {
  role?: string | null;
  banned?: boolean | null;
  banReason?: string | null;
  banExpires?: Date | null;
};

Additional context

No response

Originally created by @DimitarY on GitHub (Mar 9, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/1745 ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce Register with credentials provider and then try to log in with social provider. ### Current vs. Expected behavior When users register with a credentials provider, it is possible to signin with a social provider that is using the same email without connecting the provider to their user profile The expected behavior is that the sighin should be canceled because user don't have a connection to this social provider. ### What version of Better Auth are you using? 1.2.3 ### Provide environment information ```bash OS: Rocky Linux 9.5 Browser: Firefox ``` ### Which area(s) are affected? (Select all that apply) Backend ### Auth config (if applicable) ```typescript import { db } from "@/db"; import { account } from "@/db/schema/account"; import { session } from "@/db/schema/session"; import { user } from "@/db/schema/user"; import { verification } from "@/db/schema/verification"; import { env } from "@/env"; import { sendMagicLink, sendVerificationRequest } from "@/lib/authSendRequest"; import { createEnumObject } from "@/lib/utils"; import { betterAuth, User as User_Original } from "better-auth"; import { drizzleAdapter } from "better-auth/adapters/drizzle"; import { nextCookies } from "better-auth/next-js"; import { admin, magicLink } from "better-auth/plugins"; export const auth = betterAuth({ trustedOrigins: [env.NEXT_PUBLIC_BASE_URL], database: drizzleAdapter(db, { provider: "pg", schema: { user: user, session: session, account: account, verification: verification, }, }), emailAndPassword: { enabled: true, autoSignIn: false, }, emailVerification: { expiresIn: env.EMAIL_VERIFICATION_EXPIRES_IN_SECONDS, sendVerificationEmail: async ({ user, url }) => { await sendVerificationRequest({ identifier: user.email, url: url, }); }, }, socialProviders: { // FIXME: Block user from signing in with social providers if there is an credential account with the same email google: { clientId: env.BETTER_AUTH_GOOGLE_CLIENT_ID, clientSecret: env.BETTER_AUTH_GOOGLE_CLIENT_SECRET, }, github: { clientId: env.BETTER_AUTH_GITHUB_CLIENT_ID, clientSecret: env.BETTER_AUTH_GITHUB_CLIENT_SECRET, }, }, account: { accountLinking: { enabled: true, allowMultipleAccounts: true, allowDifferentEmails: true, }, }, plugins: [ admin({ defaultRole: "user", adminRole: "admin", }), magicLink({ expiresIn: env.MAGIC_LINK_EXPIRES_IN_SECONDS, sendMagicLink: async ({ email, url }) => { await sendMagicLink({ identifier: email, url, }); }, }), nextCookies(), // make sure nextCookies is the last plugin in the array ], }); // Same as admin plugin roles export const UserRole = createEnumObject(["user", "admin"]); export type User = User_Original & { role?: string | null; banned?: boolean | null; banReason?: string | null; banExpires?: Date | null; }; ``` ### Additional context _No response_
GiteaMirror added the lockedbug labels 2026-04-13 04:08:40 -05:00
Author
Owner

@Bekacru commented on GitHub (Mar 9, 2025):

This is because you've enabled account linking. Maybe it should be more obvious, but enabling account linking means enabling automatic account linking. If you don't need that behavior and want your users to sign in only with an actively linked account, you can disable it.

<!-- gh-comment-id:2708895613 --> @Bekacru commented on GitHub (Mar 9, 2025): This is because you've enabled account linking. Maybe it should be more obvious, but enabling account linking means enabling automatic account linking. If you don't need that behavior and want your users to sign in only with an actively linked account, you can disable it.
Author
Owner

@DimitarY commented on GitHub (Mar 10, 2025):

@Bekacru, even without accountLinking, the accounts are linked. In the documentation accountLinking is needed to link the account using authClient.linkSocial

https://better-auth.vercel.app/docs/concepts/users-accounts#manually-linking-accounts

<!-- gh-comment-id:2710240351 --> @DimitarY commented on GitHub (Mar 10, 2025): @Bekacru, even without `accountLinking`, the accounts are linked. In the documentation `accountLinking` is needed to link the account using `authClient.linkSocial` https://better-auth.vercel.app/docs/concepts/users-accounts#manually-linking-accounts
Author
Owner

@DimitarY commented on GitHub (Mar 10, 2025):

@Bekacru you're solution is working great and account linking is working even with

    accountLinking: {
      enabled: false,
      allowMultipleAccounts: true,
      allowDifferentEmails: true,
    },```
<!-- gh-comment-id:2710779202 --> @DimitarY commented on GitHub (Mar 10, 2025): @Bekacru you're solution is working great and account linking is working even with ``` account: { accountLinking: { enabled: false, allowMultipleAccounts: true, allowDifferentEmails: true, },```
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#8896