[GH-ISSUE #371] User's additionalFields doesn't work for OAuth #16871

Closed
opened 2026-04-15 14:51:32 -05:00 by GiteaMirror · 7 comments
Owner

Originally created by @EilonK05 on GitHub (Oct 30, 2024).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/371

Originally assigned to: @Bekacru on GitHub.

Describe the bug
I added a field to the user scheme: cid.
I use the generic OAuth plugin with a custom getUserInfo function, but when I return the user with all the fields and my additional one, I get an error from Prisma because the additional field has not been passed to Prisma.

To Reproduce
Steps to reproduce the behavior:
here is my auth.ts file:

export const auth = betterAuth({
  database: prismaAdapter(prisma, {
    provider: "mongodb",
    generateId: false,
  }),
  user: {
    additionalFields: {
      cid: {
        type: "string",
        required: true,
        returned: true,
        input: true,
      },
    },
  },
  plugins: [
    genericOAuth({
      config: [
        {
          providerId: "vatsim-connect",
          clientId: process.env.VATSIM_CONNECT_CLIENT_ID!,
          clientSecret: process.env.VATSIM_CONNECT_CLIENT_SECRET!,
          authorizationUrl: "https://auth-dev.vatsim.net/oauth/authorize",
          tokenUrl: "https://auth-dev.vatsim.net/oauth/token",
          userInfoUrl: "https://auth-dev.vatsim.net/api/user",
          scopes: ["full_name", "vatsim_details", "email"],
          pkce: true,
          responseType: "code",
          getUserInfo: async (tokens) => {
            const res = await fetch("https://auth-dev.vatsim.net/api/user", {
              headers: {
                Authorization: `Bearer ${tokens.accessToken}`,
              },
            });
            const user = await res.json();
            console.log(user);
            return {
              id: "",
              cid: user.data.cid,
              name: user.data.personal.name_full,
              email: user.data.personal.email,
              emailVerified: true,
              createdAt: new Date(),
              updatedAt: new Date(),
            };
          },
        },
      ],
    }),
  ],
});

And my schma.prisma file:

model User {
  id            String    @id @default(auto()) @map("_id") @db.ObjectId
  cid           String
  email         String    @unique
  name          String
  emailVerified Boolean
  image         String?
  createdAt     DateTime
  updatedAt     DateTime
  Session       Session[]
  Account       Account[]

  @@map("user")
}

model Session {
  id        String   @id @default(auto()) @map("_id") @db.ObjectId
  expiresAt DateTime
  ipAddress String?
  userAgent String?
  userId    String   @db.ObjectId
  user      User     @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@map("session")
}

model Account {
  id           String    @id @default(auto()) @map("_id") @db.ObjectId
  accountId    String
  providerId   String
  userId       String    @db.ObjectId
  user         User      @relation(fields: [userId], references: [id], onDelete: Cascade)
  accessToken  String?
  refreshToken String?
  idToken      String?
  expiresAt    DateTime?
  password     String?

  @@map("account")
}

model Verification {
  id         String   @id @default(auto()) @map("_id") @db.ObjectId
  identifier String
  value      String
  expiresAt  DateTime

  @@map("verification")
}

This is the error that I'm getting:

PrismaClientValidationError: 
Invalid `prisma.user.create()` invocation:

{
  data: {
    id: undefined,
    name: "Web Ten",
    email: "auth.dev10@vatsim.net",
    emailVerified: true,
    image: undefined,
    createdAt: new Date("2024-10-30T17:39:49.802Z"),
    updatedAt: new Date("2024-10-30T17:39:49.802Z"),
+   cid: String
  }
}

Argument `cid` is missing.
    at Dn (D:\Files\Programing\vatil-training\node_modules\@prisma\client\runtime\library.js:114:8082)
    at Mn.handleRequestError (D:\Files\Programing\vatil-training\node_modules\@prisma\client\runtime\library.js:121:7396)
    at Mn.handleAndLogRequestError (D:\Files\Programing\vatil-training\node_modules\@prisma\client\runtime\library.js:121:7061)
    at Mn.request (D:\Files\Programing\vatil-training\node_modules\@prisma\client\runtime\library.js:121:6745)
    at async l (D:\Files\Programing\vatil-training\node_modules\@prisma\client\runtime\library.js:130:9633)
    at async Object.create (webpack-internal:///(rsc)/./node_modules/better-auth/dist/adapters/prisma.js:6:689)
    at async f (webpack-internal:///(rsc)/./node_modules/better-auth/dist/chunk-YVHVIMAI.js:21:4127)
    at async Object.createOAuthUser (webpack-internal:///(rsc)/./node_modules/better-auth/dist/chunk-YVHVIMAI.js:21:4927)
    at async eval (webpack-internal:///(rsc)/./node_modules/better-auth/dist/plugins.js:62:936)
    at async handle (webpack-internal:///(rsc)/./node_modules/better-call/dist/index.js:588:17)
    at async Ye.i.<computed> (webpack-internal:///(rsc)/./node_modules/better-auth/dist/chunk-5KNKZ7OW.js:135:8453)
    at async handler (webpack-internal:///(rsc)/./node_modules/better-call/dist/index.js:804:26)
    at async handler (webpack-internal:///(rsc)/./node_modules/better-call/dist/index.js:855:19)
    at async AppRouteRouteModule.do (D:\Files\Programing\vatil-training\node_modules\next\dist\compiled\next-server\app-route.runtime.dev.js:10:32801)
    at async AppRouteRouteModule.handle (D:\Files\Programing\vatil-training\node_modules\next\dist\compiled\next-server\app-route.runtime.dev.js:10:38302)
    at async doRender (D:\Files\Programing\vatil-training\node_modules\next\dist\server\base-server.js:1493:42)
    at async responseGenerator (D:\Files\Programing\vatil-training\node_modules\next\dist\server\base-server.js:1834:28)
    at async DevServer.renderToResponseWithComponentsImpl (D:\Files\Programing\vatil-training\node_modules\next\dist\server\base-server.js:1878:28)
    at async DevServer.renderPageComponent (D:\Files\Programing\vatil-training\node_modules\next\dist\server\base-server.js:2292:24)
    at async DevServer.renderToResponseImpl (D:\Files\Programing\vatil-training\node_modules\next\dist\server\base-server.js:2330:32)
    at async DevServer.pipeImpl (D:\Files\Programing\vatil-training\node_modules\next\dist\server\base-server.js:984:25)
    at async NextNodeServer.handleCatchallRenderRequest (D:\Files\Programing\vatil-training\node_modules\next\dist\server\next-server.js:281:17)
    at async DevServer.handleRequestImpl (D:\Files\Programing\vatil-training\node_modules\next\dist\server\base-server.js:877:17)
    at async D:\Files\Programing\vatil-training\node_modules\next\dist\server\dev\next-dev-server.js:373:20
    at async Span.traceAsyncFn (D:\Files\Programing\vatil-training\node_modules\next\dist\trace\trace.js:157:20)
    at async DevServer.handleRequest (D:\Files\Programing\vatil-training\node_modules\next\dist\server\dev\next-dev-server.js:370:24)
    at async invokeRender (D:\Files\Programing\vatil-training\node_modules\next\dist\server\lib\router-server.js:183:21)
    at async handleRequest (D:\Files\Programing\vatil-training\node_modules\next\dist\server\lib\router-server.js:360:24)
    at async requestHandlerImpl (D:\Files\Programing\vatil-training\node_modules\next\dist\server\lib\router-server.js:384:13)
    at async Server.requestListener (D:\Files\Programing\vatil-training\node_modules\next\dist\server\lib\start-server.js:142:13) {
  clientVersion: '5.21.1'
}

Expected behavior
I expected that my cid field would be passed on to Prisma along with the rest of the fields.

Desktop (please complete the following information):

  • OS: Windows 11
  • Browser: Google Chrome
  • Version: 130.0.6723.70
Originally created by @EilonK05 on GitHub (Oct 30, 2024). Original GitHub issue: https://github.com/better-auth/better-auth/issues/371 Originally assigned to: @Bekacru on GitHub. **Describe the bug** I added a field to the user scheme: cid. I use the generic OAuth plugin with a custom getUserInfo function, but when I return the user with all the fields and my additional one, I get an error from Prisma because the additional field has not been passed to Prisma. **To Reproduce** Steps to reproduce the behavior: here is my auth.ts file: ```ts export const auth = betterAuth({ database: prismaAdapter(prisma, { provider: "mongodb", generateId: false, }), user: { additionalFields: { cid: { type: "string", required: true, returned: true, input: true, }, }, }, plugins: [ genericOAuth({ config: [ { providerId: "vatsim-connect", clientId: process.env.VATSIM_CONNECT_CLIENT_ID!, clientSecret: process.env.VATSIM_CONNECT_CLIENT_SECRET!, authorizationUrl: "https://auth-dev.vatsim.net/oauth/authorize", tokenUrl: "https://auth-dev.vatsim.net/oauth/token", userInfoUrl: "https://auth-dev.vatsim.net/api/user", scopes: ["full_name", "vatsim_details", "email"], pkce: true, responseType: "code", getUserInfo: async (tokens) => { const res = await fetch("https://auth-dev.vatsim.net/api/user", { headers: { Authorization: `Bearer ${tokens.accessToken}`, }, }); const user = await res.json(); console.log(user); return { id: "", cid: user.data.cid, name: user.data.personal.name_full, email: user.data.personal.email, emailVerified: true, createdAt: new Date(), updatedAt: new Date(), }; }, }, ], }), ], }); ``` And my schma.prisma file: ``` model User { id String @id @default(auto()) @map("_id") @db.ObjectId cid String email String @unique name String emailVerified Boolean image String? createdAt DateTime updatedAt DateTime Session Session[] Account Account[] @@map("user") } model Session { id String @id @default(auto()) @map("_id") @db.ObjectId expiresAt DateTime ipAddress String? userAgent String? userId String @db.ObjectId user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@map("session") } model Account { id String @id @default(auto()) @map("_id") @db.ObjectId accountId String providerId String userId String @db.ObjectId user User @relation(fields: [userId], references: [id], onDelete: Cascade) accessToken String? refreshToken String? idToken String? expiresAt DateTime? password String? @@map("account") } model Verification { id String @id @default(auto()) @map("_id") @db.ObjectId identifier String value String expiresAt DateTime @@map("verification") } ``` This is the error that I'm getting: ``` PrismaClientValidationError: Invalid `prisma.user.create()` invocation: { data: { id: undefined, name: "Web Ten", email: "auth.dev10@vatsim.net", emailVerified: true, image: undefined, createdAt: new Date("2024-10-30T17:39:49.802Z"), updatedAt: new Date("2024-10-30T17:39:49.802Z"), + cid: String } } Argument `cid` is missing. at Dn (D:\Files\Programing\vatil-training\node_modules\@prisma\client\runtime\library.js:114:8082) at Mn.handleRequestError (D:\Files\Programing\vatil-training\node_modules\@prisma\client\runtime\library.js:121:7396) at Mn.handleAndLogRequestError (D:\Files\Programing\vatil-training\node_modules\@prisma\client\runtime\library.js:121:7061) at Mn.request (D:\Files\Programing\vatil-training\node_modules\@prisma\client\runtime\library.js:121:6745) at async l (D:\Files\Programing\vatil-training\node_modules\@prisma\client\runtime\library.js:130:9633) at async Object.create (webpack-internal:///(rsc)/./node_modules/better-auth/dist/adapters/prisma.js:6:689) at async f (webpack-internal:///(rsc)/./node_modules/better-auth/dist/chunk-YVHVIMAI.js:21:4127) at async Object.createOAuthUser (webpack-internal:///(rsc)/./node_modules/better-auth/dist/chunk-YVHVIMAI.js:21:4927) at async eval (webpack-internal:///(rsc)/./node_modules/better-auth/dist/plugins.js:62:936) at async handle (webpack-internal:///(rsc)/./node_modules/better-call/dist/index.js:588:17) at async Ye.i.<computed> (webpack-internal:///(rsc)/./node_modules/better-auth/dist/chunk-5KNKZ7OW.js:135:8453) at async handler (webpack-internal:///(rsc)/./node_modules/better-call/dist/index.js:804:26) at async handler (webpack-internal:///(rsc)/./node_modules/better-call/dist/index.js:855:19) at async AppRouteRouteModule.do (D:\Files\Programing\vatil-training\node_modules\next\dist\compiled\next-server\app-route.runtime.dev.js:10:32801) at async AppRouteRouteModule.handle (D:\Files\Programing\vatil-training\node_modules\next\dist\compiled\next-server\app-route.runtime.dev.js:10:38302) at async doRender (D:\Files\Programing\vatil-training\node_modules\next\dist\server\base-server.js:1493:42) at async responseGenerator (D:\Files\Programing\vatil-training\node_modules\next\dist\server\base-server.js:1834:28) at async DevServer.renderToResponseWithComponentsImpl (D:\Files\Programing\vatil-training\node_modules\next\dist\server\base-server.js:1878:28) at async DevServer.renderPageComponent (D:\Files\Programing\vatil-training\node_modules\next\dist\server\base-server.js:2292:24) at async DevServer.renderToResponseImpl (D:\Files\Programing\vatil-training\node_modules\next\dist\server\base-server.js:2330:32) at async DevServer.pipeImpl (D:\Files\Programing\vatil-training\node_modules\next\dist\server\base-server.js:984:25) at async NextNodeServer.handleCatchallRenderRequest (D:\Files\Programing\vatil-training\node_modules\next\dist\server\next-server.js:281:17) at async DevServer.handleRequestImpl (D:\Files\Programing\vatil-training\node_modules\next\dist\server\base-server.js:877:17) at async D:\Files\Programing\vatil-training\node_modules\next\dist\server\dev\next-dev-server.js:373:20 at async Span.traceAsyncFn (D:\Files\Programing\vatil-training\node_modules\next\dist\trace\trace.js:157:20) at async DevServer.handleRequest (D:\Files\Programing\vatil-training\node_modules\next\dist\server\dev\next-dev-server.js:370:24) at async invokeRender (D:\Files\Programing\vatil-training\node_modules\next\dist\server\lib\router-server.js:183:21) at async handleRequest (D:\Files\Programing\vatil-training\node_modules\next\dist\server\lib\router-server.js:360:24) at async requestHandlerImpl (D:\Files\Programing\vatil-training\node_modules\next\dist\server\lib\router-server.js:384:13) at async Server.requestListener (D:\Files\Programing\vatil-training\node_modules\next\dist\server\lib\start-server.js:142:13) { clientVersion: '5.21.1' } ``` **Expected behavior** I expected that my cid field would be passed on to Prisma along with the rest of the fields. **Desktop (please complete the following information):** - OS: Windows 11 - Browser: Google Chrome - Version: 130.0.6723.70
GiteaMirror added the lockedbug labels 2026-04-15 14:51:32 -05:00
Author
Owner

@jamesmall commented on GitHub (Oct 30, 2024):

You've set it up accordingly in the auth file already, I recommend setting it up in the auth-client file as well.

I would recommend adding the additional fields and then generating the schema again if you haven't already. Once you have the schema situated to satisfy Prisma follow this guide to update the additionalFields for the authClient as well.

https://www.better-auth.com/docs/concepts/typescript#inferring-additional-fields-on-client

All of my TS errors went away after updating the authClient using the plugin.

<!-- gh-comment-id:2448411239 --> @jamesmall commented on GitHub (Oct 30, 2024): You've set it up accordingly in the auth file already, I recommend setting it up in the auth-client file as well. I would recommend adding the additional fields and then generating the schema again if you haven't already. Once you have the schema situated to satisfy Prisma follow this guide to update the additionalFields for the authClient as well. [https://www.better-auth.com/docs/concepts/typescript#inferring-additional-fields-on-client](https://www.better-auth.com/docs/concepts/typescript#inferring-additional-fields-on-client) All of my TS errors went away after updating the authClient using the plugin.
Author
Owner

@EilonK05 commented on GitHub (Oct 30, 2024):

This is my auth-client:

export const authClient = createAuthClient({
  baseURL: process.env.BETTER_AUTH_URL,
  plugins: [genericOAuthClient(), inferAdditionalFields<typeof auth>()],
});

I also regenerated my Prisma schema from scratch and still i got the same error.
It's look like when creating the user the original schema is been used instead of the one with the additional fields.

<!-- gh-comment-id:2448457527 --> @EilonK05 commented on GitHub (Oct 30, 2024): This is my auth-client: ```ts export const authClient = createAuthClient({ baseURL: process.env.BETTER_AUTH_URL, plugins: [genericOAuthClient(), inferAdditionalFields<typeof auth>()], }); ``` I also regenerated my Prisma schema from scratch and still i got the same error. It's look like when creating the user the original schema is been used instead of the one with the additional fields.
Author
Owner

@jamesmall commented on GitHub (Oct 30, 2024):

@EilonK05 Which integration are you using? Additionally, setting the type of the inferAdditionalFields isn't part of the guide and will not yield the results you are seeking. Add the fields as an object param of the inferAdditionalFields plugin. Here is my implementation of the inferAdditionalFields:

export const authClient = createAuthClient({
  plugins: [
    inferAdditionalFields({
      user: {
        fName: {
          type: "string",
        },
        lName: {
          type: "string",
        },
      },
    }),
  ],
  baseURL: "http://localhost:5173",
});

One more thing... are you using npx @better-auth/cli generate to generate the schema? You may have to use the --config flag to set the auth.ts file.

Could you also elaborate on why you are using the returned field? That isn't part of the docs.

<!-- gh-comment-id:2448644219 --> @jamesmall commented on GitHub (Oct 30, 2024): @EilonK05 Which integration are you using? Additionally, setting the type of the inferAdditionalFields isn't part of the guide and will not yield the results you are seeking. Add the fields as an object param of the inferAdditionalFields plugin. Here is my implementation of the inferAdditionalFields: ``` export const authClient = createAuthClient({ plugins: [ inferAdditionalFields({ user: { fName: { type: "string", }, lName: { type: "string", }, }, }), ], baseURL: "http://localhost:5173", }); ``` One more thing... are you using `npx @better-auth/cli generate` to generate the schema? You may have to use the `--config` flag to set the auth.ts file. Could you also elaborate on why you are using the `returned` field? That isn't part of the docs.
Author
Owner

@EilonK05 commented on GitHub (Oct 31, 2024):

I'm using the Next integration.
Also when i set the inferAdditionalFields plugin like that i'm getting the same error:

export const authClient = createAuthClient({
  baseURL: process.env.BETTER_AUTH_URL,
  plugins: [
    genericOAuthClient(),
    inferAdditionalFields({
      user: {
        cid: {
          type: "string",
        },
      },
    }),
  ],
});

About the returned field, is was my mistake. I removed it.

<!-- gh-comment-id:2450446559 --> @EilonK05 commented on GitHub (Oct 31, 2024): I'm using the Next integration. Also when i set the inferAdditionalFields plugin like that i'm getting the same error: ```ts export const authClient = createAuthClient({ baseURL: process.env.BETTER_AUTH_URL, plugins: [ genericOAuthClient(), inferAdditionalFields({ user: { cid: { type: "string", }, }, }), ], }); ```` About the ```returned``` field, is was my mistake. I removed it.
Author
Owner

@jamesmall commented on GitHub (Oct 31, 2024):

Interesting. I'm tapped out of ideas. Looking at the error you're getting, it looks like that field isn't making to Prisma from better-auth. Prisma is expecting but it's not getting it. I would look at how the signUp method is being implemented and specifically what is being passed. The API might not be returning that value. I apologize I couldn't be of more help!

<!-- gh-comment-id:2450625800 --> @jamesmall commented on GitHub (Oct 31, 2024): Interesting. I'm tapped out of ideas. Looking at the error you're getting, it looks like that field isn't making to Prisma from better-auth. Prisma is expecting but it's not getting it. I would look at how the signUp method is being implemented and specifically what is being passed. The API might not be returning that value. I apologize I couldn't be of more help!
Author
Owner

@Bekacru commented on GitHub (Oct 31, 2024):

the additional fields will still be stripped out in the case of OAuth. We're trying to have a solution for both the OAuth plugin and the built in social providers to make this easier and work well typescript.

<!-- gh-comment-id:2450694811 --> @Bekacru commented on GitHub (Oct 31, 2024): the additional fields will still be stripped out in the case of OAuth. We're trying to have a solution for both the OAuth plugin and the built in social providers to make this easier and work well typescript.
Author
Owner

@alex-deneuvillers commented on GitHub (Nov 21, 2024):

Hi, is there any chance for this issue to be fixed in the 1.0.0 release ? Thanks :)

<!-- gh-comment-id:2491905835 --> @alex-deneuvillers commented on GitHub (Nov 21, 2024): Hi, is there any chance for this issue to be fixed in the 1.0.0 release ? Thanks :)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#16871