You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@milagro.apache.org by sa...@apache.org on 2016/08/05 14:19:33 UTC
[06/37] incubator-milagro-mfa-js-lib git commit: Add mobile
authentication flow
Add mobile authentication flow
Project: http://git-wip-us.apache.org/repos/asf/incubator-milagro-mfa-js-lib/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-milagro-mfa-js-lib/commit/f84d8c7b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-milagro-mfa-js-lib/tree/f84d8c7b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-milagro-mfa-js-lib/diff/f84d8c7b
Branch: refs/heads/add-documentation
Commit: f84d8c7b790c79ef9be6b8aff149b04d5e663e02
Parents: f27fba9
Author: Boyan Bakov <bo...@certivox.com>
Authored: Thu Dec 10 17:17:13 2015 +0200
Committer: Vladislav Mitov <vl...@certivox.com>
Committed: Fri Dec 18 18:55:25 2015 +0200
----------------------------------------------------------------------
lib/mpin.js | 236 ++++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 174 insertions(+), 62 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-milagro-mfa-js-lib/blob/f84d8c7b/lib/mpin.js
----------------------------------------------------------------------
diff --git a/lib/mpin.js b/lib/mpin.js
index 143916b..879b461 100644
--- a/lib/mpin.js
+++ b/lib/mpin.js
@@ -8,6 +8,7 @@ var mpinjs = (function () {
Errors[4] = "IDENTITY_MISSING";
Errors[5] = "WRONG_PIN";
Errors[6] = "WRONG_FLOW";
+ Errors[7] = "TIMEOUT_FINISH";
///
Status.invalid = "INVALID";
@@ -22,6 +23,8 @@ var mpinjs = (function () {
}
this.opts = options;
+
+ this.recover();
};
Mpin.prototype.storageKey = "mpinLib";
@@ -46,11 +49,7 @@ var mpinjs = (function () {
return {code: 0, type: Errors[0]};
}
- Users[userId] = {
- userId: userId,
- deviceId: deviceId || "",
- status: Status.invalid
- };
+ this.addToUser(userId, {userId: userId, deviceId: deviceId, status: Status.invalid});
return this;
};
@@ -77,8 +76,6 @@ var mpinjs = (function () {
return cb(err, null);
}
- self.identity = data.mpinId;
-
self.addToUser(userId, {regOTT: data.regOTT, mpinId: data.mpinId, status: Status.start});
//force activate
@@ -90,7 +87,6 @@ var mpinjs = (function () {
});
};
-
//request cs1 + cs2
Mpin.prototype.confirmRegistration = function (userId, cb) {
var _cs1Url = "", self = this, _userStatus;
@@ -100,7 +96,7 @@ var mpinjs = (function () {
} else if (!this.checkUser(userId)) {
return cb({code: 1, type: Errors[1]}, null);
} else if (!this.opts.signatureURL) {
- return cb({code: 2, type: Errors[2], message: "Missing signatureURL"}, null);
+ return cb({code: 2, type: Errors[2], message: "Missing signatureURL option."}, null);
}
//started || activated
@@ -109,7 +105,12 @@ var mpinjs = (function () {
return cb({code: 3, type: Errors[3]}, null);
}
- _cs1Url = this.generateUrl('signature', userId);
+ //already set.
+ if (Users[userId].csHex) {
+ return cb(null, true);
+ }
+
+ _cs1Url = this.generateUrl('signature', {userId: userId});
//req cs1
this.request({url: _cs1Url}, function (err, cs1Data) {
var _cs2Url = "";
@@ -156,7 +157,7 @@ var mpinjs = (function () {
tokenHex = MPINAuth.calculateMPinToken(Users[userId].mpinId, pin, Users[userId].csHex);
this.addToUser(userId, {tokenHex: tokenHex, status: Status.register});
- return tokenHex;
+ return true;
};
//Put user / mpinId
@@ -168,11 +169,26 @@ var mpinjs = (function () {
Mpin.prototype.startAuthentication = function (userId, cb) {
- var _tp1Url, self = this;
+ var _tp1Url, self = this, _userStatus;
+
+ if (!userId || typeof userId !== "string") {
+ return cb ? cb({code: 0, type: Errors[0]}, null) : {error: 0, type: Errors[0]};
+ } else if (!this.checkUser(userId)) {
+ return cb({code: 1, type: Errors[1]}, null);
+ } else if (!this.opts.timePermitsURL || !this.opts.certivoxURL) {
+ return cb({code: 2, type: Errors[2], message: "Missing timePermitsURL or/and certivoxURL option."}, null);
+ }
+
+ //registered
+ _userStatus = this.getUser(userId, "status");
+ if (_userStatus !== Status.register) {
+ return cb({code: 3, type: Errors[3]}, null);
+ }
+ //checkUser
_tp1Url = this.generateUrl('permit1');
this.request({url: _tp1Url}, function (err, data) {
- var _signature, _tp2Url, _timePermit1;
+ var _signature, _tp2Url, _timePermit1, _storageUrl;
_signature = data["signature"];
_timePermit1 = data["timePermit"];
@@ -181,20 +197,51 @@ var mpinjs = (function () {
_tp2Url = self.generateUrl('permit2');
_tp2Url += "&signature=" + _signature;
-
- self.request({url: _tp2Url}, function (err2, data2) {
- var _timePermit2, timePermitHex;
- _timePermit2 = data2["timePermit"];
- timePermitHex = MPINAuth.addShares(_timePermit1, _timePermit2);
+ //check cache if exist
+ if (Users[userId].timePermitCache && Users[userId].timePermitCache.date === data.date) {
+ var _timePermit2 = Users[userId].timePermitCache.timePermit;
+ var timePermitHex = MPINAuth.addShares(_timePermit1, _timePermit2);
self.addToUser(userId, {timePermitHex: timePermitHex});
+ cb && cb(null, true); //exit with cache permit2
+ return;
+ } else {
+ _storageUrl = self.generateUrl("storage", {date: data.date, storageId: data.storageId});
+
+ self.request({url: _storageUrl}, function (storErr, storData) {
+ if (storErr) {
+ self._getTimePermit2({userId: userId, permit1: _timePermit1, permit2Url: _tp2Url, date: data.date}, cb); //continue
+ return;
+ }
- cb && cb(null, true);
- });
+ var _timePermit2 = storData;
+ var timePermitHex = MPINAuth.addShares(_timePermit1, _timePermit2);
+
+ self.addToUser(userId, {timePermitHex: timePermitHex, timePermitCache: {date: data.date, timePermit: _timePermit2}});
+
+ cb && cb(null, true); //exit with storage permit2
+ }, false);
+ }
+ });
+ };
+ Mpin.prototype._getTimePermit2 = function (options, cb) {
+ var self = this, _timePermit1 = options.permit1;
+ this.request({url: options.permit2Url}, function (err2, data2) {
+ var _timePermit2, timePermitHex, _permitCache = {};
+ _timePermit2 = data2["timePermit"];
+ timePermitHex = MPINAuth.addShares(_timePermit1, _timePermit2);
+
+ _permitCache.date = options.date;
+ _permitCache.timePermit = data2["timePermit"];
+
+ self.addToUser(options.userId, {timePermitHex: timePermitHex, timePermitCache: _permitCache});
+
+ cb && cb(null, true);
});
};
+
Mpin.prototype.finishAuthentication = function (userId, aPin, cb) {
var self = this, _reqData = {};
@@ -230,7 +277,7 @@ var mpinjs = (function () {
}
}
- console.log("auth Data :::", authData);
+ cb && cb(null, true);
});
});
});
@@ -239,7 +286,7 @@ var mpinjs = (function () {
Mpin.prototype.getAuthData = function (userId, aPin) {
var _auth = {};
- _auth.mpin = this.identity;
+ _auth.mpin = this.getIdentity();
_auth.token = Users[userId].tokenHex;
_auth.timePermit = Users[userId].timePermitHex;
_auth.date = Users[userId].currentDate;
@@ -273,56 +320,54 @@ var mpinjs = (function () {
if (err) {
return cb(err, null);
}
- console.log("OTT :::", data.webOTT);
self.webOTT = data.webOTT;
- cb(null, {accessNumber: data.accessNumber});
+ cb && cb(null, {accessNumber: data.accessNumber});
});
};
- Mpin.prototype.getAccess = function (cb) {
+ Mpin.prototype.waitForMobileAuth = function (timeoutSeconds, cb) {
var self = this, _reqData = {};
-
if (!this.webOTT) {
return cb({code: 6, type: Errors[6], message: "Need to call getAccessNumber method before this."}, null);
+ } else if (!timeoutPeriod) {
+ return cb({code: 2, type: Errors[2], message: "Missing timeout/expiration period(in seconds)."}, null);
}
+
+
+ this.timeoutPeriod || (this.timeoutPeriod = timeoutSeconds * 1000);
+
_reqData.url = this.generateUrl("getaccess");
_reqData.type = "POST";
_reqData.data = {webOTT: this.webOTT};
this.request(_reqData, function (err, data) {
if (err) {
- if (err.status === 401) {
+ if (err.status === 401 && self.timeoutPeriod > 0) {
+ self.timeoutPeriod -= 3000;
self.intervalID2 = setTimeout(function () {
- self.getAccess.call(self, cb);
+ self.waitForMobileAuth.call(self, timeoutSeconds, cb);
}, 3000);
return;
+ } else if (self.timeoutPeriod <= 0) {
+ cb && cb({code: 7, type: Errors[7]}, null);
+ return;
}
}
- /*
- * self.intervalID2 = setTimeout(function () {
- self.getAccess.call(self);
- }, 3000);
- *
- */
- console.log("data :::", err, data);
-
- cb(null, true);
-
-
+ cb && cb(null, true);
});
};
- Mpin.prototype.stopAccess = function () {
+ Mpin.prototype.cancelMobileAuth = function () {
if (this.intervalID2) {
clearInterval(this.intervalID2);
}
};
- Mpin.prototype.generateUrl = function (type, userId) {
+ Mpin.prototype.generateUrl = function (type, options) {
var url, mpData, mpin_id_bytes, hash_mpin_id_bytes = [], hash_mpin_id_hex;
switch (type) {
@@ -331,15 +376,15 @@ var mpinjs = (function () {
break;
case "signature":
url = this.opts.signatureURL + "/";
- url += Users[userId].mpinId;
- url += "?regOTT=" + Users[userId].regOTT;
+ url += Users[options.userId].mpinId;
+ url += "?regOTT=" + Users[options.userId].regOTT;
break;
case "permit1":
url = this.opts.timePermitsURL + "/";
- url += this.identity;
+ url += this.getIdentity();
break;
case "permit2":
- mpData = this.fromHex(this.identity);
+ mpData = this.fromHex(this.getIdentity());
mpin_id_bytes = MPIN.stringtobytes(mpData);
hash_mpin_id_bytes = MPIN.HASH_ID(mpin_id_bytes);
hash_mpin_id_hex = MPIN.bytestostring(hash_mpin_id_bytes);
@@ -363,19 +408,23 @@ var mpinjs = (function () {
case "getaccess":
url = this.opts.accessNumberURL;
break;
+ case "storage":
+ url = this.opts.timePermitsStorageURL + "/" + this.opts.appID + "/";
+ url += options.date + "/" + options.storageId;
+ //return that.opts.timePermitsStorageURL + "/" + that.opts.appID + "/" + date + "/" + storageId;
+ break;
}
return url;
};
-
Mpin.prototype.listUsers = function () {
var listUsers = {};
for (var uKey in Users) {
listUsers[uKey] = {
userId: Users[uKey].userId,
- deviceId: Users[uKey].deviceId,
- status: Users[uKey].status
+ deviceId: Users[uKey].deviceId || "",
+ status: Users[uKey].status || ""
};
}
return listUsers;
@@ -395,7 +444,7 @@ var mpinjs = (function () {
_user = {
userId: Users[userId].userId,
- deviceId: Users[userId].deviceId,
+ deviceId: Users[userId].deviceId || "",
status: Users[userId].status
};
@@ -406,16 +455,30 @@ var mpinjs = (function () {
}
};
- Mpin.prototype.addToUser = function (userId, userProps) {
- if (!this.checkUser(userId)) {
+ //remove this
+ Mpin.prototype.getUsers = function () {
+ return Users;
+ };
+
+ Mpin.prototype.addToUser = function (userId, userProps, skipSave) {
+ var _save;
+ if (!this.checkUser(userId) && !userProps.userId) {
return false;
}
+ _save = !skipSave;
+
+ //create
+ if (userProps.userId) {
+ Users[userId] = {};
+ }
for (var uKey in userProps) {
- Users[userId][uKey] = userProps[uKey];
+ if (userProps[uKey]) {
+ Users[userId][uKey] = userProps[uKey];
+ }
}
- this.setData(userId, userProps);
+ _save && this.setData(userId, userProps);
};
Mpin.prototype.restore = function () {
@@ -423,8 +486,7 @@ var mpinjs = (function () {
};
Mpin.prototype.setData = function (userId, upData) {
- var mpinData;
- mpinData = JSON.parse(localStorage.getItem(this.storageKey));
+ var mpinData = this.getData();
if (!mpinData) {
mpinData = {
@@ -454,33 +516,83 @@ var mpinjs = (function () {
mpinData.accounts[mpinId].token = upData.tokenHex;
}
+ if (upData.status && Users[userId].mpinId) {
+ var mpinId = Users[userId].mpinId;
+ mpinData.accounts[mpinId].status = upData.status;
+ }
+
+ //cache cache
+ if (upData.timePermitCache) {
+ var mpinId = Users[userId].mpinId;
+ mpinData.accounts[mpinId].timePermitCache = upData.timePermitCache;
+ }
+
localStorage.setItem(this.storageKey, JSON.stringify(mpinData));
};
+ Mpin.prototype.getIdentity = function () {
+ var mpinData = this.getData();
+ return mpinData.defaultIdentity;
+ };
+
+ Mpin.prototype.recover = function () {
+ var userId, userData = {}, mpinData = this.getData();
+
+ if (mpinData && "accounts" in mpinData) {
+ for (var mpinId in mpinData.accounts) {
+ userId = (JSON.parse(this.fromHex(mpinId))).userID;
+
+ userData = {};
+ userData.userId = userId;
+ userData.mpinId = mpinId;
+
+ mpinData.accounts[mpinId].regOTT && (userData.regOTT = mpinData.accounts[mpinId].regOTT);
+ mpinData.accounts[mpinId].token && (userData.token = mpinData.accounts[mpinId].token);
+ mpinData.accounts[mpinId].MPinPermit && (userData.MPinPermit = mpinData.accounts[mpinId].MPinPermit);
+ mpinData.accounts[mpinId].timePermitCache && (userData.timePermitCache = mpinData.accounts[mpinId].timePermitCache);
+
+ mpinData.accounts[mpinId].status && (userData.status = mpinData.accounts[mpinId].status);
+
+ //call add To user & skip Save
+ this.addToUser(userId, userData, true);
+ }
+ }
+ };
+
Mpin.prototype.getData = function () {
var mpinData;
- mpinData = JSON.parse(localStorage.getItem(this.storageKey));
+ mpinData = localStorage.getItem(this.storageKey);
+ mpinData = JSON.parse(mpinData);
return mpinData;
};
//{url: url, type: "get post put", data: data}
- Mpin.prototype.request = function (options, cb) {
- var _request = new XMLHttpRequest(), _url, _type, _data;
+ Mpin.prototype.request = function (options, cb, jsonResponse) {
+ var _request = new XMLHttpRequest(), _url, _type, _parseJson;
_url = options.url || "";
_type = options.type || "GET";
- _data = options.data || "";
+
+ _parseJson = jsonResponse || true;
_request.onreadystatechange = function () {
if (_request.readyState === 4 && _request.status === 200) {
- cb(null, JSON.parse(_request.responseText));
+ if (_parseJson) {
+ cb(null, JSON.parse(_request.responseText));
+ } else {
+ cb(null, _request.responseText);
+ }
} else if (_request.readyState === 4) {
cb({status: _request.status}, null);
}
};
_request.open(_type, _url, true);
- _request.setRequestHeader("Content-Type", "application/json");
- _request.send(JSON.stringify(_data || ""));
+ if (options.data) {
+ _request.setRequestHeader("Content-Type", "application/json");
+ _request.send(JSON.stringify(options.data));
+ } else {
+ _request.send();
+ }
};
return Mpin;