Add provider connection

This commit is contained in:
Jim Laurie 2018-01-12 15:20:13 +01:00
parent b690951b65
commit 6e44e2e274
10 changed files with 284 additions and 5 deletions

View File

@ -1,6 +1,6 @@
{
"session": {
"enabled": false,
"enabled": true,
"client": "cookie",
"key": "strapi.sid",
"prefix": "strapi:sess:",

View File

@ -27,6 +27,45 @@ module.exports = cb => {
}
}
if (!_.get(strapi.plugins['users-permissions'], 'config.grant')) {
try {
const jwtSecret = uuid();
fs.writeFileSync(path.join(strapi.config.appPath, 'plugins', 'users-permissions', 'config', 'grant.json'), JSON.stringify({
grant: {
facebook: {
key: '',
secret: '',
callback: '/auth/facebook/callback',
scope: ['email']
},
google: {
key: '',
secret: '',
callback: '/auth/google/callback',
scope: ['email']
},
github: {
key: '',
secret: '',
callback: '/auth/github/callback'
},
linkedin2: {
key: '',
secret: '',
callback: '/auth/linkedin2/callback',
custom_params: {
'state': ''
}
}
}
}, null, 2), 'utf8');
_.set(strapi.plugins['users-permissions'], 'config.grant', grant);
} catch(err) {
strapi.log.error(err);
}
}
strapi.plugins['users-permissions'].services.userspermissions.syncSchema(() => {
strapi.plugins['users-permissions'].services.userspermissions.updatePermissions(cb);
});

View File

@ -0,0 +1,27 @@
{
"grant": {
"facebook": {
"key": "",
"secret": "",
"callback": "/auth/facebook/callback",
"scope": ["email"]
},
"google": {
"key": "",
"secret": "",
"callback": "/auth/google/callback",
"scope": ["email"]
},
"github": {
"key": "",
"secret": "",
"callback": "/auth/github/callback"
},
"linkedin2": {
"key": "",
"secret": "",
"callback": "/auth/linkedin2/callback",
"custom_params": {"state": ""}
}
}
}

View File

@ -116,6 +116,15 @@
"prefix": ""
}
},
{
"method": "GET",
"path": "/auth/:provider/callback",
"handler": "Auth.callback",
"config": {
"policies": [],
"prefix": ""
}
},
{
"method": "POST",
"path": "/auth/forgot-password",

View File

@ -62,9 +62,12 @@ module.exports = {
}
} else {
// Connect the user thanks to the third-party provider.
const user = await strapi.api.user.services.grant.connect(provider, access_token);
const user = await strapi.plugins['users-permissions'].services.providers.connect(provider, access_token);
ctx.redirect(strapi.config.frontendUrl || strapi.config.url + '?jwt=' + strapi.api.user.services.jwt.issue(user) + '&user=' + JSON.stringify(user));
ctx.send({
jwt: strapi.plugins['users-permissions'].services.jwt.issue(user),
user: _.omit(user.toJSON ? user.toJSON() : user, ['password', 'resetPasswordToken'])
});
}
},

View File

@ -0,0 +1,33 @@
'use strict';
/**
* Module dependencies
*/
// Public node modules.
const _ = require('lodash');
const Grant = require('grant-koa');
const mount = require('koa-mount');
module.exports = strapi => {
return {
beforeInitialize: function() {
strapi.config.middleware.load.after.push('provider');
},
initialize: function(cb) {
_.defaultsDeep(strapi.plugins['users-permissions'].config.grant, {
server: {
protocol: 'http',
host: 'localhost:1337'
}
});
const grant = new Grant(strapi.plugins['users-permissions'].config.grant);
strapi.app.use(mount(grant));
cb();
}
};
};

View File

@ -1,3 +1,10 @@
'use strict';
/**
* Module dependencies
*/
// Public node modules.
const _ = require('lodash');
module.exports = strapi => {

View File

@ -26,8 +26,7 @@
"password": {
"type": "password",
"minLength": 6,
"configurable": false,
"required": true
"configurable": false
},
"resetPasswordToken": {
"type": "string",

View File

@ -25,7 +25,11 @@
},
"dependencies": {
"bcryptjs": "^2.4.3",
"grant-koa": "^3.8.1",
"jsonwebtoken": "^8.1.0",
"koa": "^2.1.0",
"koa-mount": "^3.0.0",
"purest": "^2.0.1",
"request": "^2.83.0",
"uuid": "^3.1.0"
},

View File

@ -0,0 +1,158 @@
'use strict';
/**
* Module dependencies.
*/
// Public node modules.
const _ = require('lodash');
// Purest strategies.
const Purest = require('purest');
const facebook = new Purest({
provider: 'facebook'
});
const github = new Purest({
provider: 'github',
defaults: {
headers: {
'user-agent': 'strapi'
}
}
});
const google = new Purest({
provider: 'google'
});
const linkedin = new Purest({
provider: 'linkedin'
});
/**
* Connect thanks to a third-party provider.
*
*
* @param {String} provider
* @param {String} access_token
*
* @return {*}
*/
exports.connect = (provider, access_token) => {
return new Promise((resolve, reject) => {
if (!access_token) {
reject({
message: 'No access_token.'
});
} else {
// Get the profile.
getProfile(provider, access_token, (err, profile) => {
if (err) {
reject(err);
} else {
// We need at least the mail.
if (!profile.email) {
reject({
message: 'Email was not available.'
});
} else {
strapi.query('user', 'users-permissions').findOne({email: profile.email})
.then(user => {
if (!user) {
// Create the new user.
const params = _.assign(profile, {
provider: provider
});
strapi.query('user', 'users-permissions').create(params)
.then(user => {
resolve(user);
})
.catch(err => {
reject(err);
});
} else {
resolve(user);
}
})
.catch(err => {
reject(err);
});
}
}
});
}
});
};
/**
* Helper to get profiles
*
* @param {String} provider
* @param {Function} callback
*/
const getProfile = (provider, access_token, callback) => {
let fields;
switch (provider) {
case 'facebook':
facebook.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':
google.query('plus').get('people/me').auth(access_token).request((err, res, body) => {
if (err) {
callback(err);
} else {
callback(null, {
username: body.displayName,
email: body.emails[0].value
});
}
});
break;
case 'github':
github.query().get('user').auth(access_token).request((err, res, body) => {
if (err) {
callback(err);
} else {
callback(null, {
username: body.login,
email: body.email
});
}
});
break;
case 'linkedin2':
fields = [
'public-profile-url', 'email-address'
];
linkedin.query().select('people/~:(' + fields.join() + ')?format=json').auth(access_token).request((err, res, body) => {
if (err) {
callback(err);
} else {
callback(null, {
username: substr(body.publicProfileUrl.lastIndexOf('/') + 1),
email: body.emailAddress
});
}
});
break;
default:
callback({
message: 'Unknown provider.'
});
break;
}
}