Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VK provider fix #3709

Merged
merged 17 commits into from Jul 13, 2022
Merged

VK provider fix #3709

merged 17 commits into from Jul 13, 2022

Conversation

alexTayanovsky
Copy link
Contributor

Reasoning 💡

VK provider is broken (see #3587, #2524 (comment)), so this PR aims to fix it, and adds Typescript support.

Checklist 🧢

  • Documentation
  • Tests
  • Ready to be merged

Affected issues 🎟

src/providers/vk.ts Outdated Show resolved Hide resolved
Copy link
Member

@balazsorban44 balazsorban44 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you. I actually created a VK app on my own and added a few suggestions to this PR.

Looks like there is also a merge conflict, please fix it as well!

src/providers/vk.ts Outdated Show resolved Hide resolved
src/providers/vk.ts Outdated Show resolved Hide resolved
@AtomBaytovich
Copy link

Hi! I ran into the same problem today, also a bug 'invalid client (client ID not defined)'.

Co-authored-by: Balázs Orbán <info@balazsorban.com>
@vercel
Copy link

vercel bot commented Feb 4, 2022

@alexTayanovsky is attempting to deploy a commit to the NextAuth Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions github-actions bot removed core Refers to `@auth/core` providers labels Feb 4, 2022
alexTayanovsky and others added 2 commits February 4, 2022 21:53
Co-authored-by: Balázs Orbán <info@balazsorban.com>
@vercel
Copy link

vercel bot commented Feb 4, 2022

This pull request is being automatically deployed with Vercel (learn more).
To see the status of your deployment, click below or on the icon next to each commit.

🔍 Inspect: https://vercel.com/nextauthjs/next-auth/CvFFgyBrEYVCMCZ4CjX3SbwT97Tz
✅ Preview: https://next-auth-git-fork-alextayanovsky-main-nextauthjs.vercel.app

@vercel vercel bot temporarily deployed to Preview February 4, 2022 19:09 Inactive
@github-actions github-actions bot added core Refers to `@auth/core` providers labels Feb 4, 2022
@vercel vercel bot temporarily deployed to Preview February 4, 2022 20:39 Inactive
@alexTayanovsky
Copy link
Contributor Author

@balazsorban44 Thank you very much for assistance! I've addressed your review comments & suggestions

@vercel vercel bot temporarily deployed to Preview February 5, 2022 17:09 Inactive
@vercel vercel bot temporarily deployed to Preview February 6, 2022 20:32 Inactive
@sergeyshaykhullin
Copy link

sergeyshaykhullin commented Apr 30, 2022

Seems like Mailru provider is also broken

[next-auth][error][OAUTH_PARSE_PROFILE_ERROR]
23
https://next-auth.js.org/errors#oauth_parse_profile_error Cannot read properties of undefined (reading 'toString') {
22
  error: {
21
    message: "Cannot read properties of undefined (reading 'toString')",
20
    stack: "TypeError: Cannot read properties of undefined (reading 'toString')\n" +
19
      '    at getProfile (/app/node_modules/next-auth/core/lib/oauth/callback.js:176:39)\n' +
18
      '    at processTicksAndRejections (node:internal/process/task_queues:96:5)\n' +
17
      '    at async oAuthCallback (/app/node_modules/next-auth/core/lib/oauth/callback.js:139:27)\n' +
16
      '    at async Object.callback (/app/node_modules/next-auth/core/routes/callback.js:50:11)\n' +
15
      '    at async NextAuthHandler (/app/node_modules/next-auth/core/index.js:139:28)\n' +
14
      '    at async NextAuthNextHandler (/app/node_modules/next-auth/next/index.js:21:19)\n' +
13
      '    at async /app/node_modules/next-auth/next/index.js:57:32\n' +
12
      '    at async Object.apiResolver (/app/node_modules/next/dist/server/api-utils/node.js:184:9)\n' +
11
      '    at async NextNodeServer.runApi (/app/node_modules/next/dist/server/next-server.js:397:9)\n' +
10
      '    at async Object.fn (/app/node_modules/next/dist/server/base-server.js:473:37)',
9
    name: 'TypeError'
8
  },
7
  OAuthProfile: {
6
    error: 'invalid request',
5
    error_code: 2,
4
    error_description: 'missing request parameter: access_token'
3
  },
2
  message: "Cannot read properties of undefined (reading 'toString')"
1
}

