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

Keep getting redirected with error: OAuthAccountNotLinked #519

Closed
1 of 5 tasks
alex-cory opened this issue Aug 1, 2020 · 47 comments
Closed
1 of 5 tasks

Keep getting redirected with error: OAuthAccountNotLinked #519

alex-cory opened this issue Aug 1, 2020 · 47 comments
Labels
stale Did not receive any activity for 60 days

Comments

@alex-cory
Copy link
Contributor

alex-cory commented Aug 1, 2020

Describe the bug
In your next-auth-example, default login screen (http://localhost:3000/api/auth/signin)

  1. I added TWITTER_ID and TWITTER_SECRET and DATABASE_URL to .env.local
  2. added all these callback URLs to twitter since they changed:
  3. did all the initial stuff: yarn && yarn add mongodb && yarn dev
  4. click sign in, then click login to twitter
  5. once it redirects back to /api/auth/callback/twitter instead of redirecting back to the home screen, it goes to /api/auth/error?error=OAuthAccountNotLinked then /api/auth/signin?error=OAuthAccountNotLinked
    image

I noticed that when I console.log in the signIn callback I still get the twitter data.
image

Am I missing something here or is this a bug? Because I'm getting the same issue in my personal app.

Documentation feedback
Documentation refers to searching through online documentation, code comments and issue history. The example project refers to next-auth-example.

  • Found the documentation helpful
  • Found documentation but was incomplete
  • Could not find relevant documentation
  • Found the example project helpful
  • Did not find the example project helpful
@alex-cory alex-cory added the bug Something isn't working label Aug 1, 2020
@iaincollins iaincollins added stale Did not receive any activity for 60 days and removed bug Something isn't working labels Aug 1, 2020
@iaincollins
Copy link
Member

This is the error page displayed for the OAuthAccountNotLinked:

error

If you see OAuthAccountNotLinked it means you have already signed in with a different provider that is associated with the same email address.

@alex-cory
Copy link
Contributor Author

Ah, but I only have signed in with Twitter. That's the only Provider I have with my app besides email AND I have only used this email via twitter oauth.
image

@alex-cory
Copy link
Contributor Author

alex-cory commented Aug 1, 2020

In fact I only have 1 account in my entire accounts collection, and that is the twitter signin for this user.

@alex-cory
Copy link
Contributor Author

Btw, I don't have this problem in 2.2.0

@alex-cory
Copy link
Contributor Author

I also wanted to say that I think this is a great library and I really appreciate all your hard work. 👏👏👏

@iaincollins
Copy link
Member

I am not able to replicate this issue.

  • I can sign in with Twitter OAuth account, signed out, then sign back in.
  • I have explicitly tired this with a MongoDB database.
  • This can be confirmed using the example project.

I can only suggest enabling debug: true option and seeing if your database connection is throwing any errors or unexpected behaviour.

@iaincollins
Copy link
Member

iaincollins commented Aug 2, 2020

added all these callback URLs to twitter since they changed:
http://localhost:3000/api/auth/callback/twitter
http://localhost:3000/auth/oauth/twitter/callback <- old docs said this (came up when I searched "twitter" on next-auth.js.og)

To confirm, the callback API has not changed between version 2 and version 3. The documentation for providers is correct: https://next-auth.js.org/configuration/providers#using-a-built-in-provider

The second callback URL format is for version 1 which was released in 2016-2017. At the top of the page it says "WARNING This documentation is for version 1 which is no longer supported."

^ Edit: It might be worth us removing the v1 one docs from the website if they are coming up in search results above more relevant results.

@iaincollins
Copy link
Member

Btw, I don't have this problem in 2.2.0

Hmm that's interesting.

Can you replicate this issue with the example project?

@iaincollins
Copy link
Member

PS: My suspicion here is that it might be a weird interaction with the Atlas Mongo instance. I no longer have an active mongo.net instance to hand to test it, but it would be worth identifying if the same issue be replicated with the example project. If it can it's probably related to the database connection in some way.

@alex-cory
Copy link
Contributor Author

I will test the example project right now and report back

@iaincollins
Copy link
Member

Thanks! If you do get the same issue, any information you can provide about the database / connection type (including example of the connection info, minus sensitive info) would be very helpful.

@alex-cory
Copy link
Contributor Author

It works with 2.2.0 in the example.
image
My .env.local looks like

NEXTAUTH_URL=http://localhost:3000
SECRET=
AUTH0_ID=
AUTH0_SECRET=
AUTH0_DOMAIN=
FACEBOOK_ID=
FACEBOOK_SECRET=
GITHUB_ID=
GITHUB_SECRET=
GOOGLE_ID=
GOOGLE_SECRET=
TWITTER_ID=my-twitter-id
TWITTER_SECRET=my-twitter-secret
EMAIL_SERVER=smtp://username:password@smtp.example.com.com:587
EMAIL_FROM=NextAuth <noreply@example.com>
DATABASE_URL=mongodb+srv://username:password@clusterName.u01ei.mongodb.net/database-name?retryWrites=true&w=majority&synchronize=true

@iaincollins
Copy link
Member

iaincollins commented Aug 2, 2020

I can't replicate an issue with the example project, using MongoDB and Twitter. I don't have any problems signing in, signing out and then back in again.

The example uses 3.x. Did you downgrade the version of it? Can you replicate the issue raise with the example project, running 3.x?

@iaincollins
Copy link
Member

^ Sorry hit save prematurely (was on mobile).

Thinking about it, if it's just a test account I'd be included to drop those collections and just re-create it again (and use v3).

I have absolutely no idea what would be causing this. I've spun up a mongo.net service on Atlas and still can't replicate it.

@alex-cory
Copy link
Contributor Author

I'll drop and try again. Yes, I downgraded and checked in yarn.lock to make sure it was 2.2.0.

@alex-cory
Copy link
Contributor Author

alex-cory commented Aug 2, 2020

You were correct. It was the DB. Weird... So sorry I drug you through all this. I should've tried that from the get go.

I also tried your example with a fresh DB and it worked. Didn't try a new collection within the same db, but I'd assume it would work with one.

@nathansebhastian
Copy link

nathansebhastian commented Aug 21, 2020

Hi @iaincollins I just found the same error when testing oauth with Google and Github. I'm wondering is there a way to connect both providers to the same user instead of rejecting it? So sign in with Google and sign in with Github will go to the same user account.

@fzxu
Copy link

fzxu commented Aug 22, 2020

I got the same error if both facebook and google has the same email. It's better to provide option to merge user.

@nathansebhastian
Copy link

@fzxu I've been tinkering with this since yesterday. Until the library handles the merge, I think you need to handle the sign-in process yourself

I've tried writing the SignIn callback configurations, but it seems to be called after the DB operation is resolved.
The next option is updating the next-auth.functions.js to see if it works.

@iaincollins
Copy link
Member

@nsebhastian @fzxu

Please feel free to open a new issue if you have a question about why something works a particular way.

This has come up before so I've raised a PR which addresses it in the FAQ:


When I sign in with another account with the same email address, why are accounts not linked automatically?

Automatic account linking on sign in is not secure between arbitrary providers - with the exception of allowing users to sign in via an email addresses as a fallback (as they must verify their email address as part of the flow).

When an email address is associated with an OAuth account it does not necessarily mean that it has been verified as belonging to account holder — how email address verification is handled is not part of the OAuth specification and varies between providers (e.g. some do not verify first, some do verify first, others return metadata indiciating the verification status).

With automatic account linking on sign in, this can be exploited by bad actors to hijack accounts by creating an OAuth account associated with the email address of another user.

For this reason it is not secure to automatically link accounts between abitrary providers on sign in, which is why this feature is generally not provided by authentication service and is not provided by NextAuth.js.

Automatic acccount linking is seen on some sites, sometimes insecurely. It can be technically possible to do automatic account linking securely if you trust all the providers involved to ensure they have securely verified the email address associated with the account, but requires placing trust (and transfering the risk) to those providers to handle the process securely.

Examples of scenarios where this is secure include with an OAuth provider you control (e.g. that only authorizes users internal to your organization) or with a provider you explicitly trust to have verified the users email address.

Automatic account linking is not a planned feature of NextAuth.js, however there is scope to improve the user experience of account linking and of handling this flow, in a secure way. Typically this involves providing a fallback option to sign in via email, which is already possible (and recommended), but the current implementation of this flow could be improved on.

Providing support for secure account linking and unlinking of additional providers - which can only be done if a user is already signed in already - was origionally a feature in v1.x but has not been present since v2.0, is planned to return in a future release.

@mattzuckermann
Copy link

You were correct. It was the DB. Weird... So sorry I drug you through all this. I should've tried that from the get go.

I also tried your example with a fresh DB and it worked. Didn't try a new collection within the same db, but I'd assume it would work with one.

This also worked for me. Thanks so much everyone!

@spsaucier-bakkt
Copy link

spsaucier-bakkt commented Jan 3, 2021

I'm having this issue with a new user account using email only with Auth0 (no other oauth providers are enabled), and using a brand new database isn't a possibility. Is there an alternative to that fix?

@spsaucier-bakkt
Copy link

Actually, it appears to work correctly when using session instead of database, i.e.:

  session: {
    // Use JSON Web Tokens for session instead of database sessions.
    jwt: true, 
    
    // Seconds - How long until an idle session expires and is no longer valid.
    maxAge: 30 * 24 * 60 * 60, // 30 days
  },

@nimeshmaharjan1
Copy link

I am getting this OAuthAccountNotLinked when trying to login with github. But if I get this error I wish it would redirect or do anything but its just stuck in the login page with no session I think I am doing something wrong.

@swiftcc624
Copy link

swiftcc624 commented Nov 24, 2022

please use allowDangerousEmailAccountLinking: true

https://next-auth.js.org/configuration/providers/oauth

@domharrington
Copy link

I was getting this error (OAuthAccountNotLinked) with the following dependencies:

next-auth@^4.10.3
@next-auth/mongodb-adapter@^1.0.4

It's only when I enabled the debug option that I saw the following come up in the logs during another failed signin attempt:

[next-auth][error][OAUTH_CALLBACK_HANDLER_ERROR]
https://next-auth.js.org/errors#oauth_callback_handler_error E11000 duplicate key error collection: next-auth-db.accounts index: accounts_provider_provider_account_id_key dup key: { provider: "github", provider_account_id: null } MongoServerError: E11000 duplicate key error collection: next-auth-db.accounts index: accounts_provider_provider_account_id_key dup key: { provider: "github", provider_account_id: null }
    at /code/node_modules/mongodb/lib/operations/insert.js:53:33
    at /code/node_modules/mongodb/lib/cmap/connection_pool.js:299:25
    at /code/node_modules/mongodb/lib/sdam/server.js:212:17
    at handleOperationResult (/code/node_modules/mongodb/lib/sdam/server.js:287:20)
    at Connection.onMessage (/code/node_modules/mongodb/lib/cmap/connection.js:219:9)
    at MessageStream.<anonymous> (/code/node_modules/mongodb/lib/cmap/connection.js:60:60)
    at MessageStream.emit (events.js:400:28)
    at processIncomingData (/code/node_modules/mongodb/lib/cmap/message_stream.js:132:20)
    at MessageStream._write (/code/node_modules/mongodb/lib/cmap/message_stream.js:33:9)
    at writeOrBuffer (internal/streams/writable.js:358:12) {
  name: 'LinkAccountError',
  code: 11000
}

What stood out to me here is that provider_account_id is not what the property is called anymore, it is now called providerAccountId. This changed in NextAuth v4 compared to v3: https://next-auth.js.org/getting-started/upgrade-v4#schema-changes

On further investigation, I appeared to have a unique index setup in the database for a property that wasn't being used anymore:

Untitled

This meant that only a single account could ever be present in the database 😬 I've inherited this project/database so I'm not sure where that came from. Does this module ever create the indexes for you? Has that ever been a feature? It would've been nice if NextAuth bubbled up the appropriate error to the surface, at least on development, instead of hiding it behind a generic error code.

I hope this helps someone else in this situation! Thanks again for the module.

@fjprobos-divisin
Copy link

please use allowDangerousEmailAccountLinking: true

https://next-auth.js.org/configuration/providers/oauth

I don't see this option as available. I am using next-auth": "^4.10.3

@leonardomso
Copy link

please use allowDangerousEmailAccountLinking: true
https://next-auth.js.org/configuration/providers/oauth

I don't see this option as available. I am using next-auth": "^4.10.3

You should pass the allowDangerousEmailAccountLinking option to your provider, like this:

GoogleProvider({
    clientId: process.env.GOOGLE_CLIENT_ID || '',
    clientSecret: process.env.GOOGLE_CLIENT_SECRET || '',
    allowDangerousEmailAccountLinking: true,
}),

@stevenirby
Copy link

allowDangerousEmailAccountLinking: true,

Thank you! This worked for me.

@kirtirajsinh
Copy link

I'm getting the same error. While trying to create a user data on the database.
Here's my code:

import { getServerSession } from "next-auth";
import { PrismaAdapter } from "@next-auth/prisma-adapter";
import { prisma } from "./db";
import GoogleProvider from "next-auth/providers/google";

export const authOptions = {
  callbacks: {
    async signIn({ user, account, session }) {
      try {
        console.log(account, "account");
        console.log(user, "user");
        console.log(session, "session");
        // Check if the OAuth account is already linked to an existing user account
        const linkedAccount = await prisma.user.findUnique({
          where: {
            email: user.email,
          },
        });

        console.log(linkedAccount, "linkedAccount");

        if (linkedAccount) {
          // If the OAuth account is already linked, return the corresponding user
          return true;
        } else {
          // If the OAuth account is not linked, create a new user account and link it to the OAuth account
          const newUser = await prisma.user.create({
            data: {
              name: user.name,
              email: user.email,
              image: user.image,
              token: 0.1,
            },
          });

          // Return the newly created user
          return true;
        }
      } catch (error) {
        console.error(error);
        return false;
      }
    },
  },

  adapter: PrismaAdapter(prisma),
  secret: process.env.NEXTAUTH_SECRET,
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    }),
  ],
};

export const getServerAuthSession = (ctx) => {
  return getServerSession(ctx.req, ctx.res, authOptions);
};

It works if I don't add a callback it. But I added it because I need the token field to be added. Now I'm getting error=OAuthAccountNotLinked. if someone has resolved it can you help this fellow dev out.

@pedroferreira37
Copy link

pedroferreira37 commented May 13, 2023

I ran into this issue, what works for me was defining the provider id, check below:

providers: [
>     GoogleProvider({
>       id: "google",
>       name: "Google",
>       clientId: process.env.GOOGLE_CLIENT_ID,
>       clientSecret: process.env.GOOGLE_SECRET_KEY,
>     }),
>   ],

@shahbhavik01
Copy link

kirtirajsinh

I have a very similar setup to you and am getting the above error too. Were you able to resolve this?

@nimeshmaharjan1
Copy link

nimeshmaharjan1 commented May 16, 2023 via email

@fjprobos-divisin
Copy link

please use allowDangerousEmailAccountLinking: true
https://next-auth.js.org/configuration/providers/oauth

I don't see this option as available. I am using next-auth": "^4.10.3

You should pass the allowDangerousEmailAccountLinking option to your provider, like this:

GoogleProvider({
    clientId: process.env.GOOGLE_CLIENT_ID || '',
    clientSecret: process.env.GOOGLE_CLIENT_SECRET || '',
    allowDangerousEmailAccountLinking: true,
}),

