mirror of
https://bitbucket.org/tagfer_team/tagfer-server.git
synced 2025-12-25 03:37:38 +00:00
Twitter Auth + Fix Previous Errors
This commit is contained in:
parent
506166b146
commit
4248e2e870
29
.eslintrc
Normal file
29
.eslintrc
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"env": {
|
||||
"es6": true,
|
||||
"node": true
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2017,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"rules": {
|
||||
"indent": [
|
||||
"error",
|
||||
2
|
||||
],
|
||||
"linebreak-style": [
|
||||
"error",
|
||||
"unix"
|
||||
],
|
||||
"quotes": [
|
||||
"error",
|
||||
"single"
|
||||
],
|
||||
"semi": [
|
||||
"error",
|
||||
"always"
|
||||
]
|
||||
}
|
||||
}
|
||||
11
package-lock.json
generated
11
package-lock.json
generated
@ -3305,6 +3305,11 @@
|
||||
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
|
||||
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
|
||||
},
|
||||
"oauth-1.0a": {
|
||||
"version": "2.2.5",
|
||||
"resolved": "https://registry.npmjs.org/oauth-1.0a/-/oauth-1.0a-2.2.5.tgz",
|
||||
"integrity": "sha512-7Y4Gs+2dPOjrlJDzEPdpuH46gzgYeVF7CKOOQNpWKz1nlbWn2rqKSt3oF0By6KxudbOQATEUY74SphuTN0grPg=="
|
||||
},
|
||||
"oauth-sign": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
|
||||
@ -3820,9 +3825,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"sshpk": {
|
||||
"version": "1.15.2",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz",
|
||||
"integrity": "sha512-Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA==",
|
||||
"version": "1.16.0",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.0.tgz",
|
||||
"integrity": "sha512-Zhev35/y7hRMcID/upReIvRse+I9SVhyVre/KTJSJQWMz3C3+G+HpO7m1wK/yckEtujKZ7dS4hkVxAnmHaIGVQ==",
|
||||
"requires": {
|
||||
"asn1": "0.2.4",
|
||||
"assert-plus": "1.0.0",
|
||||
|
||||
@ -26,7 +26,9 @@
|
||||
"firebase-admin": "^6.4.0",
|
||||
"lodash": "^4.17.11",
|
||||
"lokijs": "^1.5.5",
|
||||
"oauth-1.0a": "^2.2.5",
|
||||
"phone": "^2.3.0",
|
||||
"request": "^2.88.0",
|
||||
"twilio": "^3.25.0",
|
||||
"uuid": "^3.3.2"
|
||||
},
|
||||
|
||||
@ -28,6 +28,26 @@
|
||||
"accountSid": "ACf62469621684ed007c01dfc9aa0923fa",
|
||||
"authToken": "62bbc8dc0bd42503dcc46eb17fb26895",
|
||||
"phoneNumber": "+17027108370 "
|
||||
},
|
||||
"twitter": {
|
||||
"consumer": {
|
||||
"key": "u7pN7MZzYwXwnlofOdKyYJNfN",
|
||||
"secret": "c4WvRNMYYNj6KZKWaqKDcvnM2Pz3tLbr9Za1EkKOmV948VEIYE"
|
||||
},
|
||||
"token": {
|
||||
"key": "58031606-MFz9HErfQBZPcFHIQBjCcJUUtQfYS4Gf2LfZjjtyr",
|
||||
"secret": "mJVbfIADRHVjmS91BSSgweh1HcK3sk0FLutqFM6mWMWd3"
|
||||
},
|
||||
"endpoints": {
|
||||
"request_token": {
|
||||
"url": "https://api.twitter.com/oauth/request_token",
|
||||
"method": "POST"
|
||||
},
|
||||
"access_token": {
|
||||
"url": "https://api.twitter.com/oauth/access_token",
|
||||
"method": "POST"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"dbPath": {
|
||||
|
||||
@ -12,6 +12,7 @@ module.exports = {
|
||||
AUTH_INVALID_SESSION_ID: 'auth/invalid-session-id',
|
||||
AUTH_UNAUTHORIZED_ACCESS: 'auth/unauthorized-access-into-api',
|
||||
AUTH_UNABLE_TO_EXTRACT_SESSION_ID_FROM_AUTH_HEADER: 'auth/unable-to-extract-session-id-from-auth-header',
|
||||
AUTH_TWITTER_REQUEST_TOKEN_FAILURE: 'auth/twitter-request-token-failure',
|
||||
//App Errors
|
||||
APP_NETWORK_ERROR: 'app/network-error',
|
||||
APP_NETWORK_TIMEOUT: 'app/network-timeout',
|
||||
|
||||
@ -8,16 +8,18 @@ const ProfileHandlers = require('../ups/profiles/handlers');
|
||||
*/
|
||||
function router(app) {
|
||||
// Auth Endpoints
|
||||
app.get('/auth/twitter/token', AuthHandlers.getTwitterToken );
|
||||
app.get('/auth/twitter/username', AuthHandlers.getTwitterUsername );
|
||||
app.get('/auth/email/:email/exists', AuthHandlers.doesAttributeExist );
|
||||
app.get('/auth/tagferId/:tagferId/exists', AuthHandlers.doesAttributeExist );
|
||||
app.post('/auth/phone/code', AuthHandlers.sendPhoneCode);
|
||||
app.post('/auth/phone/verify', AuthHandlers.verifyPhoneCode);
|
||||
app.post('/auth/signin', AuthHandlers.signin);
|
||||
app.put('/auth/signup', AuthHandlers.signup);
|
||||
app.post('/auth/passwordReset', AuthHandlers.sendPasswordResetEmail)
|
||||
app.post('/auth/passwordReset', AuthHandlers.sendPasswordResetEmail);
|
||||
|
||||
// Users Endpoints
|
||||
app.get('/users/by/phone', UserHandlers.findNetworkByPhone);
|
||||
app.post('/users/by/phone', UserHandlers.findNetworkByPhone);
|
||||
|
||||
// Profile Endpoints
|
||||
app.post('/profiles/:profileNumber', ProfileHandlers.updateUserProfile);
|
||||
|
||||
@ -113,8 +113,8 @@ function createNewSessionId(tagferId) {
|
||||
* @throws AUTH_INVALID_SESSION_ID
|
||||
*/
|
||||
function getSession(id) {
|
||||
const sessions = loki.getCollection("sessions");
|
||||
var session = sessions.by('id', id)
|
||||
const sessions = loki.getCollection('sessions');
|
||||
var session = sessions.by('id', id);
|
||||
if (session) {
|
||||
return session;
|
||||
} else {
|
||||
|
||||
@ -4,6 +4,7 @@ const utils = require('../utils/utils');
|
||||
const errors = require('../../config/errors');
|
||||
const appConfig = require('../../config/app.json');
|
||||
const http = require('../../config/http');
|
||||
const twitter = require('../socials/twitter');
|
||||
|
||||
// Handlers
|
||||
/**
|
||||
@ -105,7 +106,7 @@ async function signup(req, res) {
|
||||
}
|
||||
|
||||
profile.name = appConfig.defaultProfileName;
|
||||
profile.email = user.email
|
||||
profile.email = user.email;
|
||||
|
||||
try {
|
||||
await authDao.createNewUser(user);
|
||||
@ -130,7 +131,32 @@ function sendPasswordResetEmail(req, res) {
|
||||
return;
|
||||
}
|
||||
|
||||
dao.resetPassword(email).then(() => res.json({}) ).catch( error => res.json(error))
|
||||
authDao.resetPassword(email).then(() => res.json({}) ).catch( error => res.json(error));
|
||||
}
|
||||
|
||||
/**
|
||||
* Endpoint: auth/twitter/token
|
||||
* Calls the twitter endpoint using OAuth, to get the `oauth_token`
|
||||
* @param {Object} req {}
|
||||
* @param {Object} res { token: String } | { error: String }
|
||||
*/
|
||||
function getTwitterToken(req, res) {
|
||||
if (!utils.isAppSecretValid(req,res)) {
|
||||
return;
|
||||
}
|
||||
|
||||
twitter.getOAuthToken((result) => res.json(result));
|
||||
}
|
||||
|
||||
/**
|
||||
* Endpoint: auth/twitter/username
|
||||
* Calls the twitter endpoint to get the `screen_name`
|
||||
* @param {Object} req {}
|
||||
* @param {Object} res HTML @see socials/twitter#passingHTML
|
||||
*/
|
||||
function getTwitterUsername(req, res) {
|
||||
res.set('Content-Type', 'text/html');
|
||||
twitter.getUsername(req.query, (result) => res.send(result));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
@ -139,5 +165,7 @@ module.exports = {
|
||||
verifyPhoneCode,
|
||||
signin,
|
||||
signup,
|
||||
sendPasswordResetEmail
|
||||
sendPasswordResetEmail,
|
||||
getTwitterToken,
|
||||
getTwitterUsername
|
||||
};
|
||||
84
src/ups/socials/twitter.js
Normal file
84
src/ups/socials/twitter.js
Normal file
@ -0,0 +1,84 @@
|
||||
const request = require('request');
|
||||
const querystring = require('querystring');
|
||||
|
||||
const appConfig = require('../../config/app.json');
|
||||
const utils = require('../utils/utils');
|
||||
const errors = require('../../config/errors');
|
||||
const http = require('../../config/http');
|
||||
|
||||
/**
|
||||
* Calls api.twiter.com/oauth/request_token
|
||||
*
|
||||
* @param {Function} Takes an object that either contains {`token`} or {`error`}
|
||||
*/
|
||||
function getOAuthToken(callback) {
|
||||
const twitter = appConfig.keys.twitter;
|
||||
const twitterRequest = twitter.endpoints.request_token;
|
||||
twitterRequest.headers = utils.createOAuthHeader(twitterRequest, twitter);
|
||||
|
||||
request(twitterRequest, (twitterError, twitterResponse, twitterBody) => {
|
||||
if (!twitterError && twitterResponse.statusCode === http.OK) {
|
||||
const tokens = querystring.parse(twitterBody);
|
||||
callback({ token: tokens.oauth_token });
|
||||
} else {
|
||||
callback({ error: errors.AUTH_TWITTER_REQUEST_TOKEN_FAILURE });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback excecuted by the Twitter API.
|
||||
* @param {Object} query { oauth_token: String, oauth_verifier: String } | { denied: String }
|
||||
* @param {Function} callback non-void callback that accepts a parameter of the HTML string.
|
||||
*/
|
||||
function getUsername(query, callback) {
|
||||
const twitter = appConfig.keys.twitter;
|
||||
const { oauth_token, oauth_verifier, denied } = query;
|
||||
|
||||
if (denied) {
|
||||
callback(passingHTML(JSON.stringify({})));
|
||||
return;
|
||||
}
|
||||
|
||||
request({
|
||||
url: `${twitter.endpoints.access_token.url}?oauth_token=${oauth_token}&oauth_verifier=${oauth_verifier}`,
|
||||
method: twitter.endpoints.access_token.method
|
||||
}, (twitterError, twitterResponse, twitterBody) => {
|
||||
let result = {};
|
||||
|
||||
if(!twitterError && twitterResponse.statusCode === http.OK ){
|
||||
const { screen_name } = querystring.parse(twitterBody);
|
||||
result = { username: screen_name };
|
||||
}
|
||||
|
||||
callback(passingHTML(JSON.stringify(result)));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Raw HTML passes the result using Window.postMessage from the WebView(DOM) back to ReactNative
|
||||
*/
|
||||
const passingHTML = (result) => `
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<body>
|
||||
<script>
|
||||
function waitForBridge() {
|
||||
if(window.postMessage.length !== 1){
|
||||
setTimeout(waitForBridge, 200);
|
||||
}
|
||||
else {
|
||||
window.postMessage('${result}');
|
||||
}
|
||||
}
|
||||
|
||||
window.onload = waitForBridge;
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
||||
module.exports = {
|
||||
getOAuthToken,
|
||||
getUsername
|
||||
};
|
||||
@ -38,7 +38,7 @@ function _getContactStatus(phoneNumber) {
|
||||
return admin.auth().getUserByPhoneNumber(phoneNumber).then( user => {
|
||||
return {inNetwork: true, tagferId: user.uid};
|
||||
}).catch( error => {
|
||||
return error === errors.AUTH_USER_NOT_FOUND ? { outNetwork: true, phoneNumber } : { error: error.code, phoneNumber};
|
||||
return error.code === errors.AUTH_USER_NOT_FOUND ? { outNetwork: true, phoneNumber } : { error: error.code, phoneNumber};
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
const OAuth = require('oauth-1.0a');
|
||||
const crypto = require('crypto');
|
||||
|
||||
const appConfig = require('../../config/app.json');
|
||||
const http = require('../../config/http');
|
||||
const errors = require('../../config/errors');
|
||||
const auth = require('../auth/dao');
|
||||
|
||||
/**
|
||||
* Verifies if the request is valid by checking if the request has the right app secret.
|
||||
@ -21,7 +23,7 @@ function isAppSecretValid(req, res) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function getSessionIdFromAuthHeader(req, res) {
|
||||
function getSessionIdFromAuthHeader(req) {
|
||||
const usrToken = req.headers.authorization;
|
||||
|
||||
if (usrToken) {
|
||||
@ -52,9 +54,27 @@ function isProfileNumberValid(profileNumber, response) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: move this so other files in the socials dir can use it
|
||||
* Creates the OAuth header to be passed into a request.
|
||||
* @param {Object} request { method: String, url: String, data: Object }
|
||||
* @param {Object} app { consumer: Object, token: Object }, each object is of the following { key: String, secret: String }
|
||||
* @returns { Authorization: String }
|
||||
*/
|
||||
function createOAuthHeader(request, app) {
|
||||
const oauth = OAuth({
|
||||
consumer: app.consumer,
|
||||
signature_method: 'HMAC-SHA1',
|
||||
hash_function: (base_string, key) => (crypto.createHmac('sha1', key).update(base_string).digest('base64'))
|
||||
});
|
||||
|
||||
return oauth.toHeader(oauth.authorize(request, app.token));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
isAppSecretValid,
|
||||
isBodyValid,
|
||||
getSessionIdFromAuthHeader,
|
||||
isProfileNumberValid
|
||||
isProfileNumberValid,
|
||||
createOAuthHeader
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user