Bug 959919 - Send X-Client-State header to token server. r=rnewman

This commit is contained in:
Jed Parsons 2014-01-29 15:02:09 -08:00
Родитель b9c7ed469b
Коммит 33b83f2be5
5 изменённых файлов: 82 добавлений и 12 удалений

Просмотреть файл

@ -199,14 +199,17 @@ add_test(function test_403_no_urls() {
});
});
add_test(function test_send_conditions_accepted() {
add_test(function test_send_extra_headers() {
_("Ensures that the condition acceptance header is sent when asked.");
let duration = 300;
let server = httpd_setup({
"/1.0/foo/1.0": function(request, response) {
do_check_true(request.hasHeader("x-conditions-accepted"));
do_check_eq(request.getHeader("x-conditions-accepted"), "1");
do_check_true(request.hasHeader("x-foo"));
do_check_eq(request.getHeader("x-foo"), "42");
do_check_true(request.hasHeader("x-bar"));
do_check_eq(request.getHeader("x-bar"), "17");
response.setStatusLine(request.httpVersion, 200, "OK");
response.setHeader("Content-Type", "application/json");
@ -233,7 +236,11 @@ add_test(function test_send_conditions_accepted() {
server.stop(run_next_test);
}
client.getTokenFromBrowserIDAssertion(url, "assertion", onResponse, true);
let extra = {
"X-Foo": 42,
"X-Bar": 17
};
client.getTokenFromBrowserIDAssertion(url, "assertion", onResponse, extra);
});
add_test(function test_error_404_empty() {

Просмотреть файл

@ -206,8 +206,7 @@ TokenServerClient.prototype = {
* (bool) Whether to send acceptance to service conditions.
*/
getTokenFromBrowserIDAssertion:
function getTokenFromBrowserIDAssertion(url, assertion, cb,
conditionsAccepted=false) {
function getTokenFromBrowserIDAssertion(url, assertion, cb, addHeaders={}) {
if (!url) {
throw new TokenServerClientError("url argument is not valid.");
}
@ -226,9 +225,8 @@ TokenServerClient.prototype = {
req.setHeader("Accept", "application/json");
req.setHeader("Authorization", "BrowserID " + assertion);
if (conditionsAccepted) {
// Value is irrelevant.
req.setHeader("X-Conditions-Accepted", "1");
for (let header in addHeaders) {
req.setHeader(header, addHeaders[header]);
}
let client = this;

Просмотреть файл

@ -73,7 +73,7 @@ this.CommonUtils = {
let s = btoa(bytes).replace("+", "-", "g").replace("/", "_", "g");
if (!pad) {
s = s.replace("=", "");
s = s.replace("=", "", "g");
}
return s;

Просмотреть файл

@ -10,6 +10,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-common/async.js");
Cu.import("resource://services-common/utils.js");
Cu.import("resource://services-common/tokenserverclient.js");
Cu.import("resource://services-crypto/utils.js");
Cu.import("resource://services-sync/identity.js");
@ -42,7 +43,6 @@ function deriveKeyBundle(kB) {
return bundle;
}
this.BrowserIDManager = function BrowserIDManager() {
this._fxaService = fxAccounts;
this._tokenServerClient = new TokenServerClient();
@ -163,6 +163,25 @@ this.BrowserIDManager.prototype = {
}
},
/**
* Compute the sha256 of the message bytes. Return bytes.
*/
_sha256: function(message) {
let hasher = Cc["@mozilla.org/security/hash;1"]
.createInstance(Ci.nsICryptoHash);
hasher.init(hasher.SHA256);
return CryptoUtils.digestBytes(message, hasher);
},
/**
* Compute the X-Client-State header given the byte string kB.
*
* Return string: hex(first16Bytes(sha256(kBbytes)))
*/
_computeXClientState: function(kBbytes) {
return CommonUtils.bytesAsHex(this._sha256(kBbytes).slice(0, 16), false);
},
/**
* Provide override point for testing token expiration.
*/
@ -388,6 +407,10 @@ this.BrowserIDManager.prototype = {
let tokenServerURI = Svc.Prefs.get("tokenServerURI");
let log = this._log;
let client = this._tokenServerClient;
// Both Jelly and FxAccounts give us kB as hex
let kBbytes = CommonUtils.hexToBytes(userData.kB);
let headers = {"X-Client-State": this._computeXClientState(kBbytes)};
log.info("Fetching Sync token from: " + tokenServerURI);
function getToken(tokenServerURI, assertion) {
@ -400,7 +423,8 @@ this.BrowserIDManager.prototype = {
return deferred.resolve(token);
}
};
client.getTokenFromBrowserIDAssertion(tokenServerURI, assertion, cb);
client.getTokenFromBrowserIDAssertion(tokenServerURI, assertion, cb, headers);
return deferred.promise;
}

Просмотреть файл

@ -5,6 +5,8 @@ Cu.import("resource://gre/modules/FxAccounts.jsm");
Cu.import("resource://services-sync/browserid_identity.js");
Cu.import("resource://services-sync/rest.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-common/utils.js");
Cu.import("resource://services-crypto/utils.js");
Cu.import("resource://testing-common/services/sync/utils.js");
let identityConfig = makeIdentityConfig();
@ -102,3 +104,42 @@ add_test(function test_userChangeAndLogOut() {
run_next_test();
}
);
add_test(function test_sha256() {
// Test vectors from http://www.bichlmeier.info/sha256test.html
let vectors = [
["",
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"],
["abc",
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"],
["message digest",
"f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650"],
["secure hash algorithm",
"f30ceb2bb2829e79e4ca9753d35a8ecc00262d164cc077080295381cbd643f0d"],
["SHA256 is considered to be safe",
"6819d915c73f4d1e77e4e1b52d1fa0f9cf9beaead3939f15874bd988e2a23630"],
["abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
"248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"],
["For this sample, this 63-byte string will be used as input data",
"f08a78cbbaee082b052ae0708f32fa1e50c5c421aa772ba5dbb406a2ea6be342"],
["This is exactly 64 bytes long, not counting the terminating byte",
"ab64eff7e88e2e46165e29f2bce41826bd4c7b3552f6b382a9e7d3af47c245f8"]
];
let bidUser = new BrowserIDManager();
for (let [input,output] of vectors) {
do_check_eq(CommonUtils.bytesAsHex(bidUser._sha256(input)), output);
}
run_next_test();
});
add_test(function test_computeXClientStateHeader() {
let kBhex = "fd5c747806c07ce0b9d69dcfea144663e630b65ec4963596a22f24910d7dd15d";
let kB = CommonUtils.hexToBytes(kBhex);
let bidUser = new BrowserIDManager();
let header = bidUser._computeXClientState(kB);
do_check_eq(header, "6ae94683571c7a7c54dab4700aa3995f");
run_next_test();
});