201 lines
6.4 KiB
JavaScript
201 lines
6.4 KiB
JavaScript
const querystring = require('querystring');
|
|
const axios = require('axios').default;
|
|
|
|
const db = require('../models');
|
|
|
|
module.exports = {
|
|
google: {
|
|
/**
|
|
* Generates authentication URL
|
|
* @name oAuth.google.generateAuthURL
|
|
* @param {{redirect_uri: String, client_id: String}} config
|
|
* @returns {String} authentication URL
|
|
*/
|
|
generateAuthURL(config) {
|
|
const rootUrl = 'https://accounts.google.com/o/oauth2/v2/auth';
|
|
|
|
const options = {
|
|
redirect_uri: config.redirect_uri,
|
|
client_id: config.client_id,
|
|
access_type: 'offline',
|
|
response_type: 'code',
|
|
prompt: 'consent',
|
|
scope: ['https://www.googleapis.com/auth/userinfo.profile', 'https://www.googleapis.com/auth/userinfo.email'].join(' '),
|
|
};
|
|
|
|
return `${rootUrl}?${querystring.stringify(options)}`;
|
|
},
|
|
/**
|
|
* Generates authentication Token
|
|
* @name oAuth.google.generateAuthToken
|
|
* @param {{auth_code: String, client_id: String, client_secret: String, redirect_uri: String}} config
|
|
* @returns {Promise.<{{access_token: String, expires_in: String, refresh_token: String, scope: String, token_type: String id_token: String}}>} authentication token
|
|
*/
|
|
generateAuthToken(config) {
|
|
return new Promise(function (resolve, reject) {
|
|
const url = 'https://oauth2.googleapis.com/token';
|
|
|
|
const buildQuerystring = querystring.stringify({
|
|
code: config.auth_code,
|
|
client_id: config.client_id,
|
|
client_secret: config.client_secret,
|
|
redirect_uri: config.redirect_uri,
|
|
grant_type: 'authorization_code',
|
|
});
|
|
|
|
axios.default
|
|
.post(url, buildQuerystring, {
|
|
headers: {
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
},
|
|
})
|
|
.then((response) => resolve(response.data))
|
|
.catch((error) => reject(error));
|
|
});
|
|
},
|
|
/**
|
|
* Retrieve user information
|
|
* @name oAuth.google.getUserInfo
|
|
* @param {{access_token: String, expires_in: String, refresh_token: String, scope: String, id_token: String}} config
|
|
* @returns {Promise.<{id: string, email: string, verified_email: true, name: string, given_name: string, family_name: string, picture: string, locale: string}>} user information
|
|
*/
|
|
getUserInfo(config, isAPI = false) {
|
|
return new Promise(function (resolve, reject) {
|
|
axios
|
|
.get(
|
|
`https://www.googleapis.com/oauth2/v1/userinfo?alt=json&access_token=${config.access_token}`,
|
|
isAPI
|
|
? {}
|
|
: {
|
|
headers: {
|
|
Authorization: `Bearer ${config.id_token}`,
|
|
},
|
|
},
|
|
)
|
|
.then((response) => resolve(response.data))
|
|
.catch((error) => reject(error));
|
|
});
|
|
},
|
|
},
|
|
facebook: {
|
|
/**
|
|
* Generates authentication URL
|
|
* @name oAuth.facebook.generateAuthURL
|
|
* @param {{redirect_uri: String, client_id: String}} config
|
|
* @returns {String} authentication URL
|
|
*/
|
|
generateAuthURL(config) {
|
|
const stringifiedParams = querystring.stringify({
|
|
client_id: config.client_id,
|
|
redirect_uri: process.env.DYNAMIC_CONFIG_FACEBOOK_REDIRECT_URI,
|
|
scope: ['email', 'user_friends'].join(','),
|
|
response_type: 'code',
|
|
auth_type: 'rerequest',
|
|
display: 'popup',
|
|
});
|
|
|
|
return `https://www.facebook.com/v4.0/dialog/oauth?${stringifiedParams}`;
|
|
},
|
|
/**
|
|
* Generates authentication Token
|
|
* @name oAuth.facebook.generateAuthToken
|
|
* @param {{auth_code: String, client_id: String, client_secret: String, redirect_uri: String}} config
|
|
* @returns {Promise.<{access_token: String, token_type: String, expires_in: String}>} authentication token
|
|
*/
|
|
async generateAuthToken(config) {
|
|
const url = 'https://graph.facebook.com/v4.0/oauth/access_token';
|
|
|
|
const { data } = await axios({
|
|
url,
|
|
method: 'GET',
|
|
params: {
|
|
code: config.auth_code,
|
|
client_id: config.client_id,
|
|
client_secret: config.client_secret,
|
|
redirect_uri: config.redirect_uri,
|
|
},
|
|
});
|
|
|
|
return data;
|
|
},
|
|
/**
|
|
* Retrieve user information
|
|
* @name oAuth.facebook.getUserInfo
|
|
* @param {{access_token: String, token_type: String, expires_in: String}} config
|
|
* @returns {Promise.<{id: string, email: string, first_name: string, last_name: string, image: string}>} user information
|
|
*/
|
|
async getUserInfo(config) {
|
|
const { data } = await axios({
|
|
url: 'https://graph.facebook.com/me',
|
|
method: 'GET',
|
|
params: {
|
|
fields: ['id', 'email', 'first_name', 'last_name'].join(','),
|
|
access_token: config.access_token,
|
|
},
|
|
});
|
|
|
|
return data;
|
|
},
|
|
},
|
|
async authenticate(user) {
|
|
let User;
|
|
let Credential;
|
|
try {
|
|
const isEmailExist = await db.credential.getByField('email', user.email);
|
|
if (isEmailExist) {
|
|
// Check status and role
|
|
if (+isEmailExist.status === 0 || +user.role === +isEmailExist.role) {
|
|
throw new Error('EMAIL_ADDRESS_NOT_FOUND');
|
|
}
|
|
// Check provider type type
|
|
const type = isEmailExist.type === user.provider;
|
|
if (!type) {
|
|
throw new Error('ACCOUNT_IS_REGISTERED_WITH_' + (user.provider === 'n' ? 'EMAIL_AND_PASSWORD' : user.provider === 'g' ? 'GOOGLE' : 'FACEBOOK'));
|
|
}
|
|
const userExists = await db.user.getByPK(isEmailExist.user_id);
|
|
|
|
if (!userExists) {
|
|
throw new Error('EMAIL_ADDRESS_NOT_FOUND');
|
|
}
|
|
|
|
return {
|
|
credential: isEmailExist.id,
|
|
user: userExists,
|
|
};
|
|
}
|
|
|
|
User = await db.user.insert(
|
|
{
|
|
first_name: user.first_name,
|
|
last_name: user.last_name,
|
|
image: user.image,
|
|
},
|
|
{ returnAllFields: true },
|
|
);
|
|
|
|
Credential = await db.credential.insert(
|
|
{
|
|
user_id: User.id,
|
|
email: user.email,
|
|
type: user.provider,
|
|
role_id: user.role_id,
|
|
status: 1,
|
|
},
|
|
{ returnAllFields: true },
|
|
);
|
|
|
|
return { credential: Credential.id, user: User };
|
|
} catch (error) {
|
|
if (User) {
|
|
User.destroy();
|
|
}
|
|
|
|
if (Credential) {
|
|
Credential.destroy();
|
|
}
|
|
|
|
throw new Error(error.message);
|
|
}
|
|
},
|
|
};
|