Consolidate some routes into their corresponding js files

This commit is contained in:
Johannes Zellner
2014-04-06 19:31:23 -07:00
parent 289acc8850
commit a7ca7900a3
10 changed files with 166 additions and 213 deletions
+1 -1
View File
@@ -9,7 +9,7 @@ var passport = require('passport'),
BasicStrategy = require('passport-http').BasicStrategy,
ClientPasswordStrategy = require('passport-oauth2-client-password').Strategy,
BearerStrategy = require('passport-http-bearer').Strategy,
debug = require('debug')('auth:auth'),
debug = require('debug')('authserver:auth'),
DatabaseError = require('./databaseerror'),
clientdb = require('./clientdb'),
tokendb = require('./tokendb'),
+13 -5
View File
@@ -1,7 +1,7 @@
'use strict';
var DatabaseError = require('./databaseerror'),
debug = require('debug')('clientdb'),
debug = require('debug')('authserver:clientdb'),
assert = require('assert');
// database
@@ -29,6 +29,8 @@ function get(id, callback) {
assert(typeof id === 'string');
assert(typeof callback === 'function');
debug('get: ' + id);
if (!db[id]) return callback(new DatabaseError(DatabaseError.NOT_FOUND));
callback(null, db[id]);
}
@@ -38,6 +40,8 @@ function getByClientId(clientId, callback) {
assert(typeof clientId === 'string');
assert(typeof callback === 'function');
debug('getByClientId: ' + clientId);
for (var record in db) {
if (db.hasOwnProperty(record)) {
if (db[record].clientId === clientId) {
@@ -49,16 +53,20 @@ function getByClientId(clientId, callback) {
return callback(new DatabaseError(DatabaseError.NOT_FOUND));
}
function add(id, data, callback) {
function add(id, redirectURI, callback) {
assert(db !== null);
assert(typeof id === 'string');
assert(typeof data === 'object');
assert(typeof redirectURI === 'string');
assert(typeof callback === 'function');
data.id = id;
debug('add: ' + id + ' redirectURI "' + redirectURI + '"');
if (db[id]) return callback(new DatabaseError(DatabaseError.ALREADY_EXISTS));
db[id] = data;
db[id] = {
id: id,
redirectURI: redirectURI
};
callback(null);
}
+42 -33
View File
@@ -6,11 +6,10 @@
var oauth2orize = require('oauth2orize'),
passport = require('passport'),
login = require('connect-ensure-login'),
session = require('connect-ensure-login'),
authcodedb = require('./authcodedb'),
tokendb = require('./tokendb'),
DatabaseError = require('./databaseerror'),
userdb = require('./userdb'),
clientdb = require('./clientdb'),
uuid = require('node-uuid');
@@ -30,13 +29,13 @@ var server = oauth2orize.createServer();
// simple matter of serializing the client's ID, and deserializing by finding
// the client by ID from the database.
server.serializeClient(function(client, callback) {
server.serializeClient(function (client, callback) {
console.log('server serialize', client, client.id);
return callback(null, client.id);
});
server.deserializeClient(function(id, callback) {
server.deserializeClient(function (id, callback) {
console.log('server deserialize', id);
clientdb.get(id, function (error, client) {
@@ -99,6 +98,31 @@ server.exchange(oauth2orize.exchange.code(function (client, code, redirectURI, c
}));
// Main login form username and password
module.exports.loginForm = function (req, res) {
res.render('login');
};
// performs the login POST from the above form
module.exports.login = passport.authenticate('local', {
successReturnToOrRedirect: '/api/v1/session/account',
failureRedirect: '/api/v1/session/login'
});
// ends the current session
module.exports.logout = function (req, res) {
req.logout();
res.redirect('/');
};
// Temporary helper functions to see a login session
module.exports.account = [
session.ensureLoggedIn('/api/v1/session/login'),
function(req, res) {
res.render('account', { user: req.user });
}
];
// user authorization endpoint
//
@@ -116,46 +140,31 @@ server.exchange(oauth2orize.exchange.code(function (client, code, redirectURI, c
// authorization). We accomplish that here by routing through `ensureLoggedIn()`
// first, and rendering the `dialog` view.
exports.authorization = [
login.ensureLoggedIn('/api/v1/session/login'),
server.authorization(function(clientID, redirectURI, callback) {
module.exports.authorization = [
session.ensureLoggedIn('/api/v1/session/login'),
server.authorization(function (clientID, redirectURI, callback) {
console.log('server authorization validation for ', clientID, redirectURI);
clientdb.getByClientId(clientID, function(error, client) {
if (error) return callback(error);
// WARNING: For security purposes, it is highly advisable to check that
// redirectURI provided by the client matches one registered with
// the server. For simplicity, this example does not. You have
// been warned.
return callback(null, client, redirectURI);
clientdb.getByClientId(clientID, function (error, client) {
// TODO actually check redirectURI
if (error) return callback(error);
callback(null, client, redirectURI);
});
}),
function(req, res){
function (req, res) {
res.render('dialog', { transactionID: req.oauth2.transactionID, user: req.user, client: req.oauth2.client });
}
];
// user decision endpoint
//
// `decision` middleware processes a user's decision to allow or deny access
// requested by a client application. Based on the grant type requested by the
// client, the above grant middleware configured above will be invoked to send
// a response.
exports.decision = [
login.ensureLoggedIn('/api/v1/session/login'),
// this triggers the above grant middleware and handles the user's decision if he accepts the access
module.exports.decision = [
session.ensureLoggedIn('/api/v1/session/login'),
server.decision()
];
// token endpoint
//
// `token` middleware handles client requests to exchange authorization grants
// for access tokens. Based on the grant type being exchanged, the above
// exchange middleware will be invoked to handle the request. Clients must
// authenticate when making requests to this endpoint.
exports.token = [
// the token endpoint exchanges an authcode for an access token
// it still requires basic or oauth2-client-password authentication
module.exports.token = [
passport.authenticate(['basic', 'oauth2-client-password'], { session: false }),
server.token(),
server.errorHandler()
-6
View File
@@ -1,6 +0,0 @@
'use strict';
exports = module.exports = {
user: require('./user')
};
-50
View File
@@ -1,50 +0,0 @@
'use strict';
var userdb = require('../userdb'),
DatabaseError = require('../databaseerror'),
crypto = require('crypto'),
debug = require('debug')('auth:routes/user'),
HttpError = require('../../api/httperror'),
HttpSuccess = require('../../api/httpsuccess');
exports = module.exports = {
add: add,
get: get,
getAll: getAll,
remove: remove
};
function add(req, res, next) {
if (!req.body.username) return next(new HttpError(400, 'No username provided'));
if (!req.body.password) return next(new HttpError(400, 'No password provided'));
if (!req.body.email) return next(new HttpError(400, 'No email provided'));
userdb.add(req.body.username, req.body.username, req.body.password, req.body.email, function (error) {
if (error && error.reason === DatabaseError.ALREADY_EXISTS) return next(new HttpError(409, 'User already exists'));
if (error) return next(new HttpError(500));
next(new HttpSuccess(201, {}));
});
}
function get(req, res, next) {
console.log('---', req.user);
}
function getAll(req, res, next) {
userdb.getAll(function (error, result) {
if (error) return next(new HttpError(500));
next(new HttpSuccess(200, { users: result }));
});
}
function remove(req, res, next) {
if (!req.body.userId) return next(new HttpError(400, 'No username provided'));
if (!req.body.password) return next(new HttpError(400, 'No password provided'));
// TODO check password
userdb.del(req.body.userId, function (error) {
if (error && error.reason === DatabaseError.NOT_FOUND) return next(new HttpError(404, 'No such user'));
if (error) return next(new HttpError(500));
next(new HttpSuccess(200, {}));
});
}
+19 -19
View File
@@ -7,15 +7,14 @@ var express = require('express'),
path = require('path'),
passport = require('passport'),
oauth2 = require('./oauth2'),
session = require('./session'),
routes = require('./routes/'),
HttpError = require('../api/httperror'),
HttpSuccess = require('../api/httpsuccess'),
middleware = require('../middleware/'),
debug = require('debug')('main'),
debug = require('debug')('authserver:server'),
tokendb = require('./tokendb'),
clientdb = require('./clientdb'),
userdb = require('./userdb'),
user = require('./user'),
assert = require('assert');
module.exports = Server;
@@ -112,20 +111,21 @@ Server.prototype._initialize = function (callback) {
// Passport configuration
require('./auth');
// routes controlled by app.router
that.app.get('/', session.account);
// form based login routes
that.app.get('/api/v1/session/login', session.loginForm);
that.app.post('/api/v1/session/login', session.login);
that.app.get('/api/v1/session/logout', session.logout);
that.app.get('/api/v1/session/account', session.account);
// TODO this route needs to be replaced by a better strategy
that.app.post('/api/v1/owner', user.owner);
// user resource routes
that.app.post('/api/v1/users', routes.user.add);
that.app.get('/api/v1/users', routes.user.get);
// that.app.put('/api/v1/users', routes.user.update);
that.app.del('/api/v1/users', routes.user.remove);
that.app.post('/api/v1/users', user.add);
that.app.get('/api/v1/users', user.get);
that.app.del('/api/v1/users', user.remove);
// form based login routes used by oauth2 frame
that.app.get('/api/v1/session/login', oauth2.loginForm);
that.app.post('/api/v1/session/login', oauth2.login);
that.app.get('/api/v1/session/logout', oauth2.logout);
// TODO this is only temporary
that.app.get('/api/v1/session/account', oauth2.account);
// oauth2 routes
that.app.get('/api/v1/oauth/dialog/authorize', oauth2.authorization);
@@ -166,17 +166,17 @@ Server.prototype.start = function (callback) {
userdb.init(that._configDir, function (error) {
if (error) return callback(error);
// TODO add initial user only until the user creation works
userdb.add('test', 'test', 'foo', 'test@foo.com', function (error) {
console.log('+++ user added');
});
tokendb.init(that._configDir, function (error) {
if (error) return callback(error);
clientdb.init(that._configDir, function (error) {
if (error) return callback(error);
// TODO this is temporary, add webadmin client id
clientdb.add('abc123', 'https://localhost:3000/oauth2/oauth_callback.html', function (error) {
console.log('+++ webadmin client added');
});
that._initialize(function (error) {
if (error) return callback(error);
-26
View File
@@ -1,26 +0,0 @@
'use strict';
/*
Contains the needed UI elements for the oauth2 dialogs
*/
var passport = require('passport'),
login = require('connect-ensure-login');
exports.loginForm = function(req, res) {
res.render('login');
};
exports.login = passport.authenticate('local', { successReturnToOrRedirect: '/api/v1/session/account', failureRedirect: '/api/v1/session/login' });
exports.logout = function(req, res) {
req.logout();
res.redirect('/');
};
exports.account = [
login.ensureLoggedIn('/api/v1/session/login'),
function(req, res) {
res.render('account', { user: req.user });
}
];
+69 -14
View File
@@ -1,18 +1,73 @@
'use strict';
/*
contains the protected test route to get user info
*/
var userdb = require('./userdb'),
DatabaseError = require('./databaseerror'),
crypto = require('crypto'),
debug = require('debug')('authserver:user'),
HttpError = require('../api/httperror'),
HttpSuccess = require('../api/httpsuccess');
var passport = require('passport');
exports = module.exports = {
owner: owner,
add: add,
get: get,
getAll: getAll,
remove: remove
};
exports.info = [
passport.authenticate('bearer', { session: false }),
function(req, res) {
// req.authInfo is set using the `info` argument supplied by
// `BearerStrategy`. It is typically used to indicate scope of the token,
// and used in access control checks. For illustrative purposes, this
// example simply returns the scope in the response.
res.json({ user_id: req.user.id, name: req.user.name, scope: req.authInfo.scope });
}
];
function owner(req, res, next) {
debug('add owner: ' + req.body.username + ' ' + req.body.password + ' ' + req.body.email);
if (!req.body.username) return next(new HttpError(400, 'No username provided'));
if (!req.body.password) return next(new HttpError(400, 'No password provided'));
if (!req.body.email) return next(new HttpError(400, 'No email provided'));
userdb.add(req.body.username, req.body.username, req.body.password, req.body.email, function (error) {
if (error && error.reason === DatabaseError.ALREADY_EXISTS) return next(new HttpError(409, 'User already exists'));
if (error) return next(new HttpError(500));
next(new HttpSuccess(201, {}));
});
}
function add(req, res, next) {
debug('add user: ' + req.body.username + ' ' + req.body.password + ' ' + req.body.email);
if (!req.body.username) return next(new HttpError(400, 'No username provided'));
if (!req.body.password) return next(new HttpError(400, 'No password provided'));
if (!req.body.email) return next(new HttpError(400, 'No email provided'));
userdb.add(req.body.username, req.body.username, req.body.password, req.body.email, function (error) {
if (error && error.reason === DatabaseError.ALREADY_EXISTS) return next(new HttpError(409, 'User already exists'));
if (error) return next(new HttpError(500));
next(new HttpSuccess(201, {}));
});
}
function get(req, res, next) {
debug('get');
console.log('---', req.user);
}
function getAll(req, res, next) {
debug('getAll');
userdb.getAll(function (error, result) {
if (error) return next(new HttpError(500));
next(new HttpSuccess(200, { users: result }));
});
}
function remove(req, res, next) {
debug('remove: ' + req.body.userId + ' ' + req.body.password);
if (!req.body.userId) return next(new HttpError(400, 'No username provided'));
if (!req.body.password) return next(new HttpError(400, 'No password provided'));
// TODO check password
userdb.del(req.body.userId, function (error) {
if (error && error.reason === DatabaseError.NOT_FOUND) return next(new HttpError(404, 'No such user'));
if (error) return next(new HttpError(500));
next(new HttpSuccess(200, {}));
});
}
+1 -1
View File
@@ -2,7 +2,7 @@
var DatabaseError = require('./databaseerror'),
tokendb = require('./tokendb'),
debug = require('debug')('userdb'),
debug = require('debug')('authserver:userdb'),
assert = require('assert');
// database
+21 -58
View File
@@ -38,38 +38,34 @@ function setAuthCode(code) {
}
function init() {
btn = document.getElementById('startButton');
startBtn = document.getElementById('startButton');
tokenBtn = document.getElementById('tokenButton');
logoutBtn = document.getElementById('logoutButton');
frame = document.getElementById('frame');
// loginForm = document.getElementById('loginForm');
oauthResult = document.getElementById('oauthResult');
infoButton = document.getElementById('infoButton');
userInfo = document.getElementById('userInfo');
// loginForm.onsubmit = function (event) {
// event.preventDefault();
loginForm.onsubmit = function (event) {
event.preventDefault();
// superagent.post(accountsServer + '/api/v1/session/login')
// .send({
// username: loginForm.elements.namedItem('username').value,
// password: loginForm.elements.namedItem('password').value
// })
// .end(function (error, result) {
// if (error) {
// alert('Login failed, see console.');
// console.error(error);
// return;
// }
superagent.post(accountsServer + '/api/v1/session/login')
.send({
username: loginForm.elements.namedItem('username').value,
password: loginForm.elements.namedItem('password').value
})
.end(function (error, result) {
if (error) {
alert('Login failed, see console.');
console.error(error);
return;
}
// alert('Login successfull');
// console.log(result.body);
// });
alert('Login successfull');
console.log(result.body);
});
// return false;
// }
return false;
}
btn.onclick = function () {
startBtn.onclick = function () {
frame.src = accountsServer + '/api/v1/oauth/dialog/authorize?response_type=code&client_id=abc123&redirect_uri=' + redirectServer + '/oauth2/oauth_callback.html';
frame.style.display = 'block';
};
@@ -81,7 +77,7 @@ function init() {
code: authCode,
redirect_uri: redirectServer + '/oauth2/oauth_callback.html',
client_id: 'abc123',
client_secret: 'ssh-secret'
client_secret: 'not used for in browser app'
})
.end(function (error, result) {
if (error) {
@@ -96,35 +92,6 @@ function init() {
console.log(result.body);
});
};
// logoutBtn.onclick = function () {
// superagent.get(accountsServer + '/api/v1/session/logout')
// .end(function (error, result) {
// if (error) {
// alert('Logout failed, see console.');
// console.error(error);
// return;
// }
// alert('Logout successfull');
// console.log(result.body);
// });
// };
infoButton.onclick = function () {
superagent.get(accountsServer + '/users')
.set('Authorization', 'Bearer ' + accessToken)
.end(function (error, result) {
if (error) {
alert('User info failed, see console.');
console.error(error);
return;
}
userInfo.innerText = JSON.stringify(result.body);
console.log(result.body);
});
};
}
</script>
@@ -133,13 +100,9 @@ function init() {
<body onload="init()">
<hr/>
<button id="infoButton">Get User Info</button>
<div id="userInfo"></div>
<hr/>
OAuth based login: <button id="startButton">Go for it</button>
<div id="oauthResult"></div>
<button id="tokenButton" style="display: none"/>Exchange code for token</button>
<iframe id="frame" style="display: none"></iframe>