@ndom91
Copy link
Member

ndom91 commented May 7, 2022

Seems like Mailru provider is also broken

@sergeyshaykhullin Can you open a separate issue for mail.ru provider?

@ndom91
Copy link
Member

ndom91 commented May 7, 2022

@balazsorban44 I tested this fix, it is working, but was unable to save authorized user inside db

Log Output
[next-auth][error][OAUTH_CALLBACK_HANDLER_ERROR]
https://next-auth.js.org/errors#oauth_callback_handler_error
Invalid `p.account.create()` invocation in
C:\REDACTED\app\node_modules\@next-auth\prisma-adapter\dist\index.js:19:42

  16 },
  17 updateUser: ({ id, ...data }) => p.user.update({ where: { id }, data }),
  18 deleteUser: (id) => p.user.delete({ where: { id } }),
→ 19 linkAccount: (data) => p.account.create({
       data: {
         provider: 'vk',
         type: 'oauth',
         providerAccountId: 'REDACTED',
         access_token: 'REDACTED',
         expires_at: 1651408254,
         user_id: REDACTED,
         ~~~~~~~
         email: 'REDACTED',
         ~~~~~
         userId: 'REDACTED'
       }
     })

Unknown arg `user_id` in data.user_id for type AccountUncheckedCreateInput. Did you mean `userId`? Available args:
type AccountUncheckedCreateInput {
  id?: String
  userId: String
  type: String
  provider: String
  providerAccountId: String
  refresh_token?: String | Null
  access_token?: String | Null
  expires_at?: Int | Null
  token_type?: String | Null
  scope?: String | Null
  id_token?: String | Null
  session_state?: String | Null
  oauth_token_secret?: String | Null
  oauth_token?: String | Null
}
Unknown arg `email` in data.email for type AccountUncheckedCreateInput. Did you mean `id`? Available args:
type AccountUncheckedCreateInput {
  id?: String
  userId: String
  type: String
  provider: String
  providerAccountId: String
  refresh_token?: String | Null
  access_token?: String | Null
  expires_at?: Int | Null
  token_type?: String | Null
  scope?: String | Null
  id_token?: String | Null
  session_state?: String | Null
  oauth_token_secret?: String | Null
  oauth_token?: String | Null
}

 Error:
Invalid `p.account.create()` invocation in
C:\REDACTED\app\node_modules\@next-auth\prisma-adapter\dist\index.js:19:42

  16 },
  17 updateUser: ({ id, ...data }) => p.user.update({ where: { id }, data }),
  18 deleteUser: (id) => p.user.delete({ where: { id } }),
→ 19 linkAccount: (data) => p.account.create({
       data: {
         provider: 'vk',
         type: 'oauth',
         providerAccountId: 'REDACTED',
         access_token: 'REDACTED',
         expires_at: 1651408254,
         user_id: REDACTED,
         ~~~~~~~
         email: 'REDACTED',
         ~~~~~
         userId: 'REDACTED'
       }
     })

Unknown arg `user_id` in data.user_id for type AccountUncheckedCreateInput. Did you mean `userId`? Available args:
type AccountUncheckedCreateInput {
  id?: String
  userId: String
  type: String
  provider: String
  providerAccountId: String
  refresh_token?: String | Null
  access_token?: String | Null
  expires_at?: Int | Null
  token_type?: String | Null
  scope?: String | Null
  id_token?: String | Null
  session_state?: String | Null
  oauth_token_secret?: String | Null
  oauth_token?: String | Null
}
Unknown arg `email` in data.email for type AccountUncheckedCreateInput. Did you mean `id`? Available args:
type AccountUncheckedCreateInput {
  id?: String
  userId: String
  type: String
  provider: String
  providerAccountId: String
  refresh_token?: String | Null
  access_token?: String | Null
  expires_at?: Int | Null
  token_type?: String | Null
  scope?: String | Null
  id_token?: String | Null
  session_state?: String | Null
  oauth_token_secret?: String | Null
  oauth_token?: String | Null
}


    at Object.validate (C:\REDACTED\app\node_modules\@prisma\client\runtime\index.js:44425:20)
    at PrismaClient._executeRequest (C:\REDACTED\app\node_modules\@prisma\client\runtime\index.js:46509:17)
    at consumer (C:\REDACTED\app\node_modules\@prisma\client\runtime\index.js:46453:23)
    at C:\REDACTED\app\node_modules\@prisma\client\runtime\index.js:46457:76
    at runInChildSpan (C:\REDACTED\app\node_modules\@prisma\client\runtime\index.js:45702:12)
    at C:\REDACTED\app\node_modules\@prisma\client\runtime\index.js:46457:20
    at AsyncResource.runInAsyncScope (node:async_hooks:201:9)
    at PrismaClient._request (C:\REDACTED\app\node_modules\@prisma\client\runtime\index.js:46456:86)
    at C:\REDACTED\app\node_modules\@prisma\client\runtime\index.js:43088:25
    at _callback (C:\REDACTED\app\node_modules\@prisma\client\runtime\index.js:42852:52) {
  name: 'LinkAccountError',
  code: undefined
}