Thanks for your reply, I needed to update Next.js and then next-auth. Now I am using next-auth 4.20.1 and next 12.3.4 and the property is part of the social provider.

@kirtirajsinh
Copy link

share the code with you in a bit I did something with prisma.upsert if the ac

pls, do share. I'm still stuck on the same issue.

@nimeshmaharjan1
Copy link

nimeshmaharjan1 commented May 18, 2023 via email

@nimeshmaharjan1
Copy link

nimeshmaharjan1 commented May 18, 2023 via email

@leo-petrucci
Copy link

You should pass the allowDangerousEmailAccountLinking option to your provider, like this:

Oh my god I love you

@0xw5555
Copy link

0xw5555 commented Jan 14, 2024

I am getting this OAuthAccountNotLinked when trying to login with DISCORD . its just stuck in the login page with no session & can’t enter a giveaway without connecting my discord account. Any idea how to fix it ?

@Mirasaki
Copy link

I was having this issue as well, and in the hopes this will help at least someone: Using the Prisma adapter, I had a seeder populating the database with our administrators (users, roles, permissions, etc.) which ended up causing this. The User was being created with the default cuid() id value, instead of the (selected) provider user id.

@unknwOO
Copy link

unknwOO commented Feb 10, 2024

I was having this issue as well, and in the hopes this will help at least someone: Using the Prisma adapter, I had a seeder populating the database with our administrators (users, roles, permissions, etc.) which ended up causing this. The User was being created with the default cuid() id value, instead of the (selected) provider user id.

Hey man, I am having this issue right now with the next auth v5 beta, what did you do to solve the problem of prisma adapter generating the default cuid? Thank you really much

@Ydin0
Copy link

Ydin0 commented Feb 12, 2024

I was having this issue as well, and in the hopes this will help at least someone: Using the Prisma adapter, I had a seeder populating the database with our administrators (users, roles, permissions, etc.) which ended up causing this. The User was being created with the default cuid() id value, instead of the (selected) provider user id.

Can you expand on this i am stuck on this issue been trying to solve for a long time now

@nimeshmaharjan1
Copy link

nimeshmaharjan1 commented Feb 12, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stale Did not receive any activity for 60 days
Projects
None yet
Development

No branches or pull requests