var url = null; //xyz servlet
var app_name = '';
var initialized = 0;
var debug = false; //don't submit login just show if it works or not
var XYZ = true; //use XYZ or fail to old authentication
var submit_form = false;
var acct_id = null;
var user_name = null;
var complete_authentication = false;
var complete_confirm_token = false;
var is_two_factor_user = false;
//pteng used to identify the user as second factor. used by WT to redirect to login on disconnect
var twoFactorUser = false;
var suppLongPwd = false;
var userSfTypes = [];
var selectedSF =null;
//default to 512 bit value
var N = parseBigInt("d4c7f8a2b32c11b8fba9581ec4ba4f1b04215642ef7355e37c0fc0443ef756ea2c6b8eeb755a1c723027663caa265ef785b8ff6a9b35227a52d86633dbdfca43",16);
var g = parseBigInt("2",10);
var a = null;
var A = null;
var B = null;
var k = null;
var x = null;
var u = null;
var K = null;
var M = 0;
var M2 = null;
var salt = null;
var rng = null;
var Sc = null;
var one;
var two;
var three;
var radix = 16;
var proto = "6"; // 3 or 6 or 6a
var hash = "SHA1";
var startTime = null; //measure time of execution start
var endTime = null; //measure time of execution end
var INITIATED = "INITIATED"; //starting authentication submitting username
var INITIALIZED = "INITIALIZED"; //username submitted
var INPROCESS = "INPROCESS"; //submitted M1
var AUTHENTICATED = "AUTHENTICATED"; //allok
var FAILEDAUTH = "FAILEDAUTH"; //failed
var STATE = null;
var NULL=null; //<-- added
var twoFactType = null; //what type of two factor is used
var towFactChlg = null;
var submit_enckx = false;
//PHONE AUTH VARIABLES
//3 minutes
//var PHONE_AUTH_POLLING_TIMEOUT = 180000;
var PUSH_AUTH_MAX_ATTEMPTS = 36; //36*5s = 180s=3min
var PUSH_AUTH_ATTEMPTS = 0;
//5 seconds
var PUSH_CHECK_AUTH_INTERVAL = 5000
//POLLING URL
var PUSH_AUTH_POLLING_URL ='';
var PUSH_AUTH_STATE ='INVALID';
var PUSH_AUTH_INSTRUCTIONS = 'A message has been sent to your phone. Tap the link to complete secondary authentication.
';
var PUSH_AUTH_ALT_LINK = 'Click here if you did not receive the message.';
var PUSH_TIMEOUT_MSG = 'Two Factor Authentication Timed out.';
var pushTimeout;
var VERSION = 0;
//Local storage key
var SELECTED_SF_KEY="SELECTED_SF";
//URL param to reset LS
var RESET_KEY="resetSF";
//SF types
var SSC = "3";
var IBKEY_ANDROID = "5.2a";
var IBKEY_IOS = "5.2i";
var BANK_KEY = "5.3";
var DSC = "4.1";
var ALPINE = "4";
var DSC_PLUS = "5.1";
var PLAT_GOLD = "5";
var TSC = "6";
var SMS = "4.2";
var SF_NAMES ={};
SF_NAMES[SSC] = "Security Code Card";
SF_NAMES[IBKEY_ANDROID] = "IB Key";
SF_NAMES[IBKEY_IOS] = "IB Key";
SF_NAMES[BANK_KEY] = "Bank Key";
SF_NAMES[DSC] = "Digital Security Card";
SF_NAMES[ALPINE] = "Alpine Device";
SF_NAMES[DSC_PLUS] = "Digital Security Card+";
SF_NAMES[PLAT_GOLD] = "Platinum/Gold";
SF_NAMES[TSC] = "Temporary Security Code";
SF_NAMES[SMS] ="One Time Passcode"
var tempServerS2="";
window.IBSSO = window.IBSSO || {};
IBSSO.MESSAGES = IBSSO.MESSAGES || {};
IBSSO.CONSTANT = IBSSO.CONSTANT || {};
IBSSO.MESSAGES.LIVE_ACCOUNT_WITH_PAPER_TRADING = "You have selected the Live Account Mode, but the specified user is a Paper Trading user. Please select the correct Login mode.";
IBSSO.isPaper = IBSSO.isPaper || {};
IBSSO.CONSTANT.LOGIN_TYPE_PROD = 1;
IBSSO.CONSTANT.LOGIN_TYPE_PAPER = 2;
IBSSO.CONSTANT.SECOND_FACTOR_TYPE_OTP = "4.2";
IBSSO.CONSTANT.OTP_DELIVERY_TYPE_SMS = 1;
IBSSO.CONSTANT.OTP_DELIVERY_TYPE_VOICE = 2;
IBSSO.CONSTANT.OTP_DELIVERY_TYPE_EMAIL = 4;
IBSSO.otpSelectTimer = null;
IBSSO.otpSelectTimerTimeout = 60 * 1000; //60sec
var loadingCallback = function(){
//Quick check for url parameter to reset local store
var resetSF = getParam(RESET_KEY);
if(resetSF && resetSF=="true"){
try {
localStorage.setItem(SELECTED_SF_KEY, "");
} catch(e) {}
}
if(typeof SF_VERSION != "undefined" && SF_VERSION){
VERSION = SF_VERSION;
}
};
var specialPushAuthRequest;
var specialCompleteAuth_1;
if(document.readyState ==="complete"||(document.readySate !=="loading" && !document.documentElement.doScroll)){
loadingCallback();
}else{
document.addEventListener("DOMContentLoaded",loadingCallback);
}
//ibkey recovery variables
var MODE_NORMAL = "NORMAL";
var MODE_IBKEY_RECOVERY = "IBKEY_RECOVERY";
var MODE = MODE_NORMAL;
function isync_radix() {
radix = 16;
}
function isync_proto() {
proto = "6";
}
function parseBigInt(str,r) {
return new BigInteger(str,r);
}
function bigInt2radix(bi, radix){
return bi.toString(radix);
}
function randomBigInt(bytes) {
if(rng == null) {
rng = new SecureRandom();
}
return new BigInteger(8 * bytes, rng);
}
function str2BigInt(str) {
return parseBigInt(str, radix);
}
function bigInt2Str(bi) {
return bigInt2radix(bi, radix);
}
/* Returns a string with n zeroes in it */
function nzero(n) {
if(n < 1) {
return "";
}
var t = nzero(n >> 1);
if((n & 1) == 0) {
return t + t;
}
else {
return t + t + "0";
}
}
function set_random_a() {
a = randomBigInt(32);
if(a.compareTo(N) >= 0) {
a = a.mod(N.subtract(one));
}
if(a.compareTo(two) < 0) {
a = two;
}
//for tests keep it static
// a = parseBigInt("222444666",16);
}
function randomize_a() {
set_random_a();
recalc_A();
}
function recalc_A() {
A = g.modPow(a, N);
}
function recalc_k() {
k = xyz_compute_k(N, g);
}
function recalc_K() {
// writeDebug("recalc_K Sc = "+bigInt2radix(Sc,16));
K = xyz_compute_K(Sc);
// writeDebug("recalc_K K = "+K);
}
function recalc_M(){
M = xyz_compute_M1(N, g,user_name, salt, A, B, K);
// writeDebug("recalc_M M = "+M);
}
function recalc_M2(){
M2 = xyz_compute_M2(A,M,K);
}
function recalc_x() {
// writeDebug("recalc_x user = "+getUserName());
// writeDebug("recalc_x pass = "+getPassword());
// writeDebug("recalc_x salt = "+bigInt2radix(salt,16));
x = xyz_compute_x(getUserName(), getPassword(), salt);
// writeDebug("recalc_x x = "+bigInt2radix(x ,16));
}
function recalc_Sc() {
// writeDebug("recalc_Sc B = "+bigInt2radix(B, 16));
// writeDebug("recalc_Sc x = "+bigInt2radix(x, 16));
// writeDebug("recalc_Sc u = "+bigInt2radix(u, 16));
// writeDebug("recalc_Sc a = "+bigInt2radix(a, 16));
// writeDebug("recalc_Sc k = "+bigInt2radix(k, 16));
Sc = xyz_compute_client_S(B, x, u, a, k);
// writeDebug("recalc_Sc Sc = "+bigInt2radix(Sc, 16));
}
function recalc_u() {
// writeDebug("recalc_u N = "+bigInt2radix(N,16));
// writeDebug("recalc_u A = "+bigInt2radix(A, 16));
// writeDebug("recalc_u B = "+bigInt2radix(B, 16));
u = xyz_compute_u(N, A, B);
// writeDebug("recalc_u u = "+u);
}
function recalc_v(){
// writeDebug("recalc_v g = "+g);
// writeDebug("recalc_v x = "+x);
var v = xyz_compute_v(g,x);
// writeDebug("recalc_v v = "+v);
}
/* S = (B - kg^x) ^ (a + ux) (mod N) */
function xyz_compute_client_S(BB, xx, uu, aa, kk) {
var bx = g.modPow(xx, N);
var btmp = BB.add(N.multiply(kk)).subtract(bx.multiply(kk)).mod(N);
return btmp.modPow(xx.multiply(uu).add(aa), N);
}
function xyz_compute_k(NN, gg) {
var hashin = "";
var nhex;
var ghex;
var ktmp;
if(proto == "3")
return one;
else if(proto == "6")
return three;
else {
/* XYZ-6a: k = H(N || g) */
nhex = String(bigInt2radix(NN, 16));
if((nhex.length & 1) == 0) {
hashin += nhex;
}
else {
hashin += "0" + nhex;
}
ghex = String(bigInt2radix(gg, 16));
hashin += nzero(nhex.length - ghex.length);
hashin += ghex;
ktmp = parseBigInt(calcSHA1Hex(hashin), 16);
if(ktmp.compareTo(NN) < 0) {
return ktmp;
}
else {
return ktmp.mod(NN);
}
}
}
/* x = H(salt || H(username || ":" || password)) */
function xyz_compute_x(u, p, s) {
// Inner hash: SHA-1(username || ":" || password)
var ih = calcSHA1(u + ":" + p);
// Outer hash: SHA-1(salt || inner_hash)
// This assumes that the hex salt string has an even number of characters...
//original
//var oh = calcSHA1Hex(bigInt2radix(s, 16) + ih);
//this makes sure that hex salt string has an even number of characters, kt ...
var oh = calcSHA1Hex(verifyHexVal(s) + ih);
var xtmp = parseBigInt(oh, 16);
if(xtmp.compareTo(N) < 0) {
return xtmp;
}
else {
return xtmp.mod(N.subtract(one));
}
}
/*
* XYZ-3: u = first 32 bits (MSB) of SHA-1(B)
* XYZ-6(a): u = SHA-1(A || B)
*/
function xyz_compute_u(Nv, av, bv) {
var ahex;
var bhex = String(bigInt2radix(bv, 16));
var hashin = "";
var utmp;
var nlen;
if(proto != "3") {
ahex = String(bigInt2radix(av, 16));
if(proto == "6") {
if((ahex.length & 1) == 0) {
hashin += ahex;
}
else {
hashin += "0" + ahex;
}
}
else { /* 6a requires left-padding */
nlen = 2 * ((Nv.bitLength() + 7) >> 3);
hashin += nzero(nlen - ahex.length) + ahex;
}
}
if(proto == "3" || proto == "6") {
if((bhex.length & 1) == 0) {
hashin += bhex;
}
else {
hashin += "0" + bhex;
}
}
else { /* 6a requires left-padding; nlen already set above */
hashin += nzero(nlen - bhex.length) + bhex;
}
if(proto == "3") {
utmp = parseBigInt(calcSHA1Hex(hashin).substr(0, 8), 16);
}
else {
utmp = parseBigInt(calcSHA1Hex(hashin), 16);
}
if(utmp.compareTo(Nv) < 0) {
return utmp;
}
else {
return utmp.mod(Nv.subtract(one));
}
}
/* K = H(S) */
function xyz_compute_K(SS) {
var tmpk = calcSHA1Hex(verifyHexVal(SS));
// writeDebug("xyz_compute_K K = "+tmpk);
return tmpk;
}
// M = H(A,B,K) */
function xyz_compute_M_old(AI,BI,KI) {
var hashin ="";
hashin += String(bigInt2radix(verifyHexVal(AI), 16));
hashin += String(bigInt2radix(verifyHexVal(BI), 16));
hashin += String(bigInt2radix(verifyHexVal(KI), 16));
return calcSHA1Hex(hashin);
}
// M1 = H( H(N) xor H(g), H(I), s, A,B,K) */
function xyz_compute_M1(NI, gI, uI, sI, AI,BI,KI) {
var hashin ="";
// writeDebug("xyz_compute_M1 N: "+NI);
var h_n = calcSHA1Hex(bigInt2radix(verifyHexVal(NI), 16));
// writeDebug("xyz_compute_M1 h_n: "+h_n);
// writeDebug("xyz_compute_M1 g: "+gI);
var h_g = calcSHA1Hex(bigInt2radix(verifyHexVal(gI), 16));
// writeDebug("xyz_compute_M1 h_g: "+h_g);
h_n = parseBigInt(verifyHexVal(h_n), 16);
h_g = parseBigInt(verifyHexVal(h_g), 16);
var h_xor = verifyHexVal(bigInt2radix(h_n.xor(h_g),16));
// writeDebug("xyz_compute_M1 xor: "+h_xor);
// writeDebug("xyz_compute_M1 username: "+uI);
var h_I = calcSHA1(uI);
// writeDebug("xyz_compute_M1 h_I: "+h_I);
var shex = verifyHexVal(sI);
// writeDebug("xyz_compute_M1 s_hex: "+shex);
// writeDebug("xyz_compute_M1 AI : "+bigInt2radix(verifyHexVal(AI), 16));
// writeDebug("xyz_compute_M1 BI : "+bigInt2radix(verifyHexVal(BI), 16));
// writeDebug("xyz_compute_M1 KI : "+bigInt2radix(verifyHexVal(KI), 16));
hashin += h_xor;
hashin += h_I;
hashin += shex;
hashin += String(bigInt2radix(verifyHexVal(AI), 16));
hashin += String(bigInt2radix(verifyHexVal(BI), 16));
hashin += String(bigInt2radix(verifyHexVal(KI), 16));
// writeDebug("xyz_compute_M1 hashin= "+hashin);
return verifyHexVal(calcSHA1Hex(hashin));
}
function xyz_compute_M2(AI,MI,KI) {
//alert("A: "+AI+"\nMI: "+MI+"\nKI: "+KI);
var hashin ="";
hashin += String(bigInt2radix(verifyHexVal(AI), 16));
hashin += String(bigInt2radix(verifyHexVal(MI), 16));
hashin += String(bigInt2radix(verifyHexVal(KI), 16));
return calcSHA1Hex(hashin);
}
/* v = g^x */
function xyz_compute_v(gi, xi) {
return gi.modPow(xi, N);
}
/* this makes sure it is even number */
function verifyHexVal(HV){
var hashin ="";
var bhex = String(bigInt2radix(HV, 16));
if((bhex.length & 1) == 0) {
hashin += bhex;
}
else {
hashin += "0" + bhex;
}
//20061106
if(hashin.charAt(0) == "0" && hashin.charAt(1) == "0"){
hashin = hashin.substring(2,hashin.length);
}
return hashin;
}
function set_radix(r) {
radix = r;
}
function set_proto(p) {
proto = p;
recalc_k();
}
//read url params
function getParam(param){
var location = window.location.search;
var parArr = location.split('?').length==2 ? location.split('?')[1].split("&"): [];
for(var i=0;i 0)
{
return;
}
one = parseBigInt("1", 16);
two = parseBigInt("2", 16);
three = parseBigInt("3", 16);
randomize_a();
initialized = 1;
}
var userNameFocused = false;
var passwordFocused = false;
var forceUserNameFocused = false;
var forcePasswordFocused = false;
var userNameEnterPressed = false;
function focusElsewhereFirst() {
document.getElementById("submitForm").focus();//<-- As a work around to deal with hidden focus problem
}
function focusUserName() {
if(!userNameFocused && !forcePasswordFocused) {
writeDebug("##focusUserName");
document.getElementById(user_field_id).focus();
userNameFocused = true;
passwordFocused = false;
}
}
function focusPassword() {
if(!passwordFocused && !forceUserNameFocused) {
writeDebug("##focusPassword");
document.getElementById(pass_field_id).focus();
passwordFocused = true;
userNameFocused = false;
}
}
function forceFocusUserName() {
writeDebug("##forceFocusUserName: "+STATE);
showErrorMessage(error_field_id,"");
forceUserNameFocused = true;
forcePasswordFocused = false;
document.getElementById(user_field_id).focus();
}
function forceFocusPassword() {
writeDebug("##forceFocusPassword: "+STATE);
showErrorMessage(error_field_id,"");
forceUserNameFocused = false;
forcePasswordFocused = true;
document.getElementById(pass_field_id).focus();
}
function enableUserNameSubmit(){
writeDebug("enableUserNameSubmit: "+STATE);
document.getElementById("submitForm").disabled=false;
return true;
}
function handleUserNameEvent(evt){
evt = (evt)?evt : event;
var charCode = (evt.charCode)? evt.charCode : ((evt.which) ?evt.which:evt.keyCode);
if(charCode == 13 || charCode == 3){
writeDebug("*** username enter pressed "+charCode);
userNameEnterPressed = true;
complete_authentication = false;
passwordFocused = false;
forceUserNameFocused = false;
focusPassword();
}
return false;
}
function initAuthentication(in_user_id, in_error_id){
writeDebug("initAuthentication: "+STATE);
//initAuthentication() requires xyz_initialize() to have completed successfully
if(initialized === 0){
writeDebug("Warning: initAuthentication() called before xyz_initialize(). Calling xyz_initialize() now.");
xyz_initialize();
}
setUserFieldId(in_user_id);
setErrorFieldId(in_error_id);
if(user_name != null && user_name != getUserName()){
writeDebug("user_name != getUserName: "+STATE);
STATE = null;
XYZ = true;
}
else if(user_name != null && user_name == getUserName() && STATE != FAILEDAUTH){
writeDebug("user_name == getUserName: "+STATE);
return false;
}
//alert("initAuthentication");
user_name = getUserName();
acct_id = getAcctId();
force_login=getForceLogin();
if(user_name == null || user_name == ""){
//showErrorMessage(error_field_id,"Enter username");
return false;
}
else{
//showErrorMessage(error_field_id,"");
}
if(STATE == INITIATED){
return false;
}
writeDebug("initAuthentication 2 : "+STATE);
STATE = INITIATED;
var login_type = getLoginType();
var params = "ACTION=INIT&APP_NAME="+app_name+"&MODE="+MODE+"&FORCE_LOGIN="+force_login+"&USER="+user_name+"&ACCT="+ acct_id + "&A="+bigInt2Str(A);
if (login_type) {
params += "&LOGIN_TYPE=" + login_type;
}
var loader = new xhr.ContentLoader("POST", url, true, initHandler, params);
}
function processError(root, from){
if(root !=null && root.getElementsByTagName("error") !=null && root.getElementsByTagName("error").length>0){
var message = root.getElementsByTagName("error")[0].firstChild.nodeValue;
//send separately link that has 'LINK_S' and 'LINK_E'
if(root.getElementsByTagName("link").length>0){
var url = root.getElementsByTagName("link")[0].firstChild.nodeValue;
message = message.replace("LINK_E","");
message = message.replace("LINK_S","");
}
if(message == "unknown"){
if(getPassword().length > 0){
showErrorMessage(error_field_id,"Invalid username password combination");
clearUserName();
clearPassword();
usernameFocus();
}
}
else if (from === "initHandler" && message === "Invalid username password combination") {
writeDebug("processError - Do not display error message with empty password");
// Do not display this error message if password field is empty
// see https://prod.ibkr-web.com/ibjira/browse/IGAME-1244
}
else{
showErrorMessage(error_field_id,message);
}
STATE = null;
return true;
}
return false;
}
function initHandler(){
writeDebug("initHandler : "+STATE);
if (!this.req || !this.req.responseXML) {
return false;
}
var root = this.req.responseXML.documentElement;
if(processError(root, "initHandler")){
return false;
}
else if(this.req.responseText.indexOf("RESPONSEPENDING")!=-1){
return false;
}
var default_param = true;
if (!root.getElementsByTagName("user") || !root.getElementsByTagName("user")[0]) {
return false;
}
var user = root.getElementsByTagName("user")[0].firstChild.nodeValue;
if(user != "true"){
//in transitional period switch to use old type authentication
XYZ = false;
var isloginform = xyz_form_id == "loginform";
if(!isloginform){
showErrorMessage(error_field_id,"Invalid username password combination");
return false;
}
else{
return true;
}
}
try {
if (root.getElementsByTagName("paper").length > 0) {
var paper = root.getElementsByTagName("paper")[0].firstChild.nodeValue;
var user = getUserName();
if (user && paper) {
// save isPaper state for username
IBSSO.isPaper[user] = (paper === "true");
}
}
} catch(e) {}
var newg = root.getElementsByTagName("g")[0].firstChild.nodeValue;
var newN = root.getElementsByTagName("N")[0].firstChild.nodeValue;
proto = root.getElementsByTagName("proto")[0].firstChild.nodeValue;
hash = root.getElementsByTagName("hash")[0].firstChild.nodeValue;
salt = parseBigInt(root.getElementsByTagName("s")[0].firstChild.nodeValue,16);
B = parseBigInt(root.getElementsByTagName("B")[0].firstChild.nodeValue,16);
try{
suppLongPwd = ("true" === root.getElementsByTagName("lp")[0].firstChild.nodeValue);
}catch(err){suppLongPwd = false;}//default not provided
if(root.getElementsByTagName("rsapub")!=null && root.getElementsByTagName("rsapub").length > 0 && root.getElementsByTagName("rsapub")[0].firstChild !=null){
submit_enckx = true;
rsa = new RSAKey();
rsa.setPublic(root.getElementsByTagName("rsapub")[0].firstChild.nodeValue,'3');
}
if(root.getElementsByTagName("info")!=null && root.getElementsByTagName("info").length > 0 && root.getElementsByTagName("info")[0].firstChild !=null){
var message = root.getElementsByTagName("info")[0].firstChild.nodeValue;
showErrorMessage(error_field_id,message);
}
if(!g.equals(parseBigInt(newg,10))){
default_param = false;
g = parseBigInt(newg,10);
}
if(!N.equals(parseBigInt(newN,16))){
default_param = false;
N = parseBigInt(newN,16);
}
if(!default_param){
STATE = NULL;
initAuthentication();
return false;
}
recalc_k();
STATE = INITIALIZED;
writeDebug("initHandler complete_authentication: "+complete_authentication+" STATE: "+STATE);
if(complete_authentication){
writeDebug("** completeAuthentication invoked from initHandler");
completeAuthentication();
} else {
if(!bypass_empty_field) {
writeDebug("initHandler focusPassword");
focusPassword();
}
}
}
function completeAuthentication(in_passw_id, in_error_id){
if(!bypass_empty_field) {
if(!complete_authentication) {
return false;
}
}
writeDebug("completeAuthentication: "+STATE);
setPasswFieldId(in_passw_id);
setErrorFieldId(in_error_id);
var counter = 0;
//here logic is like this if it is not INITIALIZED it is probobly due to 2 reasons:
// 1. server has not responded (when it will respond complete auth.
// 2. STATE == null - in this case run init and the whole authentication from beginning.
if(!XYZ){return true;} //this user doesn't have XYZ use old authentication
if(STATE == null || STATE == FAILEDAUTH){
//(STATE !=INITIATED && STATE != INITIALIZED && STATE != INPROCESS && STATE != AUTHENTICATED )){
complete_authentication = false;
initAuthentication();//do the whole thing;
return false;
}
if(STATE == INITIATED){ //this if submit form is entered and server hasn't come back with xyz params
complete_authentication = true;
return false;
}
if(STATE == INPROCESS){
//there is already thread running wait till it finishes
return false;
}
if(!bypass_empty_field) {
if(getPassword() == null || getPassword() == ""){
showErrorMessage(error_field_id,"Please enter password");
writeDebug("password focus: "+STATE);
focusPassword()
return false;
}
}
STATE = INPROCESS;
showErrorMessage(error_field_id,"");
recalc_x();
recalc_u();
recalc_Sc();
recalc_K();
recalc_M();
var login_type = getLoginType();
var params ="ACTION=COMPLETEAUTH&APP_NAME="+app_name+"&USER="+user_name+"&ACCT="+ acct_id + "&M1="+M+"&VERSION="+VERSION;
if (login_type) {
params += "&LOGIN_TYPE=" + login_type;
}
if(submit_enckx){
var ekx = do_encrypt(K);
writeDebug("EKX: "+ekx);
params +="&EKX="+ekx;
}
if(VERSION == 1){
var loader = new xhr.ContentLoader("POST", url,true, completeAuthenticationHandlerV2,params);
}else{
var loader = new xhr.ContentLoader("POST", url,true, completeAuthenticationHandler,params);
}
return false;
}
//second auth step. completeAuthentication() must have been sent previously to generate variables
function completeAuthentication_1(){
if(typeof specialCompleteAuth_1 !== "undefined" && typeof specialCompleteAuth_1 === "function"){
specialCompleteAuth_1();
} else {
//addition of SF parameter
var params ="ACTION=COMPLETEAUTH_1&APP_NAME="+app_name+"&USER="+user_name+"&ACCT="+ acct_id + "&M1="+M+"&VERSION="+VERSION+"&SF="+selectedSF;
var loader = new xhr.ContentLoader("POST", url,true, completeAuthenticationHandler,params);
}
}
function completeAuthenticationHandlerV2(){
writeDebug("completeAuthenticationHandlerV2: "+STATE+" "+this.req.responseText.length);
var root = this.req.responseXML.documentElement;
if(this.req.responseText.length ==0 ||root.getElementsByTagName("error").length>0){
var message = root.getElementsByTagName("error")[0].firstChild.nodeValue;
showErrorMessage(error_field_id,message);
STATE = null;
return false;
}
else if(this.req.responseText.indexOf("RESPONSEPENDING")!=-1){
return false;
}
var pushSent = false;
var server_M2="";
if(root.getElementsByTagName("M2").length>0){
server_M2 = root.getElementsByTagName("M2")[0].firstChild.nodeValue;
tempServerS2 = server_M2;
}else{
//from previous request take temps2
server_M2 = tempServerS2;
}
var twoFactorType = null;
if(root.getElementsByTagName("type").length >0){
twoFactorType = root.getElementsByTagName("type")[0].firstChild.nodeValue;
}
try{
pushSent = (root.getElementsByTagName("push_sent")[0].firstChild.nodeValue === "true");
}catch(err){pushSent = false;}//default not provided
recalc_M2();
complete_authentication = false; //reset to initial state
if(server_M2 == M2){
//calculate session key
//store it in the cookie
var sk = compute_sk(B,K)
recordSK(sk);
showErrorMessage(error_field_id,"");
//if two factor authentication is required, show the form
twoFactorUser=true;
//read second factor types
if(root.getElementsByTagName("sftypes").length >0){
//TODO handle/get multiple sf types
var sfTypes = root.getElementsByTagName("sftypes")[0].firstChild.nodeValue;
userSfTypes = sfTypes.split(',');
//check length of userSfTypes
if(userSfTypes && userSfTypes.length==1){
//single selection and not show second factor list
selectedSF = userSfTypes[0];
completeAuthentication_1();
}else{
showSecondFactorList();
}
return;
}
//get reference to the form
//append M1
//submit the form
STATE=AUTHENTICATED;
//Added by snarayan for 'Confirm Token Action'
if(complete_confirm_token && !is_two_factor_user) {
randomizePassword();
var user_name = getUserName();
var token = fortifyFilterOpenRedirect(document.getElementById("token").value);
complete_confirm_token = false;
//if(getIfMultiUser() == "true" ) {
// var myparams = "token="+token+"&ACTION=CONFIRMREQUESTWITHAUTHTOKEN&APP_NAME="+app_name+"&user_name="+user_name;
// generalAjaxQuery(url, myparams);
// return true;
//} else {
// var myparams = "token="+token+"&ACTION=CONFIRMREQUEST&APP_NAME="+app_name+"&user_name="+user_name;
// generalAjaxQuery(url, myparams);
// return true;
//}
//Display all the signature parts for ACH signature
var signatures = document.getElementsByName("signatures");
var signatures_str = "";
if(signatures!=null) {
showErrorMessage("ACHERRORMSG","");
//signatures_str = "&signaturelength="+signatures.length;
for(var i =0;i ";
html +="";
var foundSelected = false;
for(var a=0;a0){
foundSelected = true;
}
html +="";
}
html +="";
var sfContainer = document.getElementById("sfContainer");
var twofactSelect = document.getElementById("twofactselect");
sfContainer.innerHTML= html;
twofactSelect.style.display = "";
//append to
//attempt to auto select value
if(foundSelected){
selectedSF = selectedSecondFactor;
completeAuthentication_1();
}
}
function completeAuthenticationHandler(){
writeDebug("completeAuthenticationHandler: "+STATE+" "+this.req.responseText.length);
var root = this.req.responseXML.documentElement;
if(this.req.responseText.length ==0 ||root.getElementsByTagName("error").length>0){
var message = root.getElementsByTagName("error")[0].firstChild.nodeValue;
showErrorMessage(error_field_id,message);
STATE = null;
return false;
}
else if(this.req.responseText.indexOf("RESPONSEPENDING")!=-1){
return false;
}
var pushSent = false;
var server_M2="";
if(root.getElementsByTagName("M2").length>0){
server_M2 = root.getElementsByTagName("M2")[0].firstChild.nodeValue;
}else{
//from previous request take temps2
server_M2 = tempServerS2;
}
var twoFactorType = null;
if(root.getElementsByTagName("type").length >0){
twoFactorType = root.getElementsByTagName("type")[0].firstChild.nodeValue;
}
try{
pushSent = (root.getElementsByTagName("push_sent")[0].firstChild.nodeValue === "true");
}catch(err){pushSent = false;}//default not provided
recalc_M2();
complete_authentication = false; //reset to initial state
if(server_M2 == M2){
//calculate session key
//store it in the cookie
var sk = compute_sk(B,K)
recordSK(sk);
showErrorMessage(error_field_id,"");
//if two factor authentication is required, show the form
if(twoFactorType != null){
twoFactorUser=true;
doTwoFactorAuthentication(root, pushSent);
if(pushSent){
//If specialPushAuthRequest() is defined, then execute that. Otherwise, default to pushAuthRequest(root)
if(typeof specialPushAuthRequest !== "undefined" && typeof specialPushAuthRequest === "function"){
specialPushAuthRequest(root);
} else {
pushAuthRequest(root);
}
}
return;
}
//get reference to the form
//append M1
//submit the form
STATE=AUTHENTICATED;
//Added by snarayan for 'Confirm Token Action'
if(complete_confirm_token && !is_two_factor_user) {
randomizePassword();
var user_name = getUserName();
var token = fortifyFilterOpenRedirect(document.getElementById("token").value);
complete_confirm_token = false;
//if(getIfMultiUser() == "true" ) {
// var myparams = "token="+token+"&ACTION=CONFIRMREQUESTWITHAUTHTOKEN&APP_NAME="+app_name+"&user_name="+user_name;
// generalAjaxQuery(url, myparams);
// return true;
//} else {
// var myparams = "token="+token+"&ACTION=CONFIRMREQUEST&APP_NAME="+app_name+"&user_name="+user_name;
// generalAjaxQuery(url, myparams);
// return true;
//}
//Display all the signature parts for ACH signature
var signatures = document.getElementsByName("signatures");
var signatures_str = "";
if(signatures!=null) {
showErrorMessage("ACHERRORMSG","");
//signatures_str = "&signaturelength="+signatures.length;
for(var i =0;i";
chlgtext.style.display = "";
}
var swcrText = "Response String";
if (isPushAuth) {
if (document.getElementById("chlgdescr_SWCR_IBKey")) {
swcrText = document.getElementById("chlgdescr_SWCR_IBKey").textContent;
}
} else {
if (document.getElementById("chlgdescr_SWCR")) {
swcrText = document.getElementById("chlgdescr_SWCR").textContent;
}
}
var usePlaceHolder = xyz_html5_placeholderCheck();
if (usePlaceHolder)
{
chlgfield.setAttribute("placeholder", swcrText);
//reset size of challenge field
if(chlgdescr){
chlgdescr.parentNode.removeChild(chlgdescr);
}
}
else
chlgdescr.innerHTML = swcrText;
if (!isPushAuth) {
attachXYZHelpLink(twoFactType);
}
}
else if (twoFactType == "Bingo")
{
//reset first
chlgtext.innerHTML="";
if (document.getElementById("chlgtext_Bingo"))
document.getElementById("chlgtext_Bingo").style.display = "";
else
chlgtext.innerHTML = "";
var img = new Image();
img.src = url + "?ACTION=GET_BINGO_CHLG&APP_NAME=" + app_name + "&USER=" + user_name + "&rand=" + Math.random();
chlgtext.appendChild(img);
chlgtext.style.display = "";
var bingoText = "Card Values";
if (document.getElementById("chlgdescr_Bingo"))
bingoText = document.getElementById("chlgdescr_Bingo").textContent;
if (xyz_html5_placeholderCheck())
{
chlgfield.setAttribute("placeholder", bingoText);
if(chlgdescr){
chlgdescr.parentNode.removeChild(chlgdescr);
}
}
else
chlgdescr.innerHTML = bingoText;
attachXYZHelpLink(twoFactType);
}
else if (twoFactType == "IBTK")
{
twoFactChlg = xmlroot.getElementsByTagName("challenge")[0].firstChild.nodeValue;
var ibtkText = "Temporary Security Code";
//clear instructions
chlgtext.innerHTML="";
if (document.getElementById("chlgdescr_IBTK"))
ibtkText = document.getElementById("chlgdescr_IBTK").textContent;
if (xyz_html5_placeholderCheck())
{
chlgfield.setAttribute("placeholder", ibtkText);
if(chlgdescr){
chlgdescr.parentNode.removeChild(chlgdescr);
}
}
else
chlgdescr.innerHTML = ibtkText;
attachXYZHelpLink(twoFactType);
}
if (isPushAuth) {
// hide and display phone text
tbodybase.style.display = 'none';
}
if (isPushAuth && !IBSSO.isRL) {
// add hide show link
var ibKeyInst = document.getElementById('ibKeyInst');
ibKeyInst.innerHTML=PUSH_AUTH_INSTRUCTIONS;
ibKeyInst.style.display='';
//create and add link
var link = document.createElement('a');
link.id = 'phoneLink'
link.href = "javascript:void(0)";
link.onclick = hideShowChallenge;
link.innerHTML = PUSH_AUTH_ALT_LINK;
ibKeyInst.appendChild(link);
ibKeyInst.appendChild(createHelpLink(twoFactType));
}
if (isPushAuth && IBSSO.isRL) {
$('.login-step-username').hide();
$('.login-step-sf').hide();
$('.login-step-notification').show();
animateNotification();
}
}
function notificationShowChallenge() {
clearTimeout(pushTimeout);
$('.login-step-notification').hide();
$('.login-step-challenge').show();
$('.login-step-sf').show();
$('#twofactbase').show();
}
function resendNotification() {
completeAuthentication_1();
$('.login-step-notification .notifResent').slideDown();
};
function animateNotification() {
$('.notificationImg').attr('src', 'images/2fa-animated-once.gif?q=' + Math.random());
}
function xyz_html5_placeholderCheck()
{
var test = document.createElement("input");
return ("placeholder" in test);
}
function hideIBKeyInst(){
var ibKeyInst = document.getElementById("ibKeyInst");
if(ibKeyInst != null)
ibKeyInst.style.display ='none';
}
function hideShowChallenge(){
var tbodybase = document.getElementById("twofactbase");
var instructions2 = document.getElementById("phoneLink");
if(tbodybase.style.display =='none'){
tbodybase.style.display ='';
}else{
tbodybase.style.display ='none';
}
}
// PHONE AUTH FUNCTIONS
function pushAuthRequest(root) {
// set root to reuse on timeout
if (root) {
PHONE_AUTH_ROOT = root;
}
PUSH_AUTH_ATTEMPTS++;
// TODO replace params
if(VERSION==1){
var params = "ACTION=COMPLETETWOFACT&APP_NAME="+app_name+"&USER="+ user_name+"&VERSION="+VERSION+"&SF="+selectedSF+"&PUSH=true"+"&counter="+PUSH_AUTH_ATTEMPTS;
} else {
var params = "ACTION=COMPLETETWOFACT&APP_NAME="+app_name+"&USER="+ user_name+"&VERSION="+VERSION+"&SF="+twoFactType+"&PUSH=true"+"&counter="+PUSH_AUTH_ATTEMPTS;
}
var loader = new xhr.ContentLoader("POST", url, true, pushAuthHandler, params);
// PHONE_AUTH_REQUESTED = true;
}
function pushAuthHandler() {
// Read XML doc
var root = this.req.responseXML.documentElement;
// check response valid
// not valid call pushAuthRequest again
// also check if max attempts reached
if (PUSH_AUTH_ATTEMPTS >= PUSH_AUTH_MAX_ATTEMPTS) {
// display error message or show challenege inputs
// TODO change error message
showErrorMessage(error_field_id, ' ' + PUSH_TIMEOUT_MSG);
hideShowChallenge();
return;
}
if(root.getElementsByTagName("auth_res")!=null){
var auth_res = root.getElementsByTagName("auth_res")[0].firstChild.nodeValue;
if(auth_res === "true"){
PUSH_AUTH_ATTEMPTS = 0;
authenticateTwoFactorHandler(root);
}
else{
pushTimeout = setTimeout(pushAuthRequest, PUSH_CHECK_AUTH_INTERVAL);
}
}
}
function clearPush(){
//reset to zero
PUSH_AUTH_ATTEMPTS = 0;
clearTimeout(pushTimeout);
}
function createHelpLink(twoFactType,secondHelp){
var suffix = "";
if(secondHelp){
suffix = "2";
}
var aLink = document.createElement("a");
aLink.style.fontSize = "14px";
aLink.style.color = "#999999";
aLink.style.cssFloat = "right";
aLink.setAttribute("href", "#");
aLink.setAttribute("onclick", "showXYZHelpWindow('" + twoFactType + "'); return false;");
aLink.setAttribute("id", "help_SF" + suffix);
aLink.setAttribute("name", "help_" + twoFactType);
if (document.getElementById("helpTextCopy"))
aLink.innerHTML = document.getElementById("helpTextCopy").innerHTML;
else
aLink.innerHTML = "Help";
return aLink;
}
function attachXYZHelpLink(twoFactType){
try {
var url = (top.frames) ? top.frames.location : document.location;
url = url.toString().toLowerCase();
var chlgfield = document.getElementById("chlginput");
if (url && chlgfield && url.indexOf("interactivebrokers") != -1)
{
var parent = chlgfield.parentNode;
if (parent)
{
//delete old sf
if(document.getElementById('help_SF2')!=null){
document.getElementById('help_SF2').remove();
}
//check if IBTK
if(twoFactType=='IBTK'){
return;
}
var aLink = createHelpLink(twoFactType,true);
parent.appendChild(aLink);
chlgfield.focus();
chlgfield.select();
}
}
} catch(e) {}
}
function addSecondInputResponse(){
var noSpaceChal = twoFactChlg.replace(/ /gi, '');
var added = noSpaceChal.length == 6;
if (added ) {
//delete chlginput1 if present
var responseInput = document.getElementById("chlginput");
responseInput.maxLength = 5;
responseInput.size = 5;
responseInput.style.width = "90px";
responseInput.style.marginLeft = "25px";
responseInput.onkeyup = challengeKeyUpCheck;
//remove placeholder
responseInput.placeholder="";
responseInput.autocomplete="off";
var responseInput1 = document.createElement("input");
responseInput1.maxLength = 3;
responseInput1.size = 3;
responseInput1.style.width = "40px";
responseInput1.id = "chlginput1";
responseInput1.disabled = true;
responseInput1.style.marginLeft = "10px";
responseInput1.autocomplete="off";
responseInput.parentElement.appendChild(responseInput1);
}
return added;
}
function challengeKeyUpCheck(e){
//enable second response and change focus
var responseInput = document.getElementById('chlginput').value;
var responseInput1 = document.getElementById('chlginput1');
if(responseInput.length==5){
var responseInput1 = document.getElementById('chlginput1');
responseInput1.disabled= false;
responseInput1.focus();
}
}
function showXYZHelpWindow(type){
var twoFactType = type || this.name.split("_")[1];
var helpPlatinum = "https://www.interactivebrokers.com/en/general/platinumHelp.php";
var helpDSC = "https://www.interactivebrokers.com/en/general/digital_security_device.php";
var helpBingo = "https://www.interactivebrokers.com/en/general/bingoHelp.php";
var helpGold = "https://www.interactivebrokers.com/en/index.php?f=5775";
var helpSMS = "https://ibkr.info/article/3196#login";
var helpIBKey = "https://www.interactivebrokers.com/en/index.php?f=13733";
if(twoFactType == "SWTK"){
if(selectedSF == IBSSO.CONSTANT.SECOND_FACTOR_TYPE_OTP){
window.open(helpSMS, "HelpSMS", "width=800,height=700,scrollbars=yes,resizable=yes");
} else {
window.open(helpDSC, "HelpSWTK", "width=800,height=700,scrollbars=yes,resizable=yes");
}
}else if(twoFactType == "SWCR"){
//check if gold
var noSpaceChal = typeof twoFactChlg === 'string' ? twoFactChlg.replace(/ /gi,'') : '';
if(selectedSF ==IBKEY_ANDROID || selectedSF ==IBKEY_IOS){
window.open(helpIBKey, "HelpSWCR", "width=800,height=700,scrollbars=yes,resizable=yes");
return;
}
if(noSpaceChal.length==6){
window.open(helpGold, "HelpSWCR", "width=800,height=700,scrollbars=yes,resizable=yes");
}else{
window.open(helpPlatinum, "HelpSWCR", "width=800,height=700,scrollbars=yes,resizable=yes");
}
}else if(twoFactType == "Bingo"){
window.open(helpBingo, "HelpBingo", "width=800,height=700,scrollbars=yes,resizable=yes");
}else if(twoFactType == "IBTK"){
window.open(helpPlatinum, "HelpIBTK", "width=800,height=700,scrollbars=yes,resizable=yes");
}
}
function authenticateTwoFactor(){
document.getElementById("submitForm").disabled = true;
var additionalChal="";
if(document.getElementById("chlginput1")){
additionalChal = document.getElementById("chlginput1").value;
}
var resp = fortifyFilterOpenRedirect(document.getElementById("chlginput").value + additionalChal);
if(twoFactType !=null && twoFactType == "IBTK"){
var num = "";
var ctmp = parseBigInt(twoFactChlg,16);
//num = "112628796121458";
//var ntmp = parseBigInt(num,10);
num ="";
for(var i=0;i 255){return "";}
var i = dec % 16;
var j = (dec -i)/16;
var result = hexChars.charAt(j)+hexChars.charAt(i);
return result;
}
else return "";
}
//Functions required for Signature Component
var token_field_id = "token";
var in_xyz_form_id = "confirmform";
var actual_user_field_id = "actual_user_name";
var pass_field_id = "password";
var two_factor_user_id = "twofactoruser";
var multi_user_id = "multiuser";
function getToken(){
return fortifyFilterOpenRedirect(document.getElementById(token_field_id).value);
}
function getActualUserName(){
return document.getElementById(actual_user_field_id).value;
}
function getIfTwoFactorUser(){
return document.getElementById(two_factor_user_id).value;
}
function getIfMultiUser(){
return document.getElementById(multi_user_id).value;
}
function doNothing() {
return true;
}
function authenticateTwoFactorSign(){
//document.getElementById("submitForm").disabled = true;
var additionalChal="";
if(document.getElementById("chlginput1")){
additionalChal = document.getElementById("chlginput1").value;
}
var resp = fortifyFilterOpenRedirect(document.getElementById("chlginput").value + additionalChal);
if(twoFactType !=null && twoFactType == "IBTK"){
var num = "";
var ctmp = parseBigInt(twoFactChlg,16);
//num = "112628796121458";
//var ntmp = parseBigInt(num,10);
num ="";
for(var i=0;i 0) {
var delivery_description = xml.getElementsByTagName("delivery_description")[0].firstChild.nodeValue;
if (delivery_description) {
// Update delivery description
$('.otp-text').text(delivery_description);
}
}
}
});
$('#otp-delivery').hide();
$('#twofactbase').show();
}
function cancelOTPSelection() {
writeDebug('cancelOTPSelection');
$('#otp-delivery').hide();
$('#twofactbase').show();
}
function checkOTPSelection(xml) {
if (selectedSF !== IBSSO.CONSTANT.SECOND_FACTOR_TYPE_OTP) {
return;
}
var delivery_description = '';
var supported_media = 0;
if(xml.getElementsByTagName("delivery_description").length > 0) {
delivery_description = xml.getElementsByTagName("delivery_description")[0].firstChild.nodeValue;
}
if(xml.getElementsByTagName("supported_media").length > 0) {
var supported_media_node = xml.getElementsByTagName("supported_media")[0].firstChild.nodeValue;
supported_media = parseInt(supported_media_node, 10);
}
$('.otp-text').text(delivery_description);
if (supported_media > 0) {
var isSMSSupported = supported_media & IBSSO.CONSTANT.OTP_DELIVERY_TYPE_SMS;
var isVoiceSupported = supported_media & IBSSO.CONSTANT.OTP_DELIVERY_TYPE_VOICE;
var isEmailSupported = supported_media & IBSSO.CONSTANT.OTP_DELIVERY_TYPE_EMAIL;
var has2buttons = (isSMSSupported && isVoiceSupported && !isEmailSupported) ||
(isSMSSupported && !isVoiceSupported && isEmailSupported) ||
(!isSMSSupported && isVoiceSupported && isEmailSupported);
var has3buttons = isSMSSupported && isVoiceSupported && isEmailSupported;
if (isSMSSupported) {
$('.otp-select-sms').show();
} else {
$('.otp-select-sms').hide();
}
if (isVoiceSupported) {
$('.otp-select-voice').show();
} else {
$('.otp-select-voice').hide();
}
if (isEmailSupported) {
$('.otp-select-email').show();
} else {
$('.otp-select-email').hide();
}
if (has2buttons) {
$('.otp-buttons').addClass('twobuttons');
}
if (has3buttons) {
$('.otp-buttons').addClass('threebuttons');
}
$('.otp-opener-text').show();
window.IBSSO.otpSelectTimer = window.setTimeout(showOTPSelectionDelayed, window.IBSSO.otpSelectTimerTimeout);
}
}
function showOTPSelectionDelayed() {
writeDebug('showOTPSelectionDelayed');
// switch Text and Voice and Email buttons
$('.otp-buttons').addClass('otp-buttons-reverse');
// show buttons
showOTPSelection();
}
function xyzLoginformSubmit(formElement) {
if (typeof window.runPublishToken === 'function') {
window.runPublishToken();
window.setTimeout(function() {
formElement.submit();
}, 1000);
} else {
formElement.submit();
}
}