[GH-ISSUE #2872] Get User Info #18007

Closed
opened 2026-04-15 16:21:55 -05:00 by GiteaMirror · 12 comments
Owner

Originally created by @offwork on GitHub (Jun 2, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/2872

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  1. Create a backend with drizzleadapter
  2. Create a frontend and use react client
  3. I will log in to X using the Twitter provider

Actually, I don't know why this error occurred because it occurred 1 week after I created the project.

Image

My Config:

auth.ts

import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { X_API } from "./constants";
import { db } from "@/db/drizzle";
import { schema } from "@/db/schema";

if (!process.env.BETTER_AUTH_SECRET || !process.env.BETTER_AUTH_URL) {
  throw new Error("BETTER_AUTH_SECRET and BETTER_AUTH_URL environment variables must be set.");
}

export const auth = betterAuth({
  secret: process.env.BETTER_AUTH_SECRET,
  baseURL: process.env.BETTER_AUTH_URL,
  database: drizzleAdapter(db, {
    provider: "pg", // or "mysql", "sqlite"
    schema: {
      ...schema, 
    }
  }),
  emailAndPassword: {
    enabled: false,
  },
  socialProviders: {
    twitter: {
      clientId: X_API.CLIENT_ID,
      clientSecret: X_API.CLIENT_SECRET,
      redirectUri: X_API.REDIRECT_URI,
    },
  },
});

auth-client.ts

import { createAuthClient } from "better-auth/react";

export const authClient = createAuthClient();

drizzle.ts

import { drizzle } from "drizzle-orm/neon-http";
import { neon } from "@neondatabase/serverless";
import { config } from "dotenv";

config({ path: ".env" }); // or .env.local

const sql = neon(process.env.DATABASE_URL!);
export const db = drizzle({ client: sql });

schema.ts

import { boolean, pgTable, serial, text, timestamp } from "drizzle-orm/pg-core";

export const companyTable = pgTable("company_table", {
  id: serial("id").primaryKey(),
  createdAt: timestamp("created_at").notNull().defaultNow(),
  image: text("image").notNull(),
  name: text("name").notNull(),
  handle: text("handle").notNull(),
  categories: text("categories").notNull(),
  region: text("region").notNull(),
});

export const profileTable = pgTable("profile_table", {
  id: serial("id").primaryKey(),
  createdAt: timestamp("created_at").notNull().defaultNow(),
  avatar: text("avatar").notNull(),
  mailAddress: text("mail_address").notNull(),
  socials: text("social_platforms").notNull(),
  address: text("wallet_address").notNull(),
  username: text("user_name").notNull(),
  xUserId: text("x_user_id").notNull(),
});

export const user = pgTable("user", {
  id: text("id").primaryKey(),
  name: text("name").notNull(),
  email: text("email").notNull().unique(),
  emailVerified: boolean("email_verified")
    .$defaultFn(() => false)
    .notNull(),
  image: text("image"),
  createdAt: timestamp("created_at")
    .$defaultFn(() => /* @__PURE__ */ new Date())
    .notNull(),
  updatedAt: timestamp("updated_at")
    .$defaultFn(() => /* @__PURE__ */ new Date())
    .notNull(),
});

export const session = pgTable("session", {
  id: text("id").primaryKey(),
  expiresAt: timestamp("expires_at").notNull(),
  token: text("token").notNull().unique(),
  createdAt: timestamp("created_at").notNull(),
  updatedAt: timestamp("updated_at").notNull(),
  ipAddress: text("ip_address"),
  userAgent: text("user_agent"),
  userId: text("user_id")
    .notNull()
    .references(() => user.id, { onDelete: "cascade" }),
});

export const account = pgTable("account", {
  id: text("id").primaryKey(),
  accountId: text("account_id").notNull(),
  providerId: text("provider_id").notNull(),
  userId: text("user_id")
    .notNull()
    .references(() => user.id, { onDelete: "cascade" }),
  accessToken: text("access_token"),
  refreshToken: text("refresh_token"),
  idToken: text("id_token"),
  accessTokenExpiresAt: timestamp("access_token_expires_at"),
  refreshTokenExpiresAt: timestamp("refresh_token_expires_at"),
  scope: text("scope"),
  password: text("password"),
  createdAt: timestamp("created_at").notNull(),
  updatedAt: timestamp("updated_at").notNull(),
});

export const verification = pgTable("verification", {
  id: text("id").primaryKey(),
  identifier: text("identifier").notNull(),
  value: text("value").notNull(),
  expiresAt: timestamp("expires_at").notNull(),
  createdAt: timestamp("created_at").$defaultFn(() => /* @__PURE__ */ new Date()),
  updatedAt: timestamp("updated_at").$defaultFn(() => /* @__PURE__ */ new Date()),
});

export const schema = {
  user,
  session,
  account,
  verification,
};

Current vs. Expected behavior

I expect Better-Auth to handle login in X

What version of Better Auth are you using?

1.2.8

Provide environment information

- OS: Mac
- Browser Chrome

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

Backend, Client

Auth config (if applicable)

import { betterAuth } from "better-auth"
export const auth = betterAuth({
  emailAndPassword: {  
    enabled: true
  },
});

Additional context

No response

Originally created by @offwork on GitHub (Jun 2, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/2872 ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce 1. Create a backend with drizzleadapter 2. Create a frontend and use react client 3. I will log in to X using the Twitter provider Actually, I don't know why this error occurred because it occurred 1 week after I created the project. <img width="520" alt="Image" src="https://github.com/user-attachments/assets/f186d171-5546-47a4-8dc1-ce69f9024cbe" /> My Config: > auth.ts ``` import { betterAuth } from "better-auth"; import { drizzleAdapter } from "better-auth/adapters/drizzle"; import { X_API } from "./constants"; import { db } from "@/db/drizzle"; import { schema } from "@/db/schema"; if (!process.env.BETTER_AUTH_SECRET || !process.env.BETTER_AUTH_URL) { throw new Error("BETTER_AUTH_SECRET and BETTER_AUTH_URL environment variables must be set."); } export const auth = betterAuth({ secret: process.env.BETTER_AUTH_SECRET, baseURL: process.env.BETTER_AUTH_URL, database: drizzleAdapter(db, { provider: "pg", // or "mysql", "sqlite" schema: { ...schema, } }), emailAndPassword: { enabled: false, }, socialProviders: { twitter: { clientId: X_API.CLIENT_ID, clientSecret: X_API.CLIENT_SECRET, redirectUri: X_API.REDIRECT_URI, }, }, }); ``` > auth-client.ts ``` import { createAuthClient } from "better-auth/react"; export const authClient = createAuthClient(); ``` > drizzle.ts ``` import { drizzle } from "drizzle-orm/neon-http"; import { neon } from "@neondatabase/serverless"; import { config } from "dotenv"; config({ path: ".env" }); // or .env.local const sql = neon(process.env.DATABASE_URL!); export const db = drizzle({ client: sql }); ``` > schema.ts ``` import { boolean, pgTable, serial, text, timestamp } from "drizzle-orm/pg-core"; export const companyTable = pgTable("company_table", { id: serial("id").primaryKey(), createdAt: timestamp("created_at").notNull().defaultNow(), image: text("image").notNull(), name: text("name").notNull(), handle: text("handle").notNull(), categories: text("categories").notNull(), region: text("region").notNull(), }); export const profileTable = pgTable("profile_table", { id: serial("id").primaryKey(), createdAt: timestamp("created_at").notNull().defaultNow(), avatar: text("avatar").notNull(), mailAddress: text("mail_address").notNull(), socials: text("social_platforms").notNull(), address: text("wallet_address").notNull(), username: text("user_name").notNull(), xUserId: text("x_user_id").notNull(), }); export const user = pgTable("user", { id: text("id").primaryKey(), name: text("name").notNull(), email: text("email").notNull().unique(), emailVerified: boolean("email_verified") .$defaultFn(() => false) .notNull(), image: text("image"), createdAt: timestamp("created_at") .$defaultFn(() => /* @__PURE__ */ new Date()) .notNull(), updatedAt: timestamp("updated_at") .$defaultFn(() => /* @__PURE__ */ new Date()) .notNull(), }); export const session = pgTable("session", { id: text("id").primaryKey(), expiresAt: timestamp("expires_at").notNull(), token: text("token").notNull().unique(), createdAt: timestamp("created_at").notNull(), updatedAt: timestamp("updated_at").notNull(), ipAddress: text("ip_address"), userAgent: text("user_agent"), userId: text("user_id") .notNull() .references(() => user.id, { onDelete: "cascade" }), }); export const account = pgTable("account", { id: text("id").primaryKey(), accountId: text("account_id").notNull(), providerId: text("provider_id").notNull(), userId: text("user_id") .notNull() .references(() => user.id, { onDelete: "cascade" }), accessToken: text("access_token"), refreshToken: text("refresh_token"), idToken: text("id_token"), accessTokenExpiresAt: timestamp("access_token_expires_at"), refreshTokenExpiresAt: timestamp("refresh_token_expires_at"), scope: text("scope"), password: text("password"), createdAt: timestamp("created_at").notNull(), updatedAt: timestamp("updated_at").notNull(), }); export const verification = pgTable("verification", { id: text("id").primaryKey(), identifier: text("identifier").notNull(), value: text("value").notNull(), expiresAt: timestamp("expires_at").notNull(), createdAt: timestamp("created_at").$defaultFn(() => /* @__PURE__ */ new Date()), updatedAt: timestamp("updated_at").$defaultFn(() => /* @__PURE__ */ new Date()), }); export const schema = { user, session, account, verification, }; ``` ### Current vs. Expected behavior I expect Better-Auth to handle login in X ### What version of Better Auth are you using? 1.2.8 ### Provide environment information ```bash - OS: Mac - Browser Chrome ``` ### Which area(s) are affected? (Select all that apply) Backend, Client ### Auth config (if applicable) ```typescript import { betterAuth } from "better-auth" export const auth = betterAuth({ emailAndPassword: { enabled: true }, }); ``` ### Additional context _No response_
GiteaMirror added the locked label 2026-04-15 16:21:55 -05:00
Author
Owner

@Kinfe123 commented on GitHub (Jun 2, 2025):

so was it working before then ?

<!-- gh-comment-id:2931872145 --> @Kinfe123 commented on GitHub (Jun 2, 2025): so was it working before then ?
Author
Owner

@offwork commented on GitHub (Jun 2, 2025):

Unfortunately it didn't work

<!-- gh-comment-id:2932593081 --> @offwork commented on GitHub (Jun 2, 2025): Unfortunately it didn't work
Author
Owner

@Kinfe123 commented on GitHub (Jun 3, 2025):

have you cross checked your X client credentials on the portal that they are not revoked or something

<!-- gh-comment-id:2933000597 --> @Kinfe123 commented on GitHub (Jun 3, 2025): have you cross checked your X client credentials on the portal that they are not revoked or something
Author
Owner

@AmoabaKelvin commented on GitHub (Jun 3, 2025):

This might be because of the X client credentials as @Kinfe123 mentioned. I had the same problem with Google oauth this time around, and the realization was that the scopes of the auth i had set up weren't permissible enough in the beginning, so i ended up getting this. Getting that fixed in google cloud console resolved the issue. You can try checking the credentials very well or just creating new ones and retrying to see if they'd work out.

<!-- gh-comment-id:2936108990 --> @AmoabaKelvin commented on GitHub (Jun 3, 2025): This might be because of the X client credentials as @Kinfe123 mentioned. I had the same problem with Google oauth this time around, and the realization was that the scopes of the auth i had set up weren't permissible enough in the beginning, so i ended up getting this. Getting that fixed in google cloud console resolved the issue. You can try checking the credentials very well or just creating new ones and retrying to see if they'd work out.
Author
Owner

@offwork commented on GitHub (Jun 3, 2025):

have you cross checked your X client credentials on the portal that they are not revoked or something

Yes, I checked many times

<!-- gh-comment-id:2937158887 --> @offwork commented on GitHub (Jun 3, 2025): > have you cross checked your X client credentials on the portal that they are not revoked or something Yes, I checked many times
Author
Owner

@offwork commented on GitHub (Jun 3, 2025):

This might be because of the X client credentials as @Kinfe123 mentioned. I had the same problem with Google oauth this time around, and the realization was that the scopes of the auth i had set up weren't permissible enough in the beginning, so i ended up getting this. Getting that fixed in google cloud console resolved the issue. You can try checking the credentials very well or just creating new ones and retrying to see if they'd work out.

I noticed this too, when better-auth redirects the application to log in to X, some errors like the following occur on the X login page.

Image Image Image
<!-- gh-comment-id:2937203350 --> @offwork commented on GitHub (Jun 3, 2025): > This might be because of the X client credentials as [@Kinfe123](https://github.com/Kinfe123) mentioned. I had the same problem with Google oauth this time around, and the realization was that the scopes of the auth i had set up weren't permissible enough in the beginning, so i ended up getting this. Getting that fixed in google cloud console resolved the issue. You can try checking the credentials very well or just creating new ones and retrying to see if they'd work out. I noticed this too, when better-auth redirects the application to log in to X, some errors like the following occur on the X login page. <img width="1728" alt="Image" src="https://github.com/user-attachments/assets/d0733fd2-8cac-4114-be5e-4ed214efc639" /> <img width="1728" alt="Image" src="https://github.com/user-attachments/assets/01cc8947-d0b3-4d09-80d7-6c3396b614c5" /> <img width="1728" alt="Image" src="https://github.com/user-attachments/assets/634d2c42-c984-411a-97e9-eca8c7e30a1d" />
Author
Owner

@offwork commented on GitHub (Jun 5, 2025):

@Kinfe123 better-auth, either by itself or together with next.js, causes the "too many requests" error.

<!-- gh-comment-id:2943193993 --> @offwork commented on GitHub (Jun 5, 2025): @Kinfe123 better-auth, either by itself or together with next.js, causes the "too many requests" error.
Author
Owner

@Kinfe123 commented on GitHub (Jun 6, 2025):

Where exactly are the "too many requests" happening?

<!-- gh-comment-id:2950061794 --> @Kinfe123 commented on GitHub (Jun 6, 2025): Where exactly are the "too many requests" happening?
Author
Owner

@saad-idea-l commented on GitHub (Jun 7, 2025):

I am facing the exact issue all of a sudden on Twitter. It was working before but now it started to give exact same error. My implementation is not using better-auth client but I am making HTTP API call to /sign-in/social with required body:

{ "provider": "twitter", "callbackURL": "/somecallback" }

I checked the source code and its due to the error on getting user basic info after acquiring the token + refreshToken. I tried it manually on Postman as well and Twitter was throwing me 401 unauthorized even with a valid Bearer token being passed.

8242ebde82/packages/better-auth/src/api/routes/callback.ts (L113)

I feel like its Twitter problem, not better-auth but super frustrating!

<!-- gh-comment-id:2952373407 --> @saad-idea-l commented on GitHub (Jun 7, 2025): I am facing the exact issue all of a sudden on Twitter. It was working before but now it started to give exact same error. My implementation is not using better-auth client but I am making HTTP API call to /sign-in/social with required body: `{ "provider": "twitter", "callbackURL": "/somecallback" }` I checked the source code and its due to the error on getting user basic info after acquiring the token + refreshToken. I tried it manually on Postman as well and Twitter was throwing me 401 unauthorized even with a valid Bearer token being passed. https://github.com/better-auth/better-auth/blob/8242ebde82a557ef790de279986fc3b1e3b1b646/packages/better-auth/src/api/routes/callback.ts#L113 I feel like its Twitter problem, not better-auth but super frustrating!
Author
Owner

@saad-idea-l commented on GitHub (Jun 7, 2025):

After several hours of digging, I think I found the reason.

Image

The app you have created on Twitter Developers portal is likely in 'Free' tier and it has super restricting rate-limit. @offwork the "Too many requests" is what I see when I make HTTP GET call on below API as well with the acquired access token:

https://api.x.com/2/users/me

Frustrating part is that Twitter API doesn't say anything but just returns this:

{
"title": "Too Many Requests",
"detail": "Too Many Requests",
"type": "about:blank",
"status": 429
}

This causes Better-Auth to acquire token, but not make any further calls to get user info. I don't understand why would Twitter make such bizarre API limit as well as not make API response any explanatory.

<!-- gh-comment-id:2952397086 --> @saad-idea-l commented on GitHub (Jun 7, 2025): After several hours of digging, I think I found the reason. ![Image](https://github.com/user-attachments/assets/f65ad3fd-7df8-4ffc-a47b-195939cea5c8) The app you have created on Twitter Developers portal is likely in 'Free' tier and it has super restricting rate-limit. @offwork the "Too many requests" is what I see when I make HTTP GET call on below API as well with the acquired access token: https://api.x.com/2/users/me Frustrating part is that Twitter API doesn't say anything but just returns this: { "title": "Too Many Requests", "detail": "Too Many Requests", "type": "about:blank", "status": 429 } This causes Better-Auth to acquire token, but not make any further calls to get user info. I don't understand why would Twitter make such bizarre API limit as well as not make API response any explanatory.
Author
Owner

@offwork commented on GitHub (Jun 9, 2025):

Where exactly are the "too many requests" happening?

It happens when you are directed to log in to X from the app.

<!-- gh-comment-id:2954715152 --> @offwork commented on GitHub (Jun 9, 2025): > Where exactly are the "too many requests" happening? It happens when you are directed to log in to X from the app.
Author
Owner

@Kinfe123 commented on GitHub (Jun 12, 2025):

The issue seems to be more related to Twitter. Please make sure to tag it accordingly if you believe the problem is from Better Auth

<!-- gh-comment-id:2968254571 --> @Kinfe123 commented on GitHub (Jun 12, 2025): The issue seems to be more related to Twitter. Please make sure to tag it accordingly if you believe the problem is from Better Auth
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#18007