Skip to content

Instantly share code, notes, and snippets.

@stefek99
Created October 2, 2015 10:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stefek99/bafee8492128c63aa572 to your computer and use it in GitHub Desktop.
Save stefek99/bafee8492128c63aa572 to your computer and use it in GitHub Desktop.
Authentication
exports.exchangeTokens = function(code) {
var defer = q.defer();
var requestURL = "https://www.googleapis.com/oauth2/v3/token";
var post_data = {
code : code,
client_id : google_client_id,
client_secret : google_client_secret,
redirect_uri : 'postmessage',
grant_type : "authorization_code",
};
// https://github.com/request/request#forms
request.post(requestURL, { form: post_data }, function(error, response, body) {
// console.log("ERROR: " + error + "\n\n");
// console.log("BODY: " + body + "\n\n");
defer.resolve(JSON.parse(body));
});
return defer.promise;
};
exports.refreshToken = function(refresh_token) {
var defer = q.defer();
var requestURL = "https://www.googleapis.com/oauth2/v3/token";
var post_data = {
refresh_token : refresh_token,
client_id : google_client_id,
client_secret : google_client_secret,
grant_type : "refresh_token"
};
request.post(requestURL, { form: post_data }, function(error, response, body) {
//console.log("ERROR: " + error + "\n\n");
//console.log("BODY: " + body + "\n\n");
defer.resolve(JSON.parse(body));
});
return defer.promise;
};
exports.checkToken = function(access_token) {
var defer = q.defer();
var requestURL = "https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=" + access_token;
request.get(requestURL, function(error, response, body) {
// console.log("ERROR: " + error + "\n\n"); // error is always null, it's the error property of the body response that is set
// console.log("BODY: " + body + "\n\n");
// TRYING TO DEBUG
try {
defer.resolve(JSON.parse(body)); // google returns it as string
} catch(exception) {
console.log("GOOGLE CHECK TOKEN PARSE FAIL");
console.log(body);
defer.reject(null);
}
});
return defer.promise;
};
exports.userInfo = function(access_token) {
var defer = q.defer();
var requestURL = "https://www.googleapis.com/oauth2/v1/userinfo?access_token=" + access_token;
request.get(requestURL, function(error, response, body) {
// console.log("ERROR: " + error + "\n\n"); // error is always null, it's the error property of the body response that is set
// console.log("BODY: " + body + "\n\n");
defer.resolve(JSON.parse(body));
});
return defer.promise;
};
var verifyToken = function (req, res, next) {
var getAccessTokens = function(email) {
var defer = q.defer();
ref.child("users/email:" + email.replace(".", "(dot)") + "/access_tokens").once("value", function(snap) {
var access_tokens = snap.val();
defer.resolve(access_tokens);
});
return defer.promise;
};
var email = req.query.email;
var access_token = req.query.access_token;
var skip = req.query.skip;
if (skip) { // sometimes - when debugging - I want to hit api method without worrying about access_token
next();
return;
}
if (req.url === "/syncFinished") { // allowing callback from ContextIO that obviously does not have authentication
next();
return;
}
if (! access_token || access_token === "undefined") { // sometimes `access_token` gets serialised as string
res.send({message : "No access_token. Returning."});
return;
}
if (! email || email === "undefined") { // sometimes `email` gets serialised as string
res.send({message : "No email. Returning."});
return;
}
google.checkToken(access_token).then(function(response) {
if (! response.error) {
if (response.email !== email) {
res.send({message : "This token does not belong to this email. Weird. Are you a hacker?"});
return;
}
next();
getAccessTokens(email).then(function(access_tokens) {
if (_.contains(access_tokens, access_token) === false) {
console.log("This access_token have not been seen. Adding to the list...");
ref.child("users/email:" + email.replace(".", "(dot)") + "/access_tokens").push(access_token);
}
});
} else {
// Current access_token is invalid. But maybe it's only 3600 TTL...
// Checking if this token was valid and if yes - refreshing and returning new value to the client
getAccessTokens(email).then(function(access_tokens){
if (_.contains(access_tokens, req.query.access_token)) {
console.log("This access_token was previously valid. Refreshing...");
ref.child("users/email:" + email.replace(".", "(dot)") + "/refresh_token").once("value", function(snap) {
var refresh_token = snap.val();
google.refreshToken(refresh_token).then(function(result) {
console.log("Refreshed. " + JSON.stringify(result) + " Carrying on...");
res.append('new_access_token', result.access_token); // adding to the headers so the client can update
req.query.access_token = result.access_token; // updatin req, so further down the line there are no errors
ref.child("users/email:" + req.query.email.replace(".", "(dot)") + "/access_tokens").push(result.access_token);
next();
});
});
} else {
res.send({message : "Wrong access_token. Tried matching with the previous one but still doesn't work."});
}
});
}
});
};
app.use(verifyToken);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment