mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
Merge branch 'pr-1253' into devel
This commit is contained in:
@@ -21,6 +21,9 @@
|
||||
running on Linux machines with glibc 2.9 or newer (Ubuntu 10.04+, RHEL
|
||||
and CentOS 6+, Fedora 10+, Debian 6+).
|
||||
|
||||
* Support OAuth1 services that require request token secrets as well as
|
||||
authentication token secrets. #1253
|
||||
|
||||
## v0.6.5.1
|
||||
|
||||
* Fix syntax errors on lines that end with a backslash. #1326
|
||||
|
||||
@@ -4,16 +4,16 @@ var querystring = Npm.require("querystring");
|
||||
// An OAuth1 wrapper around http calls which helps get tokens and
|
||||
// takes care of HTTP headers
|
||||
//
|
||||
// @param consumerKey {String} As supplied by the OAuth1 provider
|
||||
// @param consumerSecret {String} As supplied by the OAuth1 provider
|
||||
// @param config {Object}
|
||||
// - consumerKey (String): oauth consumer key
|
||||
// - secret (String): oauth consumer secret
|
||||
// @param urls {Object}
|
||||
// - requestToken (String): url
|
||||
// - authorize (String): url
|
||||
// - accessToken (String): url
|
||||
// - authenticate (String): url
|
||||
OAuth1Binding = function(consumerKey, consumerSecret, urls) {
|
||||
this._consumerKey = consumerKey;
|
||||
this._secret = consumerSecret;
|
||||
OAuth1Binding = function(config, urls) {
|
||||
this._config = config;
|
||||
this._urls = urls;
|
||||
};
|
||||
|
||||
@@ -27,15 +27,26 @@ OAuth1Binding.prototype.prepareRequestToken = function(callbackUrl) {
|
||||
var response = self._call('POST', self._urls.requestToken, headers);
|
||||
var tokens = querystring.parse(response.content);
|
||||
|
||||
// XXX should we also store oauth_token_secret here?
|
||||
if (!tokens.oauth_callback_confirmed)
|
||||
throw new Error("oauth_callback_confirmed false when requesting oauth1 token", tokens);
|
||||
throw new Error(
|
||||
"oauth_callback_confirmed false when requesting oauth1 token", tokens);
|
||||
|
||||
self.requestToken = tokens.oauth_token;
|
||||
self.requestTokenSecret = tokens.oauth_token_secret;
|
||||
};
|
||||
|
||||
OAuth1Binding.prototype.prepareAccessToken = function(query) {
|
||||
OAuth1Binding.prototype.prepareAccessToken = function(query, requestTokenSecret) {
|
||||
var self = this;
|
||||
|
||||
// support implementations that use request token secrets. This is
|
||||
// read by self._call.
|
||||
//
|
||||
// XXX make it a param to call, not something stashed on self? It's
|
||||
// kinda confusing right now, everything except this is passed as
|
||||
// arguments, but this is stored.
|
||||
if (requestTokenSecret)
|
||||
self.accessTokenSecret = requestTokenSecret;
|
||||
|
||||
var headers = self._buildHeader({
|
||||
oauth_token: query.oauth_token
|
||||
});
|
||||
@@ -76,7 +87,7 @@ OAuth1Binding.prototype.post = function(url, params, callback) {
|
||||
OAuth1Binding.prototype._buildHeader = function(headers) {
|
||||
var self = this;
|
||||
return _.extend({
|
||||
oauth_consumer_key: self._consumerKey,
|
||||
oauth_consumer_key: self._config.consumerKey,
|
||||
oauth_nonce: Random.id().replace(/\W/g, ''),
|
||||
oauth_signature_method: 'HMAC-SHA1',
|
||||
oauth_timestamp: (new Date().valueOf()/1000).toFixed().toString(),
|
||||
@@ -98,7 +109,7 @@ OAuth1Binding.prototype._getSignature = function(method, url, rawHeaders, access
|
||||
self._encodeString(parameters)
|
||||
].join('&');
|
||||
|
||||
var signingKey = self._encodeString(self._secret) + '&';
|
||||
var signingKey = self._encodeString(self._config.secret) + '&';
|
||||
if (accessTokenSecret)
|
||||
signingKey += self._encodeString(accessTokenSecret);
|
||||
|
||||
@@ -108,8 +119,14 @@ OAuth1Binding.prototype._getSignature = function(method, url, rawHeaders, access
|
||||
OAuth1Binding.prototype._call = function(method, url, headers, params, callback) {
|
||||
var self = this;
|
||||
|
||||
// all URLs to be functions to support parameters/customization
|
||||
if(typeof url === "function") {
|
||||
url = url(self);
|
||||
}
|
||||
|
||||
// Get the signature
|
||||
headers.oauth_signature = self._getSignature(method, url, headers, self.accessTokenSecret, params);
|
||||
headers.oauth_signature =
|
||||
self._getSignature(method, url, headers, self.accessTokenSecret, params);
|
||||
|
||||
// Make a authorization string according to oauth1 spec
|
||||
var authString = self._getAuthHeaderString(headers);
|
||||
|
||||
@@ -12,8 +12,7 @@ Oauth._requestHandlers['1'] = function (service, query, res) {
|
||||
}
|
||||
|
||||
var urls = service.urls;
|
||||
var oauthBinding = new OAuth1Binding(
|
||||
config.consumerKey, config.secret, urls);
|
||||
var oauthBinding = new OAuth1Binding(config, urls);
|
||||
|
||||
if (query.requestTokenAndRedirect) {
|
||||
// step 1 - get and store a request token
|
||||
@@ -22,10 +21,20 @@ Oauth._requestHandlers['1'] = function (service, query, res) {
|
||||
oauthBinding.prepareRequestToken(query.requestTokenAndRedirect);
|
||||
|
||||
// Keep track of request token so we can verify it on the next step
|
||||
requestTokens[query.state] = oauthBinding.requestToken;
|
||||
requestTokens[query.state] = {
|
||||
requestToken: oauthBinding.requestToken,
|
||||
requestTokenSecret: oauthBinding.requestTokenSecret
|
||||
};
|
||||
|
||||
// support for scope/name parameters
|
||||
var redirectUrl = undefined;
|
||||
if(typeof urls.authenticate === "function") {
|
||||
redirectUrl = urls.authenticate(oauthBinding);
|
||||
} else {
|
||||
redirectUrl = urls.authenticate + '?oauth_token=' + oauthBinding.requestToken;
|
||||
}
|
||||
|
||||
// redirect to provider login, which will redirect back to "step 2" below
|
||||
var redirectUrl = urls.authenticate + '?oauth_token=' + oauthBinding.requestToken;
|
||||
res.writeHead(302, {'Location': redirectUrl});
|
||||
res.end();
|
||||
} else {
|
||||
@@ -34,7 +43,8 @@ Oauth._requestHandlers['1'] = function (service, query, res) {
|
||||
// token and access token secret and log in as user
|
||||
|
||||
// Get the user's request token so we can verify it and clear it
|
||||
var requestToken = requestTokens[query.state];
|
||||
var requestToken = requestTokens[query.state].requestToken;
|
||||
var requestTokenSecret = requestTokens[query.state].requestTokenSecret;
|
||||
delete requestTokens[query.state];
|
||||
|
||||
// Verify user authorized access and the oauth_token matches
|
||||
@@ -45,17 +55,17 @@ Oauth._requestHandlers['1'] = function (service, query, res) {
|
||||
// subsequent call to the `login` method will be immediate.
|
||||
|
||||
// Get the access token for signing requests
|
||||
oauthBinding.prepareAccessToken(query);
|
||||
oauthBinding.prepareAccessToken(query, requestTokenSecret);
|
||||
|
||||
// Run service-specific handler.
|
||||
var oauthResult = service.handleOauthRequest(oauthBinding);
|
||||
|
||||
// Add the login result to the result map
|
||||
Oauth._loginResultForCredentialToken[query.state] = {
|
||||
serviceName: service.serviceName,
|
||||
serviceData: oauthResult.serviceData,
|
||||
options: oauthResult.options
|
||||
};
|
||||
serviceName: service.serviceName,
|
||||
serviceData: oauthResult.serviceData,
|
||||
options: oauthResult.options
|
||||
};
|
||||
}
|
||||
|
||||
// Either close the window, redirect, or render nothing
|
||||
|
||||
@@ -40,7 +40,9 @@ Tinytest.add("oauth1 - loginResultForCredentialToken is stored", function (test)
|
||||
});
|
||||
|
||||
// simulate logging in using twitterfoo
|
||||
OAuth1Test.requestTokens[credentialToken] = twitterfooAccessToken;
|
||||
OAuth1Test.requestTokens[credentialToken] = {
|
||||
requestToken: twitterfooAccessToken
|
||||
};
|
||||
|
||||
var req = {
|
||||
method: "POST",
|
||||
|
||||
Reference in New Issue
Block a user