Skip to content

Commit

Permalink
Merge pull request #564 from OpenUserJs/issue-484
Browse files Browse the repository at this point in the history
Silently migrate from OpenID to OAuth2 authentication for Google.

Merge... concensus... hopefully the API key doesn't expire but nodejitsu pro is currently stopped as I expected... so getting this rolling so it can be up again. Dev may exhibit a similar behavior at some point since the id is the same as pro but different key.
  • Loading branch information
Martii committed Feb 5, 2015
2 parents 7c9f9d9 + b49b2cb commit f0e47cb
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 9 deletions.
19 changes: 17 additions & 2 deletions controllers/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ var User = require('../models/user').User;
var verifyPassport = require('../libs/passportVerify').verify;
var cleanFilename = require('../libs/helpers').cleanFilename;
var addSession = require('../libs/modifySessions').add;
var jwt = require('jwt-simple');

// Unused but removing it breaks passport
passport.serializeUser(function (aUser, aDone) {
Expand Down Expand Up @@ -43,16 +44,22 @@ exports.auth = function (aReq, aRes, aNext) {
var authedUser = aReq.session.user;
var strategy = aReq.body.auth || aReq.params.strategy;
var username = aReq.body.username || aReq.session.username;
var authOpts = { failureRedirect: '/register?stratfail' };

function auth() {
var authenticate = passport.authenticate(strategy, { failureRedirect: '/register?stratfail' });
var authenticate = null;

if (strategy === 'google') {
authOpts.scope = ['https://www.googleapis.com/auth/userinfo.profile'];
}
authenticate = passport.authenticate(strategy, authOpts);

// Just in case some dumbass tries a bad /auth/* url
if (!strategyInstances[strategy]) {
return aNext();
}

authenticate(aReq, aRes);
authenticate(aReq, aRes, aNext);
}

// Allow a logged in user to add a new strategy
Expand Down Expand Up @@ -128,6 +135,14 @@ exports.callback = function (aReq, aRes, aNext) {
strategyInstance._verify = function (aId, aDone) {
verifyPassport(aId, strategy, username, aReq.session.user, aDone);
};
} else if (strategy === 'google') { // OpenID to OAuth2 migration
strategyInstance._verify =
function(aAccessToken, aRefreshToken, aParams, aProfile, aDone) {
var openIdId = jwt.decode(aParams.id_token, null, true).openid_id;
var oAuthId = aProfile.id;

verifyPassport([openIdId, oAuthId], strategy, username, aReq.session.user, aDone);
};
} else {
strategyInstance._verify =
function (aToken, aRefreshOrSecretToken, aProfile, aDone) {
Expand Down
2 changes: 1 addition & 1 deletion controllers/strategies.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
},
"google": {
"name": "Google",
"oauth": false
"oauth": true
},
"imgur": {
"name": "Imgur",
Expand Down
16 changes: 14 additions & 2 deletions libs/passportLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@ exports.strategyInstances = nil();
// This will load a single passport
// Notice it is general so it can load any passport strategy
exports.loadPassport = function (aStrategy) {
var requireStr = 'passport-' + aStrategy.name;
var PassportStrategy = require(requireStr).Strategy;
var requireStr = 'passport-' + aStrategy.name
+ (aStrategy.name === 'google' ? '-oauth' : '');
var PassportStrategy = require(requireStr)[
aStrategy.name === 'google' ? 'OAuth2Strategy' : 'Strategy'];
var instance = null;
var authParams = null;

if (aStrategy.openid) {
instance = new PassportStrategy(
Expand All @@ -50,6 +53,15 @@ exports.loadPassport = function (aStrategy) {
);
}

if (aStrategy.name === 'google') {
authParams = instance.authorizationParams;
instance.authorizationParams = function() {
var val = authParams.apply(this, arguments);
val['openid.realm'] = AUTH_CALLBACK_BASE_URL + '/';
return val;
};
}

exports.strategyInstances[aStrategy.name] = instance;
passport.use(instance);
};
35 changes: 32 additions & 3 deletions libs/passportVerify.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,18 @@ var userRoles = require('../models/userRoles.json');
exports.verify = function (aId, aStrategy, aUsername, aLoggedIn, aDone) {
var shasum = crypto.createHash('sha256');
var digest = null;
var query = {};
var ids = [];

// We only keep plaintext ids for GH since that's all we need
if (aStrategy === 'github') {
if (aId instanceof Array) {
ids = aId.map(function (aId) {
var shasum = crypto.createHash('sha256');
shasum.update(String(aId));
return shasum.digest('hex');
});
query.auths = { '$in': ids };
} else if (aStrategy === 'github') {
// We only keep plaintext ids for GH since that's all we need
digest = aId;
} else {
// Having these ids would allow us to do things with the user's
Expand All @@ -27,11 +36,25 @@ exports.verify = function (aId, aStrategy, aUsername, aLoggedIn, aDone) {
digest = shasum.digest('hex');
}

findDeadorAlive(User, { 'auths': digest }, true,
if (!query.auths) {
query.auths = digest;
}

findDeadorAlive(User, query, true,
function (aAlive, aUser, aRemoved) {
var pos = aUser ? aUser.auths.indexOf(digest) : -1;
var opendIdPos = -1;
if (aRemoved) { aDone(null, false, 'user was removed'); }

// Set up for OpenId to OAuth Migration
if (!digest && ids.length > 0) {
digest = ids[1];
if (aUser) {
pos = aUser.auths.indexOf(digest);
opendIdPos = aUser.auths.indexOf(ids[0]);
}
}

if (!aUser) {
User.findOne({ 'name': aUsername }, function (aErr, aUser) {
if (aUser && aLoggedIn) {
Expand Down Expand Up @@ -69,6 +92,12 @@ exports.verify = function (aId, aStrategy, aUsername, aLoggedIn, aDone) {
aUser.save(function (aErr, aUser) {
return aDone(aErr, aUser);
});
} else if (opendIdPos > 0) {
// Migrate from OpenID to OAuth
aUser.auths[opendIdPos] = digest;
aUser.save(function (aErr, aUser) {
return aDone(aErr, aUser);
});
} else {
// The user was authenticated
return aDone(null, aUser);
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"github": "0.2.3",
"highlight.js": "8.4.0",
"jquery": "2.1.3",
"jwt-simple": "0.2.0",
"less-middleware": "1.0.4",
"marked": "0.3.3",
"method-override": "2.3.1",
Expand All @@ -36,7 +37,7 @@
"passport-flickr": "0.2.0",
"passport-foursquare": "1.0.0",
"passport-github": "0.1.5",
"passport-google": "0.3.0",
"passport-google-oauth": "0.1.5",
"passport-imgur": "0.0.2",
"passport-instagram": "0.1.2",
"passport-linkedin": "0.1.3",
Expand Down

0 comments on commit f0e47cb

Please sign in to comment.