Handle unexpected keys for pending OAuth credentials.

Duplicate keys aren't expected, but in case something weird happens,
just override the previous information associated with that key. We
simply insert nothing for non-string keys (e.g. an OAuth flow with no
`state` parameter, which should never happen normally).
This commit is contained in:
Emily Stark
2014-04-24 09:56:42 -07:00
parent 682dd7895a
commit 9fb63da3c7
4 changed files with 65 additions and 5 deletions

View File

@@ -28,3 +28,22 @@ Tinytest.add("oauth - pendingCredential handles Meteor.Errors", function (test)
test.equal(result.stack, testError.stack);
test.isUndefined(result.meteorError);
});
Tinytest.add("oauth - null, undefined key for pendingCredential", function (test) {
var cred = Random.id();
test.throws(function () {
OAuth._storePendingCredential(null, cred);
});
test.throws(function () {
OAuth._storePendingCredential(undefined, cred);
});
});
Tinytest.add("oauth - pendingCredential handles duplicate key", function (test) {
var key = Random.id();
var cred = Random.id();
OAuth._storePendingCredential(key, cred);
var newCred = Random.id();
OAuth._storePendingCredential(key, newCred);
test.equal(OAuth._retrievePendingCredential(key), newCred);
});

View File

@@ -31,19 +31,27 @@ var _cleanStaleResults = function() {
var _cleanupHandle = Meteor.setInterval(_cleanStaleResults, 60 * 1000);
// Stores the key and credential in the _pendingCredentials collection
// Stores the key and credential in the _pendingCredentials collection.
// Will throw an exception if `key` is not a string.
//
// @param key {string}
// @param credential {string} The credential to store
//
OAuth._storePendingCredential = function (key, credential) {
check(key, String);
if (credential instanceof Error) {
credential = storableError(credential);
} else {
credential = OAuth.sealSecret(credential);
}
OAuth._pendingCredentials.insert({
// We do an upsert here instead of an insert in case the user happens
// to somehow send the same `state` parameter twice during an OAuth
// login; we don't want a duplicate key error.
OAuth._pendingCredentials.upsert({
key: key
}, {
key: key,
credential: credential,
createdAt: new Date()

View File

@@ -15,7 +15,8 @@
// For this reason, the _pendingRequestTokens are stored in the database
// so they can be shared across Meteor App servers.
//
// XXX This code is fairly similar to oauth/pending_credentials.js --
// maybe we can combine them somehow.
// Collection containing pending request tokens
// Has key, requestToken, requestTokenSecret, and createdAt fields.
@@ -39,14 +40,22 @@ var _cleanStaleResults = function() {
var _cleanupHandle = Meteor.setInterval(_cleanStaleResults, 60 * 1000);
// Stores the key and request token in the _pendingRequestTokens collection
// Stores the key and request token in the _pendingRequestTokens collection.
// Will throw an exception if `key` is not a string.
//
// @param key {string}
// @param requestToken {string}
// @param requestTokenSecret {string}
//
OAuth._storeRequestToken = function (key, requestToken, requestTokenSecret) {
OAuth._pendingRequestTokens.insert({
check(key, String);
// We do an upsert here instead of an insert in case the user happens
// to somehow send the same `state` parameter twice during an OAuth
// login; we don't want a duplicate key error.
OAuth._pendingRequestTokens.upsert({
key: key
}, {
key: key,
requestToken: OAuth.sealSecret(requestToken),
requestTokenSecret: OAuth.sealSecret(requestTokenSecret),

View File

@@ -84,3 +84,27 @@ Tinytest.add("oauth1 - pendingCredential is stored and can be retrieved (with oa
OAuthEncryption.loadKey(null);
}
});
Tinytest.add("oauth1 - duplicate key for request token", function (test) {
var key = Random.id();
var token = Random.id();
var secret = Random.id();
OAuth._storeRequestToken(key, token, secret);
var newToken = Random.id();
var newSecret = Random.id();
OAuth._storeRequestToken(key, newToken, newSecret);
var result = OAuth._retrieveRequestToken(key);
test.equal(result.requestToken, newToken);
test.equal(result.requestTokenSecret, newSecret);
});
Tinytest.add("oauth1 - null, undefined key for request token", function (test) {
var token = Random.id();
var secret = Random.id();
test.throws(function () {
OAuth._storeRequestToken(null, token, secret);
});
test.throws(function () {
OAuth._storeRequestToken(undefined, token, secret);
});
});