Skip to content

Commit f0e47cb

Browse files
committed
Merge pull request #564 from OpenUserJs/issue-484
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.
2 parents 7c9f9d9 + b49b2cb commit f0e47cb

5 files changed

Lines changed: 66 additions & 9 deletions

File tree

controllers/auth.js

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ var User = require('../models/user').User;
1515
var verifyPassport = require('../libs/passportVerify').verify;
1616
var cleanFilename = require('../libs/helpers').cleanFilename;
1717
var addSession = require('../libs/modifySessions').add;
18+
var jwt = require('jwt-simple');
1819

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

4749
function auth() {
48-
var authenticate = passport.authenticate(strategy, { failureRedirect: '/register?stratfail' });
50+
var authenticate = null;
51+
52+
if (strategy === 'google') {
53+
authOpts.scope = ['https://www.googleapis.com/auth/userinfo.profile'];
54+
}
55+
authenticate = passport.authenticate(strategy, authOpts);
4956

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

55-
authenticate(aReq, aRes);
62+
authenticate(aReq, aRes, aNext);
5663
}
5764

5865
// Allow a logged in user to add a new strategy
@@ -128,6 +135,14 @@ exports.callback = function (aReq, aRes, aNext) {
128135
strategyInstance._verify = function (aId, aDone) {
129136
verifyPassport(aId, strategy, username, aReq.session.user, aDone);
130137
};
138+
} else if (strategy === 'google') { // OpenID to OAuth2 migration
139+
strategyInstance._verify =
140+
function(aAccessToken, aRefreshToken, aParams, aProfile, aDone) {
141+
var openIdId = jwt.decode(aParams.id_token, null, true).openid_id;
142+
var oAuthId = aProfile.id;
143+
144+
verifyPassport([openIdId, oAuthId], strategy, username, aReq.session.user, aDone);
145+
};
131146
} else {
132147
strategyInstance._verify =
133148
function (aToken, aRefreshOrSecretToken, aProfile, aDone) {

controllers/strategies.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
},
2626
"google": {
2727
"name": "Google",
28-
"oauth": false
28+
"oauth": true
2929
},
3030
"imgur": {
3131
"name": "Imgur",

libs/passportLoader.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,12 @@ exports.strategyInstances = nil();
2121
// This will load a single passport
2222
// Notice it is general so it can load any passport strategy
2323
exports.loadPassport = function (aStrategy) {
24-
var requireStr = 'passport-' + aStrategy.name;
25-
var PassportStrategy = require(requireStr).Strategy;
24+
var requireStr = 'passport-' + aStrategy.name
25+
+ (aStrategy.name === 'google' ? '-oauth' : '');
26+
var PassportStrategy = require(requireStr)[
27+
aStrategy.name === 'google' ? 'OAuth2Strategy' : 'Strategy'];
2628
var instance = null;
29+
var authParams = null;
2730

2831
if (aStrategy.openid) {
2932
instance = new PassportStrategy(
@@ -50,6 +53,15 @@ exports.loadPassport = function (aStrategy) {
5053
);
5154
}
5255

56+
if (aStrategy.name === 'google') {
57+
authParams = instance.authorizationParams;
58+
instance.authorizationParams = function() {
59+
var val = authParams.apply(this, arguments);
60+
val['openid.realm'] = AUTH_CALLBACK_BASE_URL + '/';
61+
return val;
62+
};
63+
}
64+
5365
exports.strategyInstances[aStrategy.name] = instance;
5466
passport.use(instance);
5567
};

libs/passportVerify.js

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,18 @@ var userRoles = require('../models/userRoles.json');
1616
exports.verify = function (aId, aStrategy, aUsername, aLoggedIn, aDone) {
1717
var shasum = crypto.createHash('sha256');
1818
var digest = null;
19+
var query = {};
20+
var ids = [];
1921

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

30-
findDeadorAlive(User, { 'auths': digest }, true,
39+
if (!query.auths) {
40+
query.auths = digest;
41+
}
42+
43+
findDeadorAlive(User, query, true,
3144
function (aAlive, aUser, aRemoved) {
3245
var pos = aUser ? aUser.auths.indexOf(digest) : -1;
46+
var opendIdPos = -1;
3347
if (aRemoved) { aDone(null, false, 'user was removed'); }
3448

49+
// Set up for OpenId to OAuth Migration
50+
if (!digest && ids.length > 0) {
51+
digest = ids[1];
52+
if (aUser) {
53+
pos = aUser.auths.indexOf(digest);
54+
opendIdPos = aUser.auths.indexOf(ids[0]);
55+
}
56+
}
57+
3558
if (!aUser) {
3659
User.findOne({ 'name': aUsername }, function (aErr, aUser) {
3760
if (aUser && aLoggedIn) {
@@ -69,6 +92,12 @@ exports.verify = function (aId, aStrategy, aUsername, aLoggedIn, aDone) {
6992
aUser.save(function (aErr, aUser) {
7093
return aDone(aErr, aUser);
7194
});
95+
} else if (opendIdPos > 0) {
96+
// Migrate from OpenID to OAuth
97+
aUser.auths[opendIdPos] = digest;
98+
aUser.save(function (aErr, aUser) {
99+
return aDone(aErr, aUser);
100+
});
72101
} else {
73102
// The user was authenticated
74103
return aDone(null, aUser);

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"github": "0.2.3",
2222
"highlight.js": "8.4.0",
2323
"jquery": "2.1.3",
24+
"jwt-simple": "0.2.0",
2425
"less-middleware": "1.0.4",
2526
"marked": "0.3.3",
2627
"method-override": "2.3.1",
@@ -36,7 +37,7 @@
3637
"passport-flickr": "0.2.0",
3738
"passport-foursquare": "1.0.0",
3839
"passport-github": "0.1.5",
39-
"passport-google": "0.3.0",
40+
"passport-google-oauth": "0.1.5",
4041
"passport-imgur": "0.0.2",
4142
"passport-instagram": "0.1.2",
4243
"passport-linkedin": "0.1.3",

0 commit comments

Comments
 (0)