Bug 1023780 - Ensure that Mobile ID client support the 401/110 error (invalid token) properly. r=jedp

This commit is contained in:
Fernando Jiménez 2014-07-11 14:56:56 +02:00
parent ba1bfdb133
commit 9a27f6101c
2 changed files with 143 additions and 49 deletions

View File

@ -293,6 +293,7 @@ this.MobileIdentityManager = {
},
getCertificate: function(aSessionToken, aPublicKey) {
log.debug("getCertificate");
if (this.certificates[aSessionToken] &&
this.certificates[aSessionToken].validUntil > this.client.hawk.now()) {
return Promise.resolve(this.certificates[aSessionToken].cert);
@ -308,6 +309,7 @@ this.MobileIdentityManager = {
aPublicKey)
.then(
(signedCert) => {
log.debug("Got signed certificate");
this.certificates[aSessionToken] = {
cert: signedCert.cert,
validUntil: validUntil
@ -565,6 +567,7 @@ this.MobileIdentityManager = {
return this.ui.startFlow(aManifestURL, phoneInfoArray)
.then(
(result) => {
log.debug("startFlow result ${} ", result);
if (!result ||
(!result.phoneNumber && (result.serviceId === undefined))) {
return Promise.reject(ERROR_INTERNAL_INVALID_PROMPT_RESULT);
@ -576,7 +579,9 @@ this.MobileIdentityManager = {
// If the user selected one of the existing SIM cards we have to check
// that we either have the MSISDN for that SIM or we can do a silent
// verification that does not require us to have the MSISDN in advance.
if (result.serviceId !== undefined) {
// result.serviceId can be "0".
if (result.serviceId !== undefined &&
result.serviceId !== null) {
let icc = this.iccInfo[result.serviceId];
log.debug("icc ${}", icc);
if (!icc || !icc.msisdn && !icc.canDoSilentVerification) {
@ -777,6 +782,8 @@ this.MobileIdentityManager = {
uri, aPrincipal.appid, aPrincipal.isInBrowserElement);
let manifestURL = appsService.getManifestURLByLocalId(aPrincipal.appId);
let _creds;
// First of all we look if we already have credentials for this origin.
// If we don't have credentials it means that it is the first time that
// the caller requested an assertion.
@ -790,9 +797,11 @@ this.MobileIdentityManager = {
return;
}
_creds = creds;
// Even if we already have credentials for this origin, the consumer
// of the API might want to force the identity selection dialog.
if (aOptions.forceSelection) {
if (aOptions.forceSelection || aOptions.refreshCredentials) {
return this.promptAndVerify(principal, manifestURL, creds)
.then(
(newCreds) => {
@ -911,7 +920,21 @@ this.MobileIdentityManager = {
.then(
null,
(error) => {
log.error("getMobileIdAssertion rejected with " + error);
log.error("getMobileIdAssertion rejected with ${}", error);
// If we got an invalid token error means that the credentials that
// we have are not valid anymore and so we need to refresh them. We
// do that removing the stored credentials and starting over. We also
// make sure that we do this only once.
if (error === ERROR_INVALID_AUTH_TOKEN &&
!aOptions.refreshCredentials) {
log.debug("Need to get new credentials");
aOptions.refreshCredentials = true;
_creds && this.credStore.delete(_creds.msisdn);
this.getMobileIdAssertion(aPrincipal, aPromiseId, aOptions);
return;
}
// Notify the error to the UI.
this.ui.error(error);

View File

@ -194,8 +194,16 @@ MockCredStore.prototype = {
getByOrigin: function() {
this._spy("getByOrigin", arguments);
return Promise.resolve(this._options.getByOriginResult ||
this._getByOriginResult);
let result = this._getByOriginResult;
if (this._options.getByOriginResult) {
if (Array.isArray(this._options.getByOriginResult)) {
result = this._options.getByOriginResult.length ?
this._options.getByOriginResult.shift() : null;
} else {
result = this._options.getByOriginResult;
}
}
return Promise.resolve(result);
},
getByMsisdn: function() {
@ -223,6 +231,11 @@ MockCredStore.prototype = {
removeOrigin: function() {
this._spy("removeOrigin", arguments);
return Promise.resolve();
},
delete: function() {
this._spy("delete", arguments);
return Promise.resolve();
}
};
@ -239,15 +252,11 @@ MockClient.prototype = {
__proto__: Mock.prototype,
_discoverResult: {
verificationMethods: ["sms/momt", "sms/mt"],
verificationMethods: ["sms/mt"],
verificationDetails: {
"sms/mt": {
mtSender: "123",
url: "https://msisdn.accounts.firefox.com/v1/msisdn/sms/mt/verify"
},
"sms/momt": {
mtSender: "123",
moVerifier: "234"
}
}
},
@ -298,6 +307,12 @@ MockClient.prototype = {
sign: function() {
this._spy("sign", arguments);
if (this._options.signError) {
let error = Array.isArray(this._options.signError) ?
this._options.signError.shift() :
this._options.signError;
return Promise.reject(error);
}
return Promise.resolve(this._options.signResult || this._signResult);
}
};
@ -374,17 +389,7 @@ add_test(function() {
MobileIdentityManager.ui = ui;
let credStore = new MockCredStore();
MobileIdentityManager.credStore = credStore;
let client = new MockClient({
discoverResult: {
verificationMethods: ["sms/mt"],
verificationDetails: {
"sms/mt": {
mtSender: "123",
url: "https://msisdn.accounts.firefox.com/v1/msisdn/sms/mt/verify"
}
}
}
});
let client = new MockClient();
MobileIdentityManager.client = client;
let promiseId = Date.now();
@ -615,15 +620,6 @@ add_test(function() {
let credStore = new MockCredStore();
MobileIdentityManager.credStore = credStore;
let client = new MockClient({
discoverResult: {
verificationMethods: ["sms/mt"],
verificationDetails: {
"sms/mt": {
mtSender: "123",
url: "https://msisdn.accounts.firefox.com/v1/msisdn/sms/mt/verify"
}
}
},
signResult: {
cert: "aInvalidCert"
},
@ -813,7 +809,7 @@ add_test(function() {
});
add_test(function() {
do_print("= Existing credentials - No Icc - Permission denied - OK result =");
do_print("= Existing credentials - No Icc - Permission denied - KO result =");
do_register_cleanup(cleanup);
@ -977,15 +973,6 @@ add_test(function() {
MobileIdentityManager.credStore = credStore;
let client = new MockClient({
verifyCodeResult: ANOTHER_PHONE_NUMBER,
discoverResult: {
verificationMethods: ["sms/mt"],
verificationDetails: {
"sms/mt": {
mtSender: "123",
url: "https://msisdn.accounts.firefox.com/v1/msisdn/sms/mt/verify"
}
}
},
registerResult: {
msisdnSessionToken: _sessionToken
}
@ -1161,15 +1148,6 @@ add_test(function() {
MobileIdentityManager.credStore = credStore;
let client = new MockClient({
verifyCodeResult: ANOTHER_PHONE_NUMBER,
discoverResult: {
verificationMethods: ["sms/mt"],
verificationDetails: {
"sms/mt": {
mtSender: "123",
url: "https://msisdn.accounts.firefox.com/v1/msisdn/sms/mt/verify"
}
}
},
registerResult: {
msisdnSessionToken: _sessionToken
}
@ -1233,3 +1211,96 @@ add_test(function() {
}
});
});
add_test(function() {
do_print("= Existing credentials - No Icc - INVALID_AUTH_TOKEN - OK =");
do_register_cleanup(cleanup);
do_test_pending();
let _sessionToken = Date.now();
let existingCredentials = {
sessionToken: _sessionToken,
msisdn: PHONE_NUMBER,
origin: ORIGIN,
deviceIccIds: null
};
let ui = new MockUi({
startFlowResult: {
phoneNumber: PHONE_NUMBER
}
});
MobileIdentityManager.ui = ui;
let credStore = new MockCredStore({
getByOriginResult: [existingCredentials, null]
});
MobileIdentityManager.credStore = credStore;
let client = new MockClient({
signError: [ERROR_INVALID_AUTH_TOKEN],
verifyCodeResult: PHONE_NUMBER,
registerResult: {
msisdnSessionToken: SESSION_TOKEN
}
});
MobileIdentityManager.client = client;
let promiseId = Date.now();
let mm = {
sendAsyncMessage: function(aMsg, aData) {
do_print("sendAsyncMessage " + aMsg + " - " + JSON.stringify(aData));
// Check result.
do_check_eq(aMsg, GET_ASSERTION_RETURN_OK);
do_check_eq(typeof aData, "object");
do_check_eq(aData.promiseId, promiseId);
// Check spied calls.
// MockCredStore.
credStore._("getByOrigin").callsLength(2);
credStore._("getByOrigin").call(1).arg(1, ORIGIN);
credStore._("getByOrigin").call(2).arg(1, ORIGIN);
credStore._("getByMsisdn").callsLength(1);
credStore._("getByMsisdn").call(1).arg(1, PHONE_NUMBER);
credStore._("add").callsLength(1);
credStore._("add").call(1).arg(1, undefined);
credStore._("add").call(1).arg(2, PHONE_NUMBER);
credStore._("add").call(1).arg(3, ORIGIN);
credStore._("add").call(1).arg(4, SESSION_TOKEN);
credStore._("add").call(1).arg(5, null);
credStore._("setDeviceIccIds").callsLength(0);
credStore._("delete").callsLength(1);
credStore._("delete").call(1).arg(1, PHONE_NUMBER);
// MockUI.
ui._("startFlow").callsLength(1);
ui._("verifyCodePrompt").callsLength(1);
ui._("verify").callsLength(1);
// MockClient.
client._("discover").callsLength(1);
client._("register").callsLength(1);
client._("smsMtVerify").callsLength(1);
client._("verifyCode").callsLength(1);
client._("sign").callsLength(1);
do_test_finished();
run_next_test();
}
};
addPermission(ORIGIN, Ci.nsIPermissionManager.ALLOW_ACTION);
MobileIdentityManager.receiveMessage({
name: GET_ASSERTION_IPC_MSG,
principal: PRINCIPAL,
target: mm,
json: {
promiseId: promiseId,
options: {}
}
});
});