mirror of
				https://github.com/strapi/strapi.git
				synced 2025-10-30 17:37:26 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			361 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			361 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 'use strict';
 | |
| 
 | |
| /**
 | |
|  * Module dependencies.
 | |
|  */
 | |
| 
 | |
| // Public node modules.
 | |
| const _ = require('lodash');
 | |
| const request = require('request');
 | |
| 
 | |
| // Purest strategies.<
 | |
| const Purest = require('purest');
 | |
| 
 | |
| /**
 | |
|  * 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;
 | |
| 
 | |
|   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(err);
 | |
|       }
 | |
| 
 | |
|       // We need at least the mail.
 | |
|       if (!profile.email) {
 | |
|         return reject([
 | |
|           {
 | |
|             message: 'Email was not available.',
 | |
|           },
 | |
|           null,
 | |
|         ]);
 | |
|       }
 | |
| 
 | |
|       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 = _.find(users, { provider });
 | |
| 
 | |
|         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,
 | |
|         });
 | |
| 
 | |
|         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 = new 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 = new Purest({
 | |
|         provider: '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': {
 | |
|       const config = {
 | |
|         google: {
 | |
|           'https://www.googleapis.com': {
 | |
|             __domain: {
 | |
|               auth: {
 | |
|                 auth: { bearer: '[0]' },
 | |
|               },
 | |
|             },
 | |
|             '{endpoint}': {
 | |
|               __path: {
 | |
|                 alias: '__default',
 | |
|               },
 | |
|             },
 | |
|             'oauth/[version]/{endpoint}': {
 | |
|               __path: {
 | |
|                 alias: 'oauth',
 | |
|                 version: 'v3',
 | |
|               },
 | |
|             },
 | |
|           },
 | |
|         },
 | |
|       };
 | |
|       const google = new Purest({ provider: 'google', config });
 | |
| 
 | |
|       google
 | |
|         .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 = new Purest({
 | |
|         provider: 'github',
 | |
|         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, body) => {
 | |
|               if (err) {
 | |
|                 callback(err);
 | |
|               } else {
 | |
|                 callback(null, {
 | |
|                   username: body.login,
 | |
|                   email: body.email,
 | |
|                 });
 | |
|               }
 | |
|             });
 | |
|         }
 | |
|       );
 | |
|       break;
 | |
|     }
 | |
|     case 'microsoft': {
 | |
|       const microsoft = new Purest({
 | |
|         provider: 'microsoft',
 | |
|         config: {
 | |
|           microsoft: {
 | |
|             'https://graph.microsoft.com': {
 | |
|               __domain: {
 | |
|                 auth: {
 | |
|                   auth: { bearer: '[0]' },
 | |
|                 },
 | |
|               },
 | |
|               '[version]/{endpoint}': {
 | |
|                 __path: {
 | |
|                   alias: '__default',
 | |
|                   version: 'v1.0',
 | |
|                 },
 | |
|               },
 | |
|             },
 | |
|           },
 | |
|         },
 | |
|       });
 | |
| 
 | |
|       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 = new Purest({
 | |
|         provider: 'twitter',
 | |
|         key: grant.twitter.key,
 | |
|         secret: grant.twitter.secret,
 | |
|       });
 | |
| 
 | |
|       twitter
 | |
|         .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 = new Purest({
 | |
|         provider: 'instagram',
 | |
|         key: grant.instagram.key,
 | |
|         secret: grant.instagram.secret
 | |
|       });
 | |
|     
 | |
|       instagram.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;
 | |
|     }
 | |
|     default:
 | |
|       callback({
 | |
|         message: 'Unknown provider.',
 | |
|       });
 | |
|       break;
 | |
|   }
 | |
| };
 | 
