Created
June 17, 2020 14:40
-
-
Save ishan123456789/2fba00d48c0d7d900d03d97d35c90c4e to your computer and use it in GitHub Desktop.
Fix for strapi to allow multiple providers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// /extensions/users-permissions | |
"use strict"; | |
/** | |
* Module dependencies. | |
*/ | |
// Public node modules. | |
const _ = require("lodash"); | |
const request = require("request"); | |
// Purest strategies. | |
const purest = require("purest")({ request }); | |
const purestConfig = require("@purest/providers"); | |
/** | |
* Connect thanks to a third-party provider. | |
* | |
* | |
* @param {String} provider | |
* @param {String} access_token | |
* | |
* @return {*} | |
*/ | |
exports.connect = (provider, query) => { | |
const access_token = query.access_token || query.code || query.oauth_token; | |
console.log("heelllllllooooooooooooooorererewrwrwer"); | |
return new Promise((resolve, reject) => { | |
if (!access_token) { | |
return reject([null, { message: "No access_token." }]); | |
} | |
// Get the profile. | |
getProfile(provider, query, async (err, profile) => { | |
if (err) { | |
return reject([null, err]); | |
} | |
// We need at least the mail. | |
if (!profile.email) { | |
return reject([null, { message: "Email was not available." }]); | |
} | |
try { | |
const users = await strapi.query("user", "users-permissions").find({ | |
email: profile.email, | |
}); | |
const advanced = await strapi | |
.store({ | |
environment: "", | |
type: "plugin", | |
name: "users-permissions", | |
key: "advanced", | |
}) | |
.get(); | |
if ( | |
// _.isEmpty(_.find(users, { provider })) && | |
!advanced.allow_register | |
) { | |
return resolve([ | |
null, | |
[{ messages: [{ id: "Auth.advanced.allow_register" }] }], | |
"Register action is actualy not available.", | |
]); | |
} | |
const user = users[0]; | |
if (!_.isEmpty(user)) { | |
return resolve([user, null]); | |
} | |
// if ( | |
// !_.isEmpty(_.find(users, user => user.provider !== provider)) && | |
// advanced.unique_email | |
// ) { | |
// return resolve([ | |
// null, | |
// [{ messages: [{ id: 'Auth.form.error.email.taken' }] }], | |
// 'Email is already taken.', | |
// ]); | |
// } | |
// Retrieve default role. | |
const defaultRole = await strapi | |
.query("role", "users-permissions") | |
.findOne({ type: advanced.default_role }, []); | |
// Create the new user. | |
const params = _.assign(profile, { | |
provider: provider, | |
role: defaultRole.id, | |
confirmed: true, | |
}); | |
const createdUser = await strapi | |
.query("user", "users-permissions") | |
.create(params); | |
return resolve([createdUser, null]); | |
} catch (err) { | |
reject([null, err]); | |
} | |
}); | |
}); | |
}; | |
/** | |
* Helper to get profiles | |
* | |
* @param {String} provider | |
* @param {Function} callback | |
*/ | |
const getProfile = async (provider, query, callback) => { | |
const access_token = query.access_token || query.code || query.oauth_token; | |
const grant = await strapi | |
.store({ | |
environment: "", | |
type: "plugin", | |
name: "users-permissions", | |
key: "grant", | |
}) | |
.get(); | |
switch (provider) { | |
case "discord": { | |
const discord = purest({ | |
provider: "discord", | |
config: { | |
discord: { | |
"https://discordapp.com/api/": { | |
__domain: { | |
auth: { | |
auth: { bearer: "[0]" }, | |
}, | |
}, | |
"{endpoint}": { | |
__path: { | |
alias: "__default", | |
}, | |
}, | |
}, | |
}, | |
}, | |
}); | |
discord | |
.query() | |
.get("users/@me") | |
.auth(access_token) | |
.request((err, res, body) => { | |
if (err) { | |
callback(err); | |
} else { | |
// Combine username and discriminator because discord username is not unique | |
var username = `${body.username}#${body.discriminator}`; | |
callback(null, { | |
username: username, | |
email: body.email, | |
}); | |
} | |
}); | |
break; | |
} | |
case "facebook": { | |
const facebook = purest({ | |
provider: "facebook", | |
config: purestConfig, | |
}); | |
.query() | |
.get("me?fields=name,email") | |
.auth(access_token) | |
.request((err, res, body) => { | |
if (err) { | |
callback(err); | |
} else { | |
callback(null, { | |
username: body.name, | |
email: body.email, | |
}); | |
} | |
}); | |
break; | |
} | |
case "google": { | |
const google = purest({ provider: "google", config: purestConfig }); | |
.query("oauth") | |
.get("tokeninfo") | |
.qs({ access_token }) | |
.request((err, res, body) => { | |
if (err) { | |
callback(err); | |
} else { | |
callback(null, { | |
username: body.email.split("@")[0], | |
email: body.email, | |
}); | |
} | |
}); | |
break; | |
} | |
case "github": { | |
const github = purest({ | |
provider: "github", | |
config: purestConfig, | |
defaults: { | |
headers: { | |
"user-agent": "strapi", | |
}, | |
}, | |
}); | |
request.post( | |
{ | |
url: "https://github.com/login/oauth/access_token", | |
form: { | |
client_id: grant.github.key, | |
client_secret: grant.github.secret, | |
code: access_token, | |
}, | |
}, | |
(err, res, body) => { | |
github | |
.query() | |
.get("user") | |
.auth(body.split("&")[0].split("=")[1]) | |
.request((err, res, userbody) => { | |
if (err) { | |
return callback(err); | |
} | |
// This is the public email on the github profile | |
if (userbody.email) { | |
return callback(null, { | |
username: userbody.login, | |
email: userbody.email, | |
}); | |
} | |
// Get the email with Github's user/emails API | |
github | |
.query() | |
.get("user/emails") | |
.auth(body.split("&")[0].split("=")[1]) | |
.request((err, res, emailsbody) => { | |
if (err) { | |
return callback(err); | |
} | |
return callback(null, { | |
username: userbody.login, | |
email: Array.isArray(emailsbody) | |
? emailsbody.find((email) => email.primary === true).email | |
: null, | |
}); | |
}); | |
}); | |
} | |
); | |
break; | |
} | |
case "microsoft": { | |
const microsoft = purest({ | |
provider: "microsoft", | |
config: purestConfig, | |
}); | |
microsoft | |
.query() | |
.get("me") | |
.auth(access_token) | |
.request((err, res, body) => { | |
if (err) { | |
callback(err); | |
} else { | |
callback(null, { | |
username: body.userPrincipalName, | |
email: body.userPrincipalName, | |
}); | |
} | |
}); | |
break; | |
} | |
case "twitter": { | |
const twitter = purest({ | |
provider: "twitter", | |
config: purestConfig, | |
key: grant.twitter.key, | |
secret: grant.twitter.secret, | |
}); | |
.query() | |
.get("account/verify_credentials") | |
.auth(access_token, query.access_secret) | |
.qs({ screen_name: query["raw[screen_name]"], include_email: "true" }) | |
.request((err, res, body) => { | |
if (err) { | |
callback(err); | |
} else { | |
callback(null, { | |
username: body.screen_name, | |
email: body.email, | |
}); | |
} | |
}); | |
break; | |
} | |
case "instagram": { | |
const instagram = purest({ | |
config: purestConfig, | |
provider: "instagram", | |
key: grant.instagram.key, | |
secret: grant.instagram.secret, | |
}); | |
.query() | |
.get("users/self") | |
.qs({ access_token }) | |
.request((err, res, body) => { | |
if (err) { | |
callback(err); | |
} else { | |
callback(null, { | |
username: body.data.username, | |
email: `${body.data.username}@strapi.io`, // dummy email as Instagram does not provide user email | |
}); | |
} | |
}); | |
break; | |
} | |
case "vk": { | |
const vk = purest({ | |
provider: "vk", | |
config: purestConfig, | |
}); | |
vk.query() | |
.get("users.get") | |
.auth(access_token) | |
.qs({ id: query.raw.user_id, v: "5.013" }) | |
.request((err, res, body) => { | |
if (err) { | |
callback(err); | |
} else { | |
callback(null, { | |
username: `${body.response[0].last_name} ${body.response[0].first_name}`, | |
email: query.raw.email, | |
}); | |
} | |
}); | |
break; | |
} | |
default: | |
callback({ | |
message: "Unknown provider.", | |
}); | |
break; | |
} | |
}; |
Hi @var-bin
you'll have to copy from /node_modules/strapi-plugin-users-permissions/services/Providers.js
to /extensions/users-permissions/services/Providers.js
and update the lines with commented code https://gist.github.com/ishan123456789/2fba00d48c0d7d900d03d97d35c90c4e#file-providers-js-L76
Thanks a bunch for such a quick response. I am going to try it right away. Cheers
I have doubt will this implementation make one account only and attach the providers into the user document? or different users for each provider?
Right this would make one account per email
Thank you for the solution! Should it work for strapi -v4?
any updates on this issue?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi @ishan123456789,
Thank you for your Gist. Currently, I am dealing with the same issue that you were faced in Allow users to use multiple auth providers #2468. Could you tell me please, is there any additional step in order to have multiple multiple auth providers?
Thanks,
Vitalii