So theres two errors here according to your output:

  1. account model / table doesnt have a field called email
  2. The userId field is userId, not user_id

(See Models)

Unless you changed something in your prisma schema, those are the default values / field names.

@sergeyshaykhullin
Copy link

sergeyshaykhullin commented May 7, 2022

@ndom91 Yes, i changed using naming conventions, it works with google provider https://next-auth.js.org/adapters/prisma#naming-conventions

I am using @map("user_id") etc.

This is my schema.prisma

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

generator client {
  provider = "prisma-client-js"
}

model Account {
  id                 String  @id @default(uuid())
  userId             String  @map("user_id")
  type               String
  provider           String
  providerAccountId  String  @map("provider_account_id")
  refresh_token      String? @db.Text
  access_token       String? @db.Text
  expires_at         Int?
  token_type         String?
  scope              String?
  id_token           String? @db.Text
  session_state      String?
  oauth_token_secret String?
  oauth_token        String?

  user User @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@unique([provider, providerAccountId])
  @@map("accounts")
}

model Session {
  id           String   @id @default(uuid())
  sessionToken String   @unique @map("session_token")
  userId       String   @map("user_id")
  expires      DateTime
  user         User     @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@map("sessions")
}

model User {
  id            String    @id @default(uuid())
  name          String?
  email         String?   @unique
  emailVerified DateTime? @map("email_verified")
  image         String?
  accounts      Account[]
  sessions      Session[]

  @@map("users")
}

model VerificationToken {
  identifier String
  token      String   @unique
  expires    DateTime

  @@unique([identifier, token])
  @@map("verification_tokens")
}

And vk provider registration

VkProvider({
  clientId: process.env.VK_CLIENT_ID,
  clientSecret: process.env.VK_CLIENT_SECRET
}),

@ndom91
Copy link
Member

ndom91 commented May 7, 2022

@ndom91 Yes, i changed using naming conventions, it works with google provider https://next-auth.js.org/adapters/prisma#naming-conventions

I am using @map("user_id") etc.

Okay gotcha, makes sense.

So user_id should actually be there. However email still isn't on the account.

return {
id: profile.id,
name: [profile.first_name, profile.last_name].filter(Boolean).join(" "),
email: null,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ndom91 Maybe email: null is trying to save accounts.email column?

Copy link
Member

@ndom91 ndom91 Jun 9, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No so I meant that the email field is not on the Account table at all, but the User table (or users in your case).

Copy link
Member

@ndom91 ndom91 Jun 9, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But it in terms of why its failing on that linkAccount call, i'm still not sure..

In the /src/core/lib/callback-handler.ts, for example, it's just passing the whole account object into linkAccount function. This account, however, should only have these 4 fields according to the type definiton, and not email. See lines 156 and 206..

image

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ThangHuuVu @balazsorban44 so this is confusing me a bit, its looking like its trying to pass an Account, as well as some of the fields on User to the linkAccuont() method. Which should only take an account..

Is this the fault of this adapter? Or should we be deleting the email key off the data before tryign to pass it into linkAccount() as an argument?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ndom91 So if I understand correctly, the problem is that we're passing the account object which can contain all kinds of properties (it's extending from Record<string, unknown> and Partial<TokenSet> as seen here) into the adapter function linkAccount which expects only the object of type Account.

In this case, I think Prisma is working as expected. The proper solution IMO is that we should use the object with the desired type Account in the linkAccount implementation. Does that make sense?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that makes sense. So basically drop email?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let us drop anything but the expected properties... so I worry that another unexpected property could break the adapter again when used with another provider. WDYT?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that makes a lot of sense 👍

@MiXeR54
Copy link

