diff --git a/packages/accounts-oauth-helper/oauth_server.js b/packages/accounts-oauth-helper/oauth_server.js index de59b38411..37fa4c6487 100644 --- a/packages/accounts-oauth-helper/oauth_server.js +++ b/packages/accounts-oauth-helper/oauth_server.js @@ -75,11 +75,8 @@ var service = Meteor.accounts.oauth._services[serviceName]; // Skip everything if there's no service set by the oauth middleware - // XXX should we instead throw an error? - if (!service) { - next(); - return; - } + if (!service) + throw new Error("Unexpected OAuth service " + serviceName); // Make sure we're configured ensureConfigured(serviceName); diff --git a/packages/accounts-oauth-helper/package.js b/packages/accounts-oauth-helper/package.js index 532b80fb16..c773ae24d6 100644 --- a/packages/accounts-oauth-helper/package.js +++ b/packages/accounts-oauth-helper/package.js @@ -10,9 +10,3 @@ Package.on_use(function (api) { api.add_files('oauth_client.js', 'client'); api.add_files('oauth_server.js', 'server'); }); - -Package.on_test(function (api) { - // XXX Fix these! - // api.use('accounts-oauth-helper', 'server'); - // api.add_files("oauth_tests.js", 'server'); -}); diff --git a/packages/accounts-oauth1-helper/oauth1_server.js b/packages/accounts-oauth1-helper/oauth1_server.js index 4249d2a6b9..84be5a4ec2 100644 --- a/packages/accounts-oauth1-helper/oauth1_server.js +++ b/packages/accounts-oauth1-helper/oauth1_server.js @@ -1,6 +1,9 @@ (function () { var connect = __meteor_bootstrap__.require("connect"); + // A place to store request tokens pending verification + Meteor.accounts.oauth1._requestTokens = {}; + // connect middleware Meteor.accounts.oauth1._handleRequest = function (service, query, res) { @@ -8,7 +11,7 @@ // This way the subsequent call to the `login` method will be // immediate. - var config = Meteor.accounts[serviceName]; + var config = Meteor.accounts[service.serviceName]; var oauth = new OAuth1(config); // If we get here with a callback url we need a request token to @@ -18,6 +21,9 @@ // Get a request token to start auth process oauth.getRequestToken(query.callbackUrl); + // Keep track of request token so we can verify it on the next step + Meteor.accounts.oauth1._requestTokens[query.state] = oauth.requestToken; + var redirectUrl = config._urls.authenticate + '?oauth_token=' + oauth.requestToken; res.writeHead(302, {'Location': redirectUrl}); res.end(); @@ -27,13 +33,15 @@ } else { - // XXX Twitter's docs say to check that oauth_token is the - // same as the request token received in previous step + // Get the user's request token so we can verify it and clear it + var requestToken = Meteor.accounts.oauth1._requestTokens[query.state]; + delete Meteor.accounts.oauth1._requestTokens[query.state]; - if (query.oauth_token) { - // The user authorized access + // Verify user authorized access and the oauth_token matches + // the requestToken from previous step + if (query.oauth_token && query.oauth_token === requestToken) { - // Get the oauth token for signing requests + // Get the access token for signing requests oauth.getAccessToken(query); // Get or create user id diff --git a/packages/accounts-twitter/twitter_client.js b/packages/accounts-twitter/twitter_client.js index d93aa01cc9..8ecdafd6e2 100644 --- a/packages/accounts-twitter/twitter_client.js +++ b/packages/accounts-twitter/twitter_client.js @@ -4,8 +4,11 @@ throw new Meteor.accounts.ConfigError("Need to call Meteor.accounts.twitter.config first"); var state = Meteor.uuid(); + // We need to keep state across the next two 'steps' so we're adding + // a state parameter to the url and the callback url that we'll be returned + // to by oauth provider var callbackUrl = Meteor.accounts.twitter._appUrl + '/_oauth/twitter?close&state=' + state; - var url = '/_oauth/twitter/request_token?callbackUrl=' + encodeURIComponent(callbackUrl) + var url = '/_oauth/twitter/request_token?callbackUrl=' + encodeURIComponent(callbackUrl) + '&state=' + state Meteor.accounts.oauth.initiateLogin(state, url); };