Skip to content
This repository has been archived by the owner on May 2, 2023. It is now read-only.

Switch passport login strategy from local to oauth2. #37

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 17 additions & 51 deletions api/controllers/UserController.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
* @module :: Controller
* @description :: Пользователи.
*/
var passport = require('passport');

var moment = require('moment');
moment.lang('ru');

var passport = require('passport'),
cfg = require('../../config/local');

module.exports = {

profile: function (req, res) {
Expand Down Expand Up @@ -261,59 +262,24 @@ module.exports = {
},

login: function (req, res) {
async.waterfall([
function authenticate(callback) {
passport.authenticate('local', function (err, user, info) {
if (!user) {
if (info.message === 'Missing credentials') info.message = 'Введите логин/пароль';

return res.json({
error: info
});
}

callback(null, user);
})(req, res);
},
function logIn(user, callback) {
req.logIn(user, function (err) {
if (err) return callback(err);

callback(null, user);
});
},
function checkUserTable(origUser, callback) {
User.findOrCreate({uid: origUser.id}).exec(function (err, user) {
if (err) return callback(err);

if (user.prefix === undefined && user.canModerate === undefined) {
user.uid = origUser.id;
user.canModerate = [];
user.ugroup = 0;
user.startPage = '/all';

user.save(function (err) {
if (err) return callback(err);
callback(null);
});

return;
}

callback(null);
});
}
], function (err) {
if (err) throw err;
res.redirect(cfg.oauth2.loginURI);
},

if (req.body.redirectto) {
callback: function (req, res) {
passport.authenticate('oauth2', function (err, user, info) {
if (!user) {
return res.json({
redirectto: 'http://' + req.host + req.body.redirectto
error: info
});
}

res.redirect('/');
});
req.logIn(user, function (err) {
if (err) {
throw err;
}
res.redirect('/');
return;
});
})(req, res);
},

logout: function (req, res) {
Expand Down
9 changes: 9 additions & 0 deletions config/local.example
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,14 @@ module.exports = {
session: 0
},
pass:'<redis auth password>'
},

oauth2: {
authorizationURL: 'https://api.greencubes.org/oauth/authorize',
tokenURL: 'https://api.greencubes.org/oauth/access_token',
clientID: 42,
clientSecret: '',
callbackURL: "https://help.greencubes.org/oauth/callback",
loginURI: 'http://api.greencubes.org/oauth/authorize?response_type=code&redirect_uri=http://help.greencubes.org/oauth/callback&client_id=42'
}
};
90 changes: 33 additions & 57 deletions config/middleware.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var OAuth2Strategy = require('passport-oauth2').Strategy;
var mysql = require('mysql');
var crypto = require('crypto');
var flash = require('connect-flash');
Expand All @@ -17,7 +17,7 @@ appdbconn = mysql.createPool({
});

passport.serializeUser(function (user, done) {
done(null, user.id);
done(null, user.uid);
});

passport.deserializeUser(function (id, done) {
Expand Down Expand Up @@ -50,6 +50,8 @@ passport.deserializeUser(function (id, done) {
user.startPage = '/all';
}

user.id = user.uid;

callback(null, user);
});
}
Expand All @@ -66,61 +68,35 @@ module.exports = {
// Init custom express middleware
express: {
customMiddleware: function (app) {
passport.use(new LocalStrategy(function (username, password, done) {
username = username.replace(/[^a-zA-Z0-9_-]/g, '');
gcdbconn.query('SELECT id, password, activation_code FROM users WHERE login = ?', [username], function (err, result) {
// database error
if (err) {
return done(err, false, {
message: 'Ошибка базы данных'
});
// username not found
} else if (result.length === 0) {
return done(null, false, {
message: 'Неверный логин/пароль'
});
// check password
} else if (result[0].activation_code === undefined) {
return done(null, false, {
message: 'Аккаунт не активирован'
passport.use(new OAuth2Strategy({
authorizationURL: cfg.oauth2.authorizationURL,
tokenURL: cfg.oauth2.tokenURL,
clientID: cfg.oauth2.clientID,
clientSecret: cfg.oauth2.clientSecret,
callbackURL: cfg.oauth2.callbackURL
}, function(accessToken, refreshToken, profile, done) {
gcdb.user.getByLogin(accessToken.username, 'gcdb', function (err, uid) {
User.findOrCreate({uid: uid}, function (err, user) {
if (!user) {
if (err) return done(err);

user.uid = uid;

user.group = 0; // User have group 0 by default
user.canModerate = [];
user.startPage = '/all';
//user.locale = 'ru';

user.save(function (err, user) {
return done(err, user);
});
} else {
return done(err, user);
}
});
} else {
var passwd = result[0].password.split('$');
var hash;
if (passwd.length == 1) {
hash = crypto.createHash('md5')
.update(password)
.digest('hex');
} else {
hash = crypto.createHash('sha1')
.update(passwd[1] + password)
.digest('hex');
}
// if md5 passwords match
if (passwd.length === 1 && passwd[0] === hash) {
var user = {
id: result[0].id,
username: username,
password: hash
};
// if sha1 passwords match
} else if (passwd.length !== 1 && passwd[2] === hash) {
var user = {
id: result[0].id,
username: username,
password: hash
};

} else {
return done(null, false, {
message: 'Неверный пароль'
});
}

done(null, user);
}
});
}));
});
}
));

app.use(passport.initialize());
app.use(passport.session());
Expand All @@ -129,6 +105,7 @@ module.exports = {

app.use(flash());

// Back button exceptions.
app.use(function (req, res, next) {

if (sails.history && ['/comments', '/csrfToken'].indexOf(req.path) === -1 && sails.history[0] !== req.url) {
Expand All @@ -144,7 +121,6 @@ module.exports = {
}



if (['/comments', '/csrfToken'].indexOf(req.path) === -1 && ['all', 'bugreports','rempros','bans','unbans','admreqs','user','users'].indexOf(req.path.split('/')[1]) !== -1) {
sails.historySpec = req.url;
}
Expand Down
1 change: 1 addition & 0 deletions config/policies.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ module.exports.policies = {
'*': ['authenticated'],
'loginTpl': 'notAuthenticated',
'login': 'notAuthenticated',
'callback': 'notAuthenticated',
'logout': true
},

Expand Down
5 changes: 3 additions & 2 deletions config/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ module.exports.routes = {
'post /settings': 'user.settings',

// Вход в аккаунт и выход из него
'get /login': 'user.loginTpl',
'post /login': 'user.login',
'get /login': 'user.login',
//'post /login': 'user.login',
'/logout': 'user.logout',
'/oauth/callback': 'user.callback',

// Оповещения
'get /notifs': 'notif.listNotifications',
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"optimist": "0.3.4",
"passport": "~0.1.17",
"passport-local": "~0.1.6",
"passport-oauth2": "1.1.x",
"connect-redis": "1.4.x",
"connect-flash": "0.1.x",
"mysql": "2.0.0-alpha9",
Expand Down
4 changes: 2 additions & 2 deletions views/home/partials/header.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
<a href="https://greencubes.org/?action=recover#t" class="item">
Забыли пароль?
</a>
<a href="//greencubes.org/?action=start" class="item">
Регистрация <i class="user icon"></i>
<a href="/login" class="item">
Войти через аккаунт GC <i class="user icon"></i>
</a>
</div>
</div>
21 changes: 0 additions & 21 deletions views/home/preview.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,6 @@
<h3>Решаем проблемы, одобряем заявки</h3>
</div>
</div>
<div class="right floated two wide column loginform">
<form id="loginform" style="margin-top:50px">
<div class="ui form" style="display: inline-block !important">
<div class="field">
<div class="ui left labeled icon input">
<input placeholder="Имя пользователя" type="text" name="username">
<i class="user icon"></i>
</div>
</div>
<div class="field">
<div class="ui left labeled icon input">
<input placeholder="Пароль" type="password" name="password">
<i class="lock icon"></i>
</div>
</div>
<button type="submit" class="ui blue submit button gc-center">Войти</button>
</div>
<input type="hidden" name="_csrf" value="<%= _csrf %>" />
</form>
<div id="loginerr"></div>
</div>
</div>
</div>
<div class="second section">
Expand Down