Support for multiple Auth Providers

Hi,

I’m trying to use NextAuth for authentication for a NextJS and Strapi setup.

I’ve followed [1] to set things up and it’s working fairly well for the most part. That said, I’ve run into several issues that I’m not sure how to resolve:

  1. It appears that Strapi doesn’t support having a single email associated with multiple providers. For example, a user could choose to log in once via Google and once via Facebook. Ideally, both login methods should lead the user to be logged in with the same user account. Is single-user / multiple-provider something that is planned?

  2. When using the email sign-in method of NextAuth (See [2] - it’s basically a magic-link based login), I assume we need to perform a call to Strapi at /api/auth/<provider>/callback to ensure the user gets registered. That said, I don’t see an appropriate provider for this (See [3]). Is there anything I’m missing to make this login method work?

Happy to provide more details if needed.

Reference:

1 Like

Hey @boop

At the moment you are correct, we can’t properly handle multiple auth providers for a user, we have an open feature request for this here: Multiple authentication providers per user - Roadmap | Product Roadmap

See strapi/strapi#10746 for issue #2.

Hi,

The board doesn’t seem to be publicly accessible. Is there any update on this?

We are experiencing same issue here regarding different login method for each provider.
Without being able to link accounts to multiple providers it’s a high maintenance job to keep track of things. Now we have to show users appropriate error messages when they choose to login using a different method than the one they used for sign up.
It has appeared to be a limitation to them.

i found solution for strapi 4 using passwordless and providers like google and facebook :

file:/node_modules/@strapi/plugin-users-permissions/server/controllers/auth.js

if (provider === ‘local’) {

}else {

try {

let user = await getService(‘providers’).connect(provider, ctx.query);

// Check if the user exists based on email

const existingUser = await strapi

.query(‘plugin::users-permissions.user’)

.findOne({ where: { email: user.email } });

if (existingUser) {

// Check if the existing user is linked to another provider

if (existingUser.provider !== provider) {

// Link accounts

try{user = await strapi.query(‘plugin::users-permissions.user’).update({data:{ provider},where:{ id: existingUser.id}}

)}catch(e){console.log(“error updating”,e)}

}

}

if (user.blocked) {

throw new ForbiddenError(‘Your account has been blocked by an administrator’);

}

return ctx.send({

jwt: getService(‘jwt’).issue({ id: user.id }),

user: await sanitizeUser(user, ctx),

});

} catch (error) {

throw new ApplicationError(error.message);

}

}

file:/node_modules/@strapi/plugin-users-permissions/server/services/providers.js

@@ -67,8 +67,15 @@ module.exports = ({ strapi }) => {

const advancedSettings = await strapi

.store({ type: ‘plugin’, name: ‘users-permissions’, key: ‘advanced’ })

.get();
//change this
//const user = _.find(users, { provider });
//with this
let user = .find(users, { provider });
if(
.isEmpty(user)){
user = _.find(users);
}

if (_.isEmpty(user) && !advancedSettings.allow_register) {

throw new Error(‘Register action is actually not available.’);

use patch-package to save the changes.

hope it works for you

1 Like