MiXeR54 commented Jun 8, 2022

Any updates here? VK provider still not working properly

@pokatomnik
Copy link

I waited for this merge for tvo years.

@indicozy
Copy link

I also got invalid_client (client_id is undefined) error.

@ndom91
Copy link
Member

ndom91 commented Jul 10, 2022

@alexTayanovsky can you give me write rights to your fork? I'm trying to merge the latest main into your branch as it is fairly old.

@balazsorban44
Copy link
Member

balazsorban44 commented Jul 12, 2022

@alexTayanovsky there is a merge conflict, if you could please address that, and allow maintainers to edit, we could get this through the finish line!

Otherwise I'm going to close this PR, so someone else can open a new one including the fixes here 🙏 💚

@vercel
Copy link

vercel bot commented Jul 12, 2022

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated
next-auth ✅ Ready (Inspect) Visit Preview Jul 13, 2022 at 7:09AM (UTC)

@alexTayanovsky
Copy link
Contributor Author

@alexTayanovsky there is a merge conflict, if you could please address that, and allow maintainers to edit, we could get this through the finish line!

Otherwise I'm going to close this PR, so someone else can open a new one including the fixes here 🙏 💚

@balazsorban44 done ✅

@@ -4,7 +4,7 @@ import GitHubProvider from "next-auth/providers/github"
import Auth0Provider from "next-auth/providers/auth0"
import KeycloakProvider from "next-auth/providers/keycloak"
import TwitterProvider, {
TwitterLegacy as TwitterLegacyProvider,
// TwitterLegacy as TwitterLegacyProvider,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this commented out?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is an unused import that caused eslint warning, I guess this line can be removed instead

@vercel vercel bot temporarily deployed to Preview July 12, 2022 16:17 Inactive
@vercel vercel bot temporarily deployed to Preview July 13, 2022 07:09 Inactive
Copy link
Member

@balazsorban44 balazsorban44 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@balazsorban44 balazsorban44 merged commit cdf467e into nextauthjs:main Jul 13, 2022
@indicozy
Copy link

So, is it fixed now?

@pokatomnik
Copy link

Release this pls

@gosvoh
Copy link

gosvoh commented Nov 28, 2022

@balazsorban44 I tested this fix, it is working, but was unable to save authorized user inside db

Log Output

[next-auth][error][OAUTH_CALLBACK_HANDLER_ERROR]
https://next-auth.js.org/errors#oauth_callback_handler_error
Invalid `p.account.create()` invocation in
C:\REDACTED\app\node_modules\@next-auth\prisma-adapter\dist\index.js:19:42

  16 },
  17 updateUser: ({ id, ...data }) => p.user.update({ where: { id }, data }),
  18 deleteUser: (id) => p.user.delete({ where: { id } }),
→ 19 linkAccount: (data) => p.account.create({
       data: {
         provider: 'vk',
         type: 'oauth',
         providerAccountId: 'REDACTED',
         access_token: 'REDACTED',
         expires_at: 1651408254,
         user_id: REDACTED,
         ~~~~~~~
         email: 'REDACTED',
         ~~~~~
         userId: 'REDACTED'
       }
     })

Unknown arg `user_id` in data.user_id for type AccountUncheckedCreateInput. Did you mean `userId`? Available args:
type AccountUncheckedCreateInput {
  id?: String
  userId: String
  type: String
  provider: String
  providerAccountId: String
  refresh_token?: String | Null
  access_token?: String | Null
  expires_at?: Int | Null
  token_type?: String | Null
  scope?: String | Null
  id_token?: String | Null
  session_state?: String | Null
  oauth_token_secret?: String | Null
  oauth_token?: String | Null
}
Unknown arg `email` in data.email for type AccountUncheckedCreateInput. Did you mean `id`? Available args:
type AccountUncheckedCreateInput {
  id?: String
  userId: String
  type: String
  provider: String
  providerAccountId: String
  refresh_token?: String | Null
  access_token?: String | Null
  expires_at?: Int | Null
  token_type?: String | Null
  scope?: String | Null
  id_token?: String | Null
  session_state?: String | Null
  oauth_token_secret?: String | Null
  oauth_token?: String | Null
}

 Error:
Invalid `p.account.create()` invocation in
C:\REDACTED\app\node_modules\@next-auth\prisma-adapter\dist\index.js:19:42

  16 },
  17 updateUser: ({ id, ...data }) => p.user.update({ where: { id }, data }),
  18 deleteUser: (id) => p.user.delete({ where: { id } }),
