Tests for oauth2 server flow

This commit is contained in:
Avital Oliver
2012-07-09 16:51:16 -07:00
committed by Nick Martin
parent 1773c91c50
commit cbce421b98
3 changed files with 90 additions and 51 deletions

View File

@@ -49,59 +49,63 @@
// XXX we should periodically clear old entries
Meteor.accounts.oauth2._loginResultForState = {};
// connect middleware
Meteor.accounts.oauth2._handleRequest = function (req, res, next) {
// Need to create a Fiber since we're using synchronous http calls
Fiber(function() {
// req.url will be "/_oauth/<service name>?<action>"
var barePath = req.url.substring(0, req.url.indexOf('?'));
var splitPath = barePath.split('/');
// Any non-oauth request will continue down the default middlewares
if (splitPath[1] !== '_oauth') {
next();
return;
}
// Make sure we prepare the login results before returning.
// This way the subsequent call to the `login` method will be
// immediate.
var serviceName = splitPath[2];
var service = Meteor.accounts.oauth2._services[serviceName];
// Get or create user id
var userInfo = service.handleOauthRequest(req.query);
var userId = Meteor.accounts.updateOrCreateUser(
userInfo.email, userInfo.userData, serviceName,
userInfo.serviceUserId, userInfo.serviceData);
// Generate and store a login token for reconnect
// XXX this could go in accounts_server.js instead
var loginToken = Meteor.accounts._loginTokens.insert({userId: userId});
// Store results to subsequent call to `login`
Meteor.accounts.oauth2._loginResultForState[req.query.state] =
{token: loginToken, id: userId};
// We support ?close and ?redirect=URL. Any other query should
// just serve a blank page
if ('close' in req.query) { // check with 'in' because we don't set a value
// Close the popup window
res.writeHead(200, {'Content-Type': 'text/html'});
var content =
'<html><head><script>window.close()</script></head></html>';
res.end(content, 'utf-8');
} else if (req.query.redirect) {
res.writeHead(302, {'Location': req.query.redirect});
res.end();
} else {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end('', 'utf-8');
}
}).run();
};
// Listen on /_oauth/*
__meteor_bootstrap__.app
.use(connect.query())
.use(function (req, res, next) {
// Need to create a Fiber since we're using synchronous http calls
Fiber(function() {
// req.url will be "/_oauth/<service name>?<action>"
var barePath = req.url.substring(0, req.url.indexOf('?'));
var splitPath = barePath.split('/');
// Any non-oauth request will continue down the default middlewares
if (splitPath[1] !== '_oauth') {
next();
return;
}
// Make sure we prepare the login results before returning.
// This way the subsequent call to the `login` method will be
// immediate.
var serviceName = splitPath[2];
var service = Meteor.accounts.oauth2._services[serviceName];
// Get or create user id
var userInfo = service.handleOauthRequest(req.query);
var userId = Meteor.accounts.updateOrCreateUser(
userInfo.email, userInfo.userData, serviceName,
userInfo.serviceUserId, userInfo.serviceData);
// Generate and store a login token for reconnect
// XXX this could go in accounts_server.js instead
var loginToken = Meteor.accounts._loginTokens.insert({userId: userId});
// Store results to subsequent call to `login`
Meteor.accounts.oauth2._loginResultForState[req.query.state] =
{token: loginToken, id: userId};
// We support ?close and ?redirect=URL. Any other query should
// just serve a blank page
if ('close' in req.query) { // check with 'in' because we don't set a value
// Close the popup window
res.writeHead(200, {'Content-Type': 'text/html'});
var content =
'<html><head><script>window.close()</script></head></html>';
res.end(content, 'utf-8');
} else if (req.query.redirect) {
res.writeHead(302, {'Location': req.query.redirect});
res.end();
} else {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end('', 'utf-8');
}
}).run();
});
.use(Meteor.accounts.oauth2._handleRequest);
})();

View File

@@ -0,0 +1,31 @@
Tinytest.add("oauth2 - loginResultForState is stored", function (test) {
var http = __meteor_bootstrap__.require('http');
Meteor.accounts._loginTokens.remove({});
// register a fake login service - foobook
Meteor.accounts.oauth2.registerService("foobook", function (query) {
return {email: 'foo@bar.com', userData: {},
serviceUserId: 1, serviceData: {}};
});
// simulate logging in using foobook
var req = {method: "POST",
url: "/_oauth/foobook?close",
query: {state: "STATE"}};
Meteor.accounts.oauth2._handleRequest(req, new http.ServerResponse(req));
// verify that a user is created
var user = Meteor.users.findOne({emails: 'foo@bar.com'});
test.equal(user.services.foobook.id, 1);
// and that that user has a login token
var token = Meteor.accounts._loginTokens.findOne({userId: user._id});
test.notEqual(token, undefined);
// and that the login result for that user is prepared
test.equal(
Meteor.accounts.oauth2._loginResultForState['STATE'].id, user._id);
test.equal(
Meteor.accounts.oauth2._loginResultForState['STATE'].token, token._id);
});

View File

@@ -10,3 +10,7 @@ Package.on_use(function (api) {
api.add_files('oauth2_server.js', 'server');
api.add_files('oauth2_client.js', 'client');
});
Package.on_test(function (api) {
api.add_files("oauth2_tests.js", 'server');
});