→ 19 linkAccount: (data) => p.account.create({
       data: {
         provider: 'vk',
         type: 'oauth',
         providerAccountId: 'REDACTED',
         access_token: 'REDACTED',
         expires_at: 1651408254,
         user_id: REDACTED,
         ~~~~~~~
         email: 'REDACTED',
         ~~~~~
         userId: 'REDACTED'
       }
     })

Unknown arg `user_id` in data.user_id for type AccountUncheckedCreateInput. Did you mean `userId`? Available args:
type AccountUncheckedCreateInput {
  id?: String
  userId: String
  type: String
  provider: String
  providerAccountId: String
  refresh_token?: String | Null
  access_token?: String | Null
  expires_at?: Int | Null
  token_type?: String | Null
  scope?: String | Null
  id_token?: String | Null
  session_state?: String | Null
  oauth_token_secret?: String | Null
  oauth_token?: String | Null
}
Unknown arg `email` in data.email for type AccountUncheckedCreateInput. Did you mean `id`? Available args:
type AccountUncheckedCreateInput {
  id?: String
  userId: String
  type: String
  provider: String
  providerAccountId: String
  refresh_token?: String | Null
  access_token?: String | Null
  expires_at?: Int | Null
  token_type?: String | Null
  scope?: String | Null
  id_token?: String | Null
  session_state?: String | Null
  oauth_token_secret?: String | Null
  oauth_token?: String | Null
}


    at Object.validate (C:\REDACTED\app\node_modules\@prisma\client\runtime\index.js:44425:20)
    at PrismaClient._executeRequest (C:\REDACTED\app\node_modules\@prisma\client\runtime\index.js:46509:17)
    at consumer (C:\REDACTED\app\node_modules\@prisma\client\runtime\index.js:46453:23)
    at C:\REDACTED\app\node_modules\@prisma\client\runtime\index.js:46457:76
    at runInChildSpan (C:\REDACTED\app\node_modules\@prisma\client\runtime\index.js:45702:12)
    at C:\REDACTED\app\node_modules\@prisma\client\runtime\index.js:46457:20
    at AsyncResource.runInAsyncScope (node:async_hooks:201:9)
    at PrismaClient._request (C:\REDACTED\app\node_modules\@prisma\client\runtime\index.js:46456:86)
    at C:\REDACTED\app\node_modules\@prisma\client\runtime\index.js:43088:25
    at _callback (C:\REDACTED\app\node_modules\@prisma\client\runtime\index.js:42852:52) {
  name: 'LinkAccountError',
  code: undefined
}

So theres two errors here according to your output:

  1. account model / table doesnt have a field called email
  2. The userId field is userId, not user_id

(See Models)

Unless you changed something in your prisma schema, those are the default values / field names.

The error still appears. In addition to VK, my project uses authorization with Google, Yandex and Mail.ru and they work fine.

@Almasx
Copy link

Almasx commented Mar 5, 2023

Is there any workaround?

@theneuetimes
Copy link

theneuetimes commented Mar 26, 2023

@Almasx I managed to fix the issue in a pull request here (#7070), unfortunately it's been rejected. If you need Vk to work and want to implement my solution, you can run this command in your project directory:

npm install https://gitpkg.now.sh/theneuetimes/next-auth/packages/adapter-prisma?main

(if you're using ubuntu, you may need to wrap the link in a single quotation mark)

Alternatively, you can open your package.json file and edit your @next-auth/prisma-adapter dependency to this:

"@next-auth/prisma-adapter": "https://gitpkg.now.sh/theneuetimes/next-auth/packages/adapter-prisma?main",

Then run npm install.

If this still doesn't work and you only need it for your local environment, you can open node_modules/next-auth/providers/vk.js and change line 18 from this:

token: `https://oauth.vk.com/access_token?v=${apiVersion}`,

to this:

token: {
      url: `https://oauth.vk.com/access_token?v=${apiVersion}`,

      async request({ client, params, checks, provider }) {
        const response = await client.oauthCallback(
          provider.callbackUrl,
          params,
          checks,
          { exchangeBody: { client_id: options.clientId } }
        )

        return {
          tokens: {
            access_token: response.access_token,
            expires_at: response.expires_at
          }
        }
      },
    },

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core Refers to `@auth/core` providers
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet