';
+
+ let btn = document.getElementById(factor);
+ btn.onclick = () => {
+ let state = JSON.parse(self.app.getInitialState())
+ self.app.setSelectedDevice({ "deviceId": jsonResponse[factor]["enrolledDevices"][0].deviceId });
+ switch (factor) {
+ case "EMAIL":
+ self.initAuthnOtpEmail(buildPayloadUserNameFirst("EMAIL"));
+ subdiv.innerHTML = "";
+ subdiv.whichDisplayName = getDisplayName("EMAIL");
+ self.app.buildEmailOtpForm(subdiv, buildPayloadUserNameFirst("EMAIL"));
+ break;
+ case "SMS":
+ self.initAuthnOtpSms(buildPayloadUserNameFirst("SMS"));
+ subdiv.innerHTML = "";
+ subdiv.whichDisplayName = getDisplayName("SMS");
+ self.app.buildSMSMobileEnrollmentForm(subdiv, buildPayloadUserNameFirst("SMS"));
+ self.app.buildSmsOtpForm(subdiv, buildPayloadUserNameFirst("SMS"));
+ break;
+ case "TOTP":
+ subdiv.innerHTML = "";
+ subdiv.whichDisplayName = getDisplayName("TOTP");
+ self.initEnrollOtpTotp()
+ self.app.buildTOTPForm(subdiv, { "deviceId": jsonResponse["TOTP"]["enrolledDevices"][0].deviceId, "offlineTotp": jsonResponse["TOTP"]["enrolledDevices"][0], });
+ break;
+ default:
+ self.app.logMsg("No factors enabled for authentication");
+ break;
+ }
+ }
+ }
+ });
+ }
+ }
}
}
else
- if (jsonResponse.status === 'failed') {
- if (jsonResponse.cause) {
- self.app.setLoginErrorMessage({code:jsonResponse.cause[0].code, msg:jsonResponse.cause[0].message});
- }
- else {
- self.app.setLoginErrorMessage(self.sdkErrors.error9010);
- }
+ if (jsonResponse.status === 'failed') {
+ if (jsonResponse.cause) {
+ self.app.setLoginErrorMessage({ code: jsonResponse.cause[0].code, msg: jsonResponse.cause[0].message });
+ }
+ else {
+ self.app.setLoginErrorMessage(self.sdkErrors.error9010);
+ }
- if (jsonResponse.nextOp && jsonResponse.nextOp.indexOf("submitCreds") >= 0) {
- // do nothing
- self.app.logMsg("Nothing to do here.");
+ if (jsonResponse.nextOp && jsonResponse.nextOp.indexOf("submitCreds") >= 0) {
+ // do nothing
+ self.app.logMsg("Nothing to do here.");
+ }
}
- }
- else
- if (jsonResponse.status === 'pending') {
- // pending means one of two things:
- if ( jsonResponse.cause ) {
- if ( jsonResponse.cause[0].code ) {
- let code = jsonResponse.cause[0].code;
-
- // then we're waiting for the user to say "Allow"
- // so call back to the app to let them know it's OK to proceed
- if ( code == "AUTH-1108" ) {
- self.app.nextOperation(jsonResponse);
+ else
+ if (jsonResponse.status === 'pending') {
+ // pending means one of two things:
+ if (jsonResponse.cause) {
+ if (jsonResponse.cause[0].code) {
+ let code = jsonResponse.cause[0].code;
+
+ // then we're waiting for the user to say "Allow"
+ // so call back to the app to let them know it's OK to proceed
+ if (code == "AUTH-1108") {
+ self.app.nextOperation(jsonResponse);
+ }
+ }
}
}
- }
- }
- else {
- self.app.setLoginErrorMessage(self.sdkErrors.error9011);
- }
+ else {
+ self.app.setLoginErrorMessage(self.sdkErrors.error9011);
+ }
}
}
});
@@ -241,55 +322,56 @@ function IdcsAuthnSDK(app) {
xhr.setRequestHeader("Accept", "application/json");
this.app.logMsg('[IdcsAuthnSDK] Using access token: ' + this.app.getAccessToken());
xhr.setRequestHeader("Authorization", "Bearer " + this.app.getAccessToken());
-
xhr.send(data);
}
- catch(e) { //this should never happen
+ catch (e) { //this should never happen
self.app.logMsg(e);
self.app.setLoginErrorMessage(self.sdkErrors.error9999);
}
} //this.authenticate
- this.postCreds = function(credentials) {
-
- this.app.logMsg('[IdcsAuthnSDK] Posting credentials (u/p)...');
-
+ this.getEnrollmentFactorsuserNameFirst = function (data) {
var data = JSON.stringify({
- "op": "credSubmit",
- "authFactor": "USERNAME_PASSWORD",
- "credentials": credentials,
+ "op": "getBackupFactors",
+ "authFactor": "USERNAME",
+ "credentials": data.credentials,
"requestState": this.app.getRequestState()
});
-
this.authenticate(data);
- }; // this.postCreds
-
- // Post just the user name to Idcs
- // This is for the "user name first" feature
- this.postUserName = function(credentials) {
-
- this.app.logMsg('[IdcsAuthnSDK] Posting user name ...');
+ }
+ this.postUserNameFirst = function (data) {
var data = JSON.stringify({
"op": "credSubmit",
"authFactor": "USERNAME",
- "credentials": credentials,
- "requestState": this.app.getRequestState()
+ "credentials": data.credentials,
+ "requestState": this.app.getRequestState(),
});
-
+ sessionStorage.setItem("userNameFirst", true)
this.authenticate(data);
- }; // this.postUserName
+ }//this.postUserNameFirst
- this.postEmailOtp = function(credentials) {
+ this.postCreds = function (data) {
+ this.app.logMsg('[IdcsAuthnSDK] Posting credentials (u/p)...');
+ var data = JSON.stringify({
+ "op": "credSubmit",
+ "authFactor": "USERNAME_PASSWORD",
+ "credentials": data.credentials,
+ "requestState": this.app.getRequestState(),
+ });
+
+ this.authenticate(data);
+ }; // this.postCreds
+ this.postEmailOtp = function (credentials) {
this.app.logMsg('[IdcsAuthnSDK] Posting Email OTP...');
var data = JSON.stringify({
"op": "credSubmit",
"authFactor": "EMAIL",
"credentials": credentials,
- "trustedDevice": JSON.parse(this.app.getTrustedDeviceOption()), // Value here MUST be Boolean!!
+ "trustedDevice": JSON.parse(this.app.getTrustedDeviceOption()) ? true : false, // Value here MUST be Boolean!!
"trustedDeviceDisplayName": this.clientFingerprint.browser + ' on ' + this.clientFingerprint.OS + ' ' + this.clientFingerprint.OSVersion,
"requestState": this.app.getRequestState()
});
@@ -297,7 +379,7 @@ function IdcsAuthnSDK(app) {
this.authenticate(data);
}; // this.postEmailOtp
- this.postSmsOtp = function(credentials) {
+ this.postSmsOtp = function (credentials) {
this.app.logMsg('[IdcsAuthnSDK] Posting SMS OTP...');
@@ -305,7 +387,7 @@ function IdcsAuthnSDK(app) {
"op": "credSubmit",
"authFactor": "SMS",
"credentials": credentials,
- "trustedDevice": JSON.parse(this.app.getTrustedDeviceOption()), // Value here MUST be Boolean!!
+ "trustedDevice": JSON.parse(this.app.getTrustedDeviceOption()) ? true : false, // Value here MUST be Boolean!!
"trustedDeviceDisplayName": this.clientFingerprint.browser + ' on ' + this.clientFingerprint.OS + ' ' + this.clientFingerprint.OSVersion,
"requestState": this.app.getRequestState()
});
@@ -313,7 +395,7 @@ function IdcsAuthnSDK(app) {
this.authenticate(data);
}; // this.postSmsOtp
- this.enrollSecurityQuestions = function(credentials) {
+ this.enrollSecurityQuestions = function (credentials) {
this.app.logMsg('[IdcsAuthnSDK] Enrolling Security Questions and Answers...');
@@ -323,17 +405,17 @@ function IdcsAuthnSDK(app) {
"requestState": this.app.getRequestState()
});
this.authenticate(data);
- }
+ }
- this.postSecQuestions = function(credentials) {
+ this.postSecQuestions = function (credentials) {
this.app.logMsg('[IdcsAuthnSDK] Posting Security Questions...');
var questions = [];
const inputElements = document.getElementsByTagName("INPUT");
- for (i=0; i < inputElements.length; i++) {
+ for (i = 0; i < inputElements.length; i++) {
if (inputElements[i].type === "password") {
- questions[i] = {'questionId':inputElements[i].name, 'answer':inputElements[i].value};
+ questions[i] = { 'questionId': inputElements[i].name, 'answer': inputElements[i].value };
}
}
@@ -341,7 +423,7 @@ function IdcsAuthnSDK(app) {
"op": "credSubmit",
"authFactor": "SECURITY_QUESTIONS",
"credentials": credentials,
- "trustedDevice": JSON.parse(this.app.getTrustedDeviceOption()), // Value here MUST be Boolean!!
+ "trustedDevice": JSON.parse(this.app.getTrustedDeviceOption()) ? true : false, // Value here MUST be Boolean!!
"trustedDeviceDisplayName": this.clientFingerprint.browser + ' on ' + this.clientFingerprint.OS + ' ' + this.clientFingerprint.OSVersion,
"requestState": this.app.getRequestState()
});
@@ -350,7 +432,22 @@ function IdcsAuthnSDK(app) {
}; // this.postSecQuestions
- this.initEnrollOtpEmail = function() {
+ this.initEnrollFido = function () {
+
+ this.app.logMsg('[IdcsAuthnSDK] Initiating Fido enrollment...');
+
+ var data = JSON.stringify({
+ "op": "enrollment",
+ "authFactor": "FIDO_AUTHENTICATOR",
+ "origin": window.location.origin,
+ "requestState": this.app.getRequestState()
+ });
+
+ this.authenticate(data);
+
+ }; // this.initEnrollFido
+
+ this.initEnrollOtpEmail = function () {
this.app.logMsg('[IdcsAuthnSDK] Initiating OTP over email enrollment...');
@@ -364,7 +461,7 @@ function IdcsAuthnSDK(app) {
}; // this.initEnrollOtpEmail
- this.enrollOtpEmail = function(credentials) {
+ this.enrollOtpEmail = function (credentials) {
this.app.logMsg('[IdcsAuthnSDK] Enrolling OTP over email...');
@@ -377,7 +474,7 @@ function IdcsAuthnSDK(app) {
this.authenticate(data);
}; // this.enrollOtpEmail
- this.initAuthnOtpEmail = function(credentials) {
+ this.initAuthnOtpEmail = function (credentials) {
this.app.logMsg('[IdcsAuthnSDK] Initiating OTP over email authentication...');
@@ -387,12 +484,12 @@ function IdcsAuthnSDK(app) {
"credentials": credentials,
"requestState": this.app.getRequestState()
});
-
this.authenticate(data);
+
}; // this.initAuthnOtpEmail
- this.initEnrollMobileNumber = function(credentials) {
+ this.initEnrollMobileNumber = function (credentials) {
this.app.logMsg('Initiating OTP over SMS: Mobile enrollment...');
var data = JSON.stringify({
@@ -404,8 +501,7 @@ function IdcsAuthnSDK(app) {
this.authenticate(data);
}; // this.initEnrollMobileNumber
-
- this.initAuthnMobileNumber = function(credentials) {
+ this.initAuthnMobileNumber = function (credentials) {
this.app.logMsg('Initiating OTP over SMS: Authenticating...');
var data = JSON.stringify({
@@ -418,7 +514,7 @@ function IdcsAuthnSDK(app) {
}; // this.initAuthnMobileNumber
- this.resendOtp = function() {
+ this.resendOtp = function () {
this.app.logMsg('Resending OTP ...');
var data = JSON.stringify({
"op": "resendCode",
@@ -427,7 +523,7 @@ function IdcsAuthnSDK(app) {
this.authenticate(data);
}; // this.initEnrollMobileNumber
- this.enrollMobileNumber = function() {
+ this.enrollMobileNumber = function () {
this.app.logMsg('[IdcsAuthnSDK] Send OTP over SMS...');
var data = JSON.stringify({
"op": "credSubmit",
@@ -439,7 +535,7 @@ function IdcsAuthnSDK(app) {
this.authenticate(data);
}; // this.enrollMobileNumber
- this.initEnrollSecurityQuestions = function() {
+ this.initEnrollSecurityQuestions = function () {
this.app.logMsg('[IdcsAuthnSDK] Enrolling Security Questions...');
var data = JSON.stringify({
"op": "enrollment",
@@ -450,9 +546,8 @@ function IdcsAuthnSDK(app) {
this.authenticate(data);
}; // this.initEnrollSecurityQuestions
- this.createToken = function() {
+ this.createToken = function () {
this.app.logMsg('[IdcsAuthnSDK] Creating token...');
-
var data = JSON.stringify({
"op": "createToken",
"requestState": this.app.getRequestState()
@@ -461,270 +556,100 @@ function IdcsAuthnSDK(app) {
this.authenticate(data);
}; // this.initEnrollSecurityQuestions
- this.initEnrollOtpTotp = function() {
- var data = JSON.stringify({
- "op":"enrollment",
- "authFactor":"TOTP",
- "credentials":{
- "offlineTotp":true
- },
- "requestState":this.app.getRequestState()
+ this.initEnrollOtpTotp = function () {
+ var data = JSON.stringify({
+ "op": "enrollment",
+ "authFactor": "TOTP",
+ "credentials": {
+ "offlineTotp": true
+ },
+ "requestState": this.app.getRequestState()
});
this.authenticate(data);
} // this.initEnrollOtpTotp
- this.submitTOTP = function(credentials, includeAuthnFactor) {
+ this.submitTOTP = function (credentials, includeAuthnFactor) {
+ var data = JSON.stringify({
+ "op": "credSubmit",
+ "credentials": credentials,
+ "trustedDevice": JSON.parse(this.app.getTrustedDeviceOption()) ? true : false, // Value here MUST be Boolean!!
+ "trustedDeviceDisplayName": this.clientFingerprint.browser + ' on ' + this.clientFingerprint.OS + ' ' + this.clientFingerprint.OSVersion,
+ "requestState": this.app.getRequestState()
+ });
- var data = JSON.stringify({
- "op":"credSubmit",
+ if (typeof includeAuthnFactor !== 'undefined') {
+ data = JSON.stringify({
+ "op": "credSubmit",
+ "authFactor": "TOTP",
"credentials": credentials,
- "trustedDevice": JSON.parse(this.app.getTrustedDeviceOption()), // Value here MUST be Boolean!!
+ "trustedDevice": JSON.parse(this.app.getTrustedDeviceOption()) ? true : false, // Value here MUST be Boolean!!
"trustedDeviceDisplayName": this.clientFingerprint.browser + ' on ' + this.clientFingerprint.OS + ' ' + this.clientFingerprint.OSVersion,
- "requestState":this.app.getRequestState()
+ "requestState": this.app.getRequestState()
});
-
- if (typeof includeAuthnFactor !== 'undefined') {
- data = JSON.stringify({
- "op":"credSubmit",
- "authFactor": "TOTP",
- "credentials": credentials,
- "trustedDevice": JSON.parse(this.app.getTrustedDeviceOption()), // Value here MUST be Boolean!!
- "trustedDeviceDisplayName": this.clientFingerprint.browser + ' on ' + this.clientFingerprint.OS + ' ' + this.clientFingerprint.OSVersion,
- "requestState":this.app.getRequestState()
- });
- }
- this.authenticate(data);
+ }
+ this.authenticate(data);
}
- this.submitBypasscode = function(credentials) {
+ this.submitBypasscode = function (credentials) {
var data = JSON.stringify({
- "op":"credSubmit",
- "authFactor":"BYPASSCODE",
- "credentials":credentials,
- "requestState":this.app.getRequestState()
+ "op": "credSubmit",
+ "authFactor": "BYPASSCODE",
+ "credentials": credentials,
+ "requestState": this.app.getRequestState()
});
this.authenticate(data);
}
- this.submitAcceptTerms = function() {
+ this.submitAcceptTerms = function () {
var data = JSON.stringify({
- "op": "acceptTOU",
- "credentials": {
- "consent": true
- },
- "requestState": this.app.getRequestState()
+ "op": "acceptTOU",
+ "credentials": {
+ "consent": true
+ },
+ "requestState": this.app.getRequestState()
});
this.authenticate(data);
}
- this.forgotPassword = function(payload) {
+ this.forgotPassword = function (username) {
const self = this;
- this.app.logMsg("[IdcsAuthnSDK] Username is :" + payload.username);
-
- var xhr = new XMLHttpRequest();
- xhr.addEventListener("readystatechange", function () {
- if (this.readyState === 4) {
- self.app.logMsg("[IdcsAuthnSDK] PasswordResetRequestor Response: "+self.app.mask(this.responseText));
- const jsonResponse = JSON.parse(this.responseText);
-
- if (jsonResponse.hasOwnProperty('userName')&& jsonResponse.notificationType === 'email') {
- // Uncomment the line below if you want the OOTB Password Reset form
- //self.app.displayForgotPassWordSuccess(jsonResponse, payload.username);
-
- // Uncomment the line below to use a custom e-mail form to enter a token.
- // The ${userToken} must be set in the E-mail template for this flow to work.
- self.app.displayForgotPassWordEmailForm(jsonResponse, payload.username);
- }
- if (jsonResponse.hasOwnProperty('userName')&& jsonResponse.notificationType === 'sms') {
- self.app.displayForgotPassWordSmsForm(jsonResponse, payload.username);
- }
- if (jsonResponse.hasOwnProperty('userName')&& jsonResponse.notificationType === 'secquestions') {
- self.app.displayForgotPassWordSecquestionForm(jsonResponse, payload.username);
- }
- }
- });
-
- xhr.open("POST", app.baseUri + "/admin/v1/MePasswordResetRequestor");
- xhr.setRequestHeader("Content-Type", "application/json");
- xhr.setRequestHeader("Authorization", "Bearer " + this.app.getAccessToken());
- if (payload.method === 'email') {
- var emailData = JSON.stringify({
- "userName": payload.username,
- "notificationType": "email",
- "notificationEmailAddress" : payload.email,
- "schemas": [
- "urn:ietf:params:scim:schemas:oracle:idcs:MePasswordResetRequestor"
- ]
- });
- xhr.send(emailData);
- }
- else if (payload.method === 'sms') {
- var smsData = JSON.stringify({
- "userName": payload.username,
- "notificationType": "sms",
- "schemas": [
- "urn:ietf:params:scim:schemas:oracle:idcs:MePasswordResetRequestor"
- ]
- });
- xhr.send(smsData);
- }
- else if (payload.method === 'secquestions') {
- var secData = JSON.stringify({
- "userName": payload.username,
- "notificationType": "secquestions",
- "schemas": [
- "urn:ietf:params:scim:schemas:oracle:idcs:MePasswordResetRequestor"
- ]
- });
- xhr.send(secData);
- }
-
- }; //this.forgotPassword
-
- this.getPasswordMethod = function(username) {
- const self = this;
- this.app.logMsg("[IdcsAuthnSDK] Username is :" + username);
+ this.app.logMsg("[IdcsAuthnSDK] Username is :" + this.app.mask(username));
var data = JSON.stringify({
"userName": username,
+ "notificationType": "email",
"schemas": [
- "urn:ietf:params:scim:schemas:oracle:idcs:MePasswordRecoveryOptionRetriever"
- ]
- });
-
- var xhr = new XMLHttpRequest();
- xhr.addEventListener("readystatechange", function () {
- if (this.readyState === 4) {
- self.app.logMsg("[IdcsAuthnSDK] PasswordRecoveryOptionRetriever Response: "+self.app.mask(this.responseText));
- const jsonResponse = JSON.parse(this.responseText);
- // Check what options the user can use for password flow (email, sms, secquestion)
- // If there is only one option it must be email, check anyways.
- if (jsonResponse.hasOwnProperty('options') )
- {
- if (jsonResponse.options.length == 1 )
- {
- if (jsonResponse.options[0].type === 'email')
- {
- self.forgotPassword({"username": username, "email": jsonResponse.options[0].value, "method": "email"});
- }
- else if (jsonResponse.options[0].type === 'sms')
- {
- self.forgotPassword({"username": username, "method": "sms"});
- }
- else if (jsonResponse.options[0].type === 'secquestions')
- {
- self.forgotPassword({"username": username, "method": "secquestions"});
- }
- else
- {
- // Error - No options found. This "should" never happen.
- self.app.setLoginErrorMessage(self.sdkErrors.error9010);
- }
- }
- else
- {
- self.app.displayForgotPassWordMethodForm(jsonResponse, username);
- }
- }
- else // Error - No options found. This "should" never happen.
- {
- self.app.setLoginErrorMessage(self.sdkErrors.error9010);
- }
- }
- });
-
- xhr.open("POST", app.baseUri + "/admin/v1/MePasswordRecoveryOptionRetriever");
- xhr.setRequestHeader("Content-Type", "application/json");
- xhr.setRequestHeader("Authorization", "Bearer " + this.app.getAccessToken());
- xhr.send(data);
- }; //this.getPasswordMethod
+ "urn:ietf:params:scim:schemas:oracle:idcs:MePasswordResetRequestor"
+ ]
+ });
- this.processPasswordMethod = function(payload) {
- const self = this;
var xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function () {
- if (this.readyState === 4) {
- self.app.logMsg("[IdcsAuthnSDK] PasswordRecoveryFactorValidator Response: "+self.app.mask(this.responseText));
- const jsonResponse = JSON.parse(this.responseText);
+ if (this.readyState === 4) {
+ self.app.logMsg("[IdcsAuthnSDK] PasswordResetRequestor Response: " + self.app.mask(this.responseText));
+ const jsonResponse = JSON.parse(this.responseText);
- if (jsonResponse.hasOwnProperty('token')) {
- self.app.displayResetPassWordForm(jsonResponse.token);
- }
- else {
- // Checking for Status 400 - No Token
- if (jsonResponse.hasOwnProperty('status') && jsonResponse.status === '400') {
- var error = jsonResponse['urn:ietf:params:scim:api:oracle:idcs:extension:messages:Error'];
- self.app.logMsg(error.messageId);
- if (error.messageId === "error.identity.passwordmgmt.invalidToken") {
- self.app.setLoginErrorMessage(self.sdkErrors.error9022);
- }
- else if (error.messageId === "error.ssocommon.auth.invalidPasscode" ||
- error.messageId === "error.identity.accrec.invalidOTP") {
- self.app.setLoginErrorMessage(self.sdkErrors.error9023);
- }
- else if (error.messageId === "error.identity.passwordmgmt.invalidSecurityQuestionAnswer") {
- self.app.setLoginErrorMessage(self.sdkErrors.error9024);
- }
- else // Unrecognized error message
- {
- self.app.setLoginErrorMessage(self.sdkErrors.error9012);
- }
- }
- }
- }
- });
+ if (jsonResponse.hasOwnProperty('userName') && jsonResponse.notificationType === 'email') {
+ self.app.displayForgotPassWordSuccess(jsonResponse);
+ }
+ }
+ });
- xhr.open("POST", app.baseUri + "/admin/v1/MePasswordRecoveryFactorValidator");
+ xhr.open("POST", app.baseUri + "/admin/v1/MePasswordResetRequestor");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("Authorization", "Bearer " + this.app.getAccessToken());
+ xhr.send(data);
+ }; //this.forgotPassword
- if (payload.method === 'email') {
- var emailData = JSON.stringify({
- "schemas": [
- "urn:ietf:params:scim:schemas:oracle:idcs:MePasswordRecoveryFactorValidator"
- ],
- "type": "email",
- "emailToken": decodeURIComponent(payload.emailToken)
- });
- xhr.send(emailData);
- }
- else if (payload.method === 'sms') {
- var smsData = JSON.stringify({
- "schemas": [
- "urn:ietf:params:scim:schemas:oracle:idcs:MePasswordRecoveryFactorValidator"
- ],
- "type": "sms",
- "userName": payload.username,
- "deviceId": payload.deviceId,
- "requestId": payload.requestId,
- "otpCode": payload.smsCode
- });
- xhr.send(smsData);
- }
- else if (payload.method === 'secquestions') {
- var secData = JSON.stringify({
- "schemas": [
- "urn:ietf:params:scim:schemas:oracle:idcs:MePasswordRecoveryFactorValidator"
- ],
- "userName": payload.username,
- "type": "secquestions",
- "securityQuestions": [{
- "questionId": payload.questionId,
- "securityAnswer": payload.secAnswer
- }] });
- xhr.send(secData);
- }
- }; //this.processPasswordMethod
-
- this.initEnrollPush = function() {
+ this.initEnrollPush = function () {
var data = JSON.stringify({
- "op":"enrollment",
- "authFactor":"PUSH",
- "requestState":this.app.getRequestState()
+ "op": "enrollment",
+ "authFactor": "PUSH",
+ "requestState": this.app.getRequestState()
});
this.authenticate(data);
}
- this.initAuthnPush = function(credentials) {
+ this.initAuthnPush = function (credentials) {
this.app.logMsg('[IdcsAuthnSDK] Initiating Push...');
var data = JSON.stringify({
@@ -736,81 +661,94 @@ function IdcsAuthnSDK(app) {
this.authenticate(data);
}; // this.initAuthnPush
- this.submitPushPoll = function(credentials) {
+ this.initAuthnFido = function (credentials) {
+ this.app.logMsg('[IdcsAuthnSDK] Initiating Fido...');
+
var data = JSON.stringify({
- "op":"credSubmit",
+ "op": "credSubmit",
+ "authFactor": "FIDO_AUTHENTICATOR",
+ "credentials": credentials,
+ "requestState": this.app.getRequestState()
+ });
+ this.authenticate(data);
+ }; // this.initAuthnFido
+
+ this.submitPushPoll = function (credentials) {
+ var data = JSON.stringify({
+ "op": "credSubmit",
"authFactor": "PUSH",
"credentials": credentials,
- "trustedDevice": JSON.parse(this.app.getTrustedDeviceOption()), // Value here MUST be Boolean!!
+ "trustedDevice": JSON.parse(this.app.getTrustedDeviceOption()) ? true : false, // Value here MUST be Boolean!!
"trustedDeviceDisplayName": this.clientFingerprint.browser + ' on ' + this.clientFingerprint.OS + ' ' + this.clientFingerprint.OSVersion,
- "requestState":this.app.getRequestState()
+ "requestState": this.app.getRequestState()
});
this.authenticate(data);
}
- this.submitBackupFactors = function() {
+ this.submitBackupFactors = function () {
var data = JSON.stringify({
- "op":"getBackupFactors",
- "requestState":this.app.getRequestState()
+ "op": "getBackupFactors",
+ "origin": window.location.origin,
+ "requestState": this.app.getRequestState()
});
this.authenticate(data);
}
- this.getEnrollmentFactors = function() {
+ this.getEnrollmentFactors = function () {
var data = JSON.stringify({
- "op":"enrollment",
- "requestState":this.app.getRequestState()
+ "op": "enrollment",
+ "requestState": this.app.getRequestState()
});
this.authenticate(data);
}
- this.validateToken = function(token, callback) {
- this.app.logMsg('[IdcsAuthnSDK] In Validate Token');
-
- var data = JSON.stringify({
- "token": token,
- "schemas": [
- "urn:ietf:params:scim:schemas:oracle:idcs:UserTokenValidator"
- ]
- });
-
- var xhr = new XMLHttpRequest();
- const self = this;
-
- xhr.addEventListener("readystatechange", function () {
- if (this.readyState === 4) {
- self.app.logMsg('[IdcsAuthnSDK] Validate User Token:' + self.app.mask(this.responseText));
- const jsonResponse = JSON.parse(this.responseText);
- callback(jsonResponse);
- }
- });
-
- xhr.open("POST", app.baseUri + "/admin/v1/UserTokenValidator");
- xhr.setRequestHeader("Content-Type", "application/json");
- xhr.setRequestHeader("Authorization", "Bearer " + this.app.getAccessToken());
- xhr.send(data);
- }; // this.validateToken
-
- this.validateUserToken = function(token) {
+ this.validateToken = function (token, callback) {
+ this.app.logMsg('[IdcsAuthnSDK] In Validate Token');
+
+ var data = JSON.stringify({
+ "token": token,
+ "schemas": [
+ "urn:ietf:params:scim:schemas:oracle:idcs:UserTokenValidator"
+ ]
+ });
+
+ var xhr = new XMLHttpRequest();
+ const self = this;
+
+ xhr.addEventListener("readystatechange", function () {
+ if (this.readyState === 4) {
+ self.app.logMsg('[IdcsAuthnSDK] Validate User Token:' + self.app.mask(this.responseText));
+ const jsonResponse = JSON.parse(this.responseText);
+ callback(jsonResponse);
+ }
+ });
+
+ xhr.open("POST", app.baseUri + "/admin/v1/UserTokenValidator");
+ xhr.setRequestHeader("Content-Type", "application/json");
+ xhr.setRequestHeader("Authorization", "Bearer " + this.app.getAccessToken());
+ xhr.send(data);
+ }; // this.validateToken
+
+ this.validateUserToken = function (token) {
this.app.logMsg('[IdcsAuthnSDK] In ValidateUserToken...');
this.app.logMsg('[IdcsAuthnSDK] Token: ' + this.app.mask(token));
const self = this;
- this.validateToken(token , function(returnVal1) {
+ this.validateToken(token, function (returnVal1) {
var id = returnVal1.userId;
if (returnVal1.hasOwnProperty('userId')) {
- self.app.logMsg('[IdcsAuthnSDK] UserTokenValidator Repsonse , Success for Id -->' + self.app.mask(returnVal1.userId));
- self.app.displayResetPassWordForm(token);
+ self.app.logMsg('[IdcsAuthnSDK] UserTokenValidator Repsonse , Success for Id -->' + self.app.mask(returnVal1.userId));
+ self.app.displayResetPassWordForm(token);
}
else {
- self.app.setLoginErrorMessage(self.sdkErrors.error9020);
+ self.app.setLoginErrorMessage(self.sdkErrors.error9020);
}
});
}; // this.validateUserToken
- this.evaluatePasswordPolicies = function(resetpaswddata ,callback) {
+ this.evaluatePasswordPolicies = function (resetpaswddata, callback) {
const self = this;
var data = JSON.stringify({
"userName": "dummydata@example.com",
@@ -839,7 +777,7 @@ function IdcsAuthnSDK(app) {
}; //this.evaluatePasswordPolicies
- this.resetUserPassword = function(token,resetpaswddata,callback){
+ this.resetUserPassword = function (token, resetpaswddata, callback) {
const self = this;
var data = JSON.stringify({
"schemas": [
@@ -855,7 +793,7 @@ function IdcsAuthnSDK(app) {
xhr.addEventListener("readystatechange", function () {
if (this.readyState === 4) {
const jsonResponse = JSON.parse(this.responseText);
- self.app.logMsg('[IdcsAuthnSDK] Reset user Password Response: ' + self.app.mask(this.responseText));
+ self.app.logMsg('[IdcsAuthnSDK] Reset user Password Response: ' + self.app.mask(this.responseText));
callback(jsonResponse);
}
});
@@ -866,11 +804,11 @@ function IdcsAuthnSDK(app) {
xhr.send(data);
}; //this.resetUserPassword
- this.resetPassword = function(credentials){
+ this.resetPassword = function (credentials) {
const self = this;
self.app.logMsg('[IdcsAuthnSDK] Resetting password...');
- this.evaluatePasswordPolicies(credentials.password ,function(returnValue1) {
+ this.evaluatePasswordPolicies(credentials.password, function (returnValue1) {
if (returnValue1.hasOwnProperty('failedPasswordPolicyRules')) {
self.sdkErrors.error9021.details = [];
@@ -887,29 +825,29 @@ function IdcsAuthnSDK(app) {
else {
self.app.logMsg('[IdcsAuthnSDK] Password policies came back fine. Proceeding with reset password...');
- self.resetUserPassword(credentials.token, credentials.password,function(returnValue2) {
- if(returnValue2.hasOwnProperty('id')) {
+ self.resetUserPassword(credentials.token, credentials.password, function (returnValue2) {
+ if (returnValue2.hasOwnProperty('id')) {
self.app.logMsg('[IdcsAuthnSDK] ResetPassword was successful.');
self.app.displayResetPassWordSuccess();
}
else {
self.app.logMsg(JSON.stringify(returnValue2));
self.app.logMsg('[IdcsAuthnSDK] ResetPassword failed: ' + returnValue2.detail);
- self.app.setLoginErrorMessage({code:'', msg:returnValue2.detail});
+ self.app.setLoginErrorMessage({ code: '', msg: returnValue2.detail });
}
});
}
});
}; // this.resetPassword
- this.createSession = function(payload) {
+ this.createSession = function (payload) {
- var addParam = function(myform, paramName, paramValue) {
- param = document.createElement("input");
- param.value = paramValue;
- param.name = paramName;
- param.hidden=true;
- myform.appendChild(param);
+ var addParam = function (myform, paramName, paramValue) {
+ param = document.createElement("input");
+ param.value = paramValue;
+ param.name = paramName;
+ param.hidden = true;
+ myform.appendChild(param);
};
this.app.logMsg('[IdcsAuthnSDK] Creating session with authnToken:' + this.app.mask(payload));
@@ -923,6 +861,11 @@ function IdcsAuthnSDK(app) {
this.app.logMsg('[IdcsAuthnSDK] trustToken added.');
addParam(myform, "trustToken", payload.trustToken);
}
+ if (payload.kmsiToken) {
+ this.app.logMsg('[IdcsAuthnSDK] kmsiToken added.');
+ addParam(myform, "kmsiToken", payload.kmsiToken);
+ console.log("KMSI")
+ }
document.body.appendChild(myform);
//adding this to flush session after successful login...
sessionStorage.clear();
@@ -955,40 +898,40 @@ function IdcsAuthnSDK(app) {
this.clientFingerprint = {
clients: [
- {searchIn:navigator.userAgent, forString:"Edge", identity:"Microsoft Edge"},
- {searchIn:navigator.userAgent, forString:"OPR", identity:"Opera"},
- {searchIn:navigator.userAgent, forString:"Chrome", identity:"Chrome"},
- {searchIn:navigator.vendor, forString:"Apple", identity:"Safari"},
- {searchIn:navigator.userAgent, forString:"Firefox", identity:"Firefox"},
- {searchIn:navigator.userAgent, forString:"Netscape", identity:"Netscape"},
- {searchIn:navigator.userAgent, forString:".NET", identity:"Internet Explorer"},
- {searchIn:navigator.userAgent, forString:"Gecko", identity:"Mozilla"},
- {searchIn:navigator.userAgent, forString:"Mozilla", identity:"Netscape"}
+ { searchIn: navigator.userAgent, forString: "Edge", identity: "Microsoft Edge" },
+ { searchIn: navigator.userAgent, forString: "OPR", identity: "Opera" },
+ { searchIn: navigator.userAgent, forString: "Chrome", identity: "Chrome" },
+ { searchIn: navigator.vendor, forString: "Apple", identity: "Safari" },
+ { searchIn: navigator.userAgent, forString: "Firefox", identity: "Firefox" },
+ { searchIn: navigator.userAgent, forString: "Netscape", identity: "Netscape" },
+ { searchIn: navigator.userAgent, forString: ".NET", identity: "Internet Explorer" },
+ { searchIn: navigator.userAgent, forString: "Gecko", identity: "Mozilla" },
+ { searchIn: navigator.userAgent, forString: "Mozilla", identity: "Netscape" }
],
operatingSystems: [
- {searchIn:navigator.platform, forString:"Win", identity: "Windows"},
- {searchIn:navigator.userAgent, forString:"iPhone", identity: "iPhone OS"},
- {searchIn:navigator.platform, forString:"Mac", identity: "Mac OS"},
- {searchIn:navigator.userAgent, forString:"Android", identity: "Android"},
- {searchIn:navigator.platform, forString:"Linux", identity: "Linux"}
+ { searchIn: navigator.platform, forString: "Win", identity: "Windows" },
+ { searchIn: navigator.userAgent, forString: "iPhone", identity: "iPhone OS" },
+ { searchIn: navigator.platform, forString: "Mac", identity: "Mac OS" },
+ { searchIn: navigator.userAgent, forString: "Android", identity: "Android" },
+ { searchIn: navigator.platform, forString: "Linux", identity: "Linux" }
],
operatingSystemsVersions: [
- {searchString: "Windows NT",delimiter: "."},
- {searchString: "iPhone OS"},
- {searchString: "Android"},
- {searchString: "Mac OS",delimiter: " "},
- {searchString: "Linux"}
+ { searchString: "Windows NT", delimiter: "." },
+ { searchString: "iPhone OS" },
+ { searchString: "Android" },
+ { searchString: "Mac OS", delimiter: " " },
+ { searchString: "Linux" }
],
- init: function() {
+ init: function () {
this.browser = this.searchString(this.clients) || "Unknown browser";
this.OS = this.searchString(this.operatingSystems) || "Unknown OS";
this.OSVersion = this.searchOSVersion(navigator.userAgent) || "";
},
- searchString: function(data) {
+ searchString: function (data) {
for (var i = 0; i < data.length; i++) {
var dataString = data[i].searchIn;
if (dataString) {
@@ -999,14 +942,14 @@ function IdcsAuthnSDK(app) {
}
},
- searchOSVersion: function(dataString) {
+ searchOSVersion: function (dataString) {
var stringIndex, delimIndex, osVersionString;
- for (var i=0; i < this.operatingSystemsVersions.length; i++) {
+ for (var i = 0; i < this.operatingSystemsVersions.length; i++) {
stringIndex = dataString.indexOf(this.operatingSystemsVersions[i].searchString);
if (stringIndex != -1) {
if (typeof this.operatingSystemsVersions[i].delimiter !== 'undefined') { // Returns no version if there's no delimiter. Linux/Android case.
osVersionString = dataString.substring(stringIndex + this.operatingSystemsVersions[i].searchString.length + 1);
- return osVersionString.substring(0,osVersionString.indexOf(this.operatingSystemsVersions[i].delimiter));
+ return osVersionString.substring(0, osVersionString.indexOf(this.operatingSystemsVersions[i].delimiter));
}
else {
return;
diff --git a/idcs-authn-api-signin-app/public/js/loginApp.js b/idcs-authn-api-signin-app/public/js/loginApp.js
index db97263..7a23655 100644
--- a/idcs-authn-api-signin-app/public/js/loginApp.js
+++ b/idcs-authn-api-signin-app/public/js/loginApp.js
@@ -13,49 +13,49 @@ function LoginApp() {
-------------------------------------------- HELPER METHODS ----------------------------------------------------
---------------------------------------------------------------------------------------------------------------- */
-// Removes the spinner from DOM tree.
-// Used, for instance, when an error comes and we have to stop spinning.
-this.removeSpinner = function() {
- let spinner = document.querySelector("div.loader");
- if (spinner != null) {
- spinner.parentNode.removeChild(spinner);
+ // Removes the spinner from DOM tree.
+ // Used, for instance, when an error comes and we have to stop spinning.
+ this.removeSpinner = function () {
+ let spinner = document.querySelector("div.loader");
+ if (spinner != null) {
+ spinner.parentNode.removeChild(spinner);
+ }
+ }
+
+ // Removes button and show spinner.
+ // Mainly used on form submission, where submit button is swapped by spinner.
+ this.removeBtnAndShowSpinner = function (btn) {
+ btn.style.display = 'none';
+ var spinnerDiv = document.createElement('div');
+ spinnerDiv.classList.add('loader');
+ spinnerDiv.data_res = 'loading-msg';
+ spinnerDiv.innerHTML = 'Loading...';
+ // Showing the spinner after btn
+ btn.parentNode.insertBefore(spinnerDiv, btn.nextSibling);
}
-}
-
-// Removes button and show spinner.
-// Mainly used on form submission, where submit button is swapped by spinner.
-this.removeBtnAndShowSpinner = function(btn) {
- btn.style.display = 'none';
- var spinnerDiv = document.createElement('div');
- spinnerDiv.classList.add('loader');
- spinnerDiv.data_res = 'loading-msg';
- spinnerDiv.innerHTML = 'Loading...';
- // Showing the spinner after btn
- btn.parentNode.insertBefore(spinnerDiv, btn.nextSibling);
-}
// Keeps polling for push notifications at the specified interval.
- this.submitPushPoll = function(timeInMillis) {
+ this.submitPushPoll = function (timeInMillis) {
const self = this;
this.logMsg('submitPushPoll');
- this.pushPollInterval = setInterval(function() {
- self.logMsg('timer');
- let signinDiv = document.getElementById("signin-div");
- if ( ( signinDiv ) &&
- ( signinDiv.whichFactorForm === "PUSH" ) ) {
- self.logMsg( signinDiv.whichFactorForm + " is active");
-
- // Issue #1 fix. Change introduced to channel the call to submitPushPoll through buildPayload for adding credentials
- const payload = self.buildPayload("submitPushPoll", signinDiv);
- self.logMsg("Invoking submitPushPoll with payload " + self.mask(payload));
- self.sdk.submitPushPoll(payload);
- // End of fix.
- }
+ this.pushPollInterval = setInterval(function () {
+ self.logMsg('timer');
+ let signinDiv = document.getElementById("signin-div");
+ if ((signinDiv) &&
+ (signinDiv.whichFactorForm === "PUSH")) {
+ self.logMsg(signinDiv.whichFactorForm + " is active");
+
+ // Issue #1 fix. Change introduced to channel the call to submitPushPoll through buildPayload for adding credentials
+ const payload = self.buildPayload("submitPushPoll", signinDiv);
+ self.logMsg("Invoking submitPushPoll with payload " + self.mask(payload));
+ self.sdk.submitPushPoll(payload);
+ // End of fix.
+ }
}, timeInMillis);
}
// Stops polling for push notifications
- this.stopPushPoll = function() {
+ this.stopPushPoll = function () {
if (this.pushPollInterval != null) {
this.removeSpinner();
this.logMsg('Stopping push poll...');
@@ -65,20 +65,20 @@ this.removeBtnAndShowSpinner = function(btn) {
// Displays an HTML snippet allowing users to request a new OTP code.
// Used in EMAIL and SMS.
- this.showResendCodeOption = function(formDiv, obj, timeInMilis) {
+ this.showResendCodeOption = function (formDiv, obj, timeInMilis) {
- if (formDiv && (formDiv.whichFactorForm === "EMAIL" || formDiv.whichFactorForm === "SMS" ) && formDiv.noResend == null) {
+ if (formDiv && (formDiv.whichFactorForm === "EMAIL" || formDiv.whichFactorForm === "SMS") && formDiv.noResend == null) {
let didNotGetMsg = this.localizeMsg(formDiv.whichFactorForm.toLowerCase() + '-did-not-get-msg', 'Did not get the message?');
let resendMsg = this.localizeMsg(formDiv.whichFactorForm.toLowerCase() + '-resend-btn', 'Resend message');
- setTimeout(function() {
+ setTimeout(function () {
self.logMsg(formDiv.whichFactorForm + " factor detected for showing Resend Message option.");
var resendDivElem = document.createElement('div');
resendDivElem.classList.add('sameline');
resendDivElem.innerHTML = '' + didNotGetMsg + ' ' +
- '' + resendMsg + '';
+ '' + resendMsg + '';
// Adding the Resend Option preferably right after the submit button.
let submitBtnElem = formDiv.querySelector("#submit-btn");
@@ -89,7 +89,7 @@ this.removeBtnAndShowSpinner = function(btn) {
formDiv.appendChild(resendDivElem);
}
- formDiv.querySelector("#resend-btn").onclick = function() {
+ formDiv.querySelector("#resend-btn").onclick = function () {
obj.sdk.resendOtp();
};
}, timeInMilis);
@@ -98,18 +98,18 @@ this.removeBtnAndShowSpinner = function(btn) {
// Displays an HTML snippet allowing users to request a new email.
// Mainly used by Forgot Password flow.
- this.showResendEmail = function(formDiv, obj, timeInMilis) {
+ this.showResendEmail = function (formDiv, obj, timeInMilis) {
if (formDiv && formDiv.whichForm != null && formDiv.whichForm === "FORGOT_PASSWORD_FORM") {
var usernameLocal = formDiv.querySelector("#forgotUserName").value;
- let didNotGetMsg = this.localizeMsg('forgot-pw-did-not-get-msg','Did not get the email?');
+ let didNotGetMsg = this.localizeMsg('forgot-pw-did-not-get-msg', 'Did not get the email?');
let resendMsg = this.localizeMsg('forgot-pw-resend-btn', 'Resend email');
- setTimeout(function() {
+ setTimeout(function () {
var resendDivElem = document.createElement('div');
resendDivElem.classList.add('sameline');
resendDivElem.innerHTML = '' + didNotGetMsg + ' ' +
- '' + resendMsg + '';
+ '' + resendMsg + '';
// Adding the Resend Option preferably right after the submit button.
let submitBtnElem = formDiv.querySelector("#submit-btn");
@@ -120,7 +120,7 @@ this.removeBtnAndShowSpinner = function(btn) {
formDiv.appendChild(resendDivElem);
}
- formDiv.querySelector("#resend-btn").onclick = function() {
+ formDiv.querySelector("#resend-btn").onclick = function () {
obj.sdk.forgotPassword(usernameLocal);
};
@@ -128,20 +128,20 @@ this.removeBtnAndShowSpinner = function(btn) {
}
}
- this.showReinputUserName = function(formDiv, obj, timeInMilis) {
+ this.showReinputUserName = function (formDiv, obj, timeInMilis) {
if (formDiv && formDiv.whichForm != null && formDiv.whichForm === "FORGOT_PASSWORD_FORM") {
var usernameLocal = formDiv.querySelector("#forgotUserName").value;
- let didNotGetMsg = this.localizeMsg('forgot-pw-incorrect-username-msg','Incorrect UserName?');
- let resendMsg = this.localizeMsg('forgot-pw-incorrect-username-btn','Fix UserName');
+ let didNotGetMsg = this.localizeMsg('forgot-pw-incorrect-username-msg', 'Incorrect UserName?');
+ let resendMsg = this.localizeMsg('forgot-pw-incorrect-username-btn', 'Fix UserName');
- setTimeout(function() {
+ setTimeout(function () {
formDiv.appendChild(document.createElement('hr'));
var resendDivElem = document.createElement('div');
resendDivElem.classList.add('sameline');
resendDivElem.innerHTML = '' + didNotGetMsg + ' ' +
- '' + resendMsg + '';
+ '' + resendMsg + '';
// Adding the Resend Option preferably right after the submit button.
let submitBtnElem = formDiv.querySelector("#submit-btn");
@@ -152,8 +152,8 @@ this.removeBtnAndShowSpinner = function(btn) {
formDiv.appendChild(resendDivElem);
}
- formDiv.querySelector("#resend-username-btn").onclick = function() {
- obj.displayForgotPassWordForm( );
+ formDiv.querySelector("#resend-username-btn").onclick = function () {
+ obj.displayForgotPassWordForm();
};
}, timeInMilis);
@@ -161,18 +161,18 @@ this.removeBtnAndShowSpinner = function(btn) {
}
// Localizes all labels inside formDiv
- this.localize = function(formDiv) {
+ this.localize = function (formDiv) {
if (resources) {
var resElms = formDiv.querySelectorAll('[data-res]');
for (var n = 0; n < resElms.length; n++) {
var elem = resElms[n];
var resKey = elem.getAttribute('data-res');
if (resKey) {
- if ( resources[resKey] ) {
+ if (resources[resKey]) {
elem.innerHTML = resources[resKey];
}
else {
- this.logWarning( "Translation missing for resource key '" + resKey + "'");
+ this.logWarning("Translation missing for resource key '" + resKey + "'");
}
}
}
@@ -180,18 +180,18 @@ this.removeBtnAndShowSpinner = function(btn) {
} // this.localize
// Returns the message associated with a given key. If the key isn't found, the message (msg) as passed is returned.
- this.localizeMsg = function(resKey, msg) {
+ this.localizeMsg = function (resKey, msg) {
if (resources && resources[resKey]) {
return resources[resKey];
}
else {
- this.logWarning( "Translation missing for resource key '" + resKey + "'");
+ this.logWarning("Translation missing for resource key '" + resKey + "'");
return msg;
}
}
- this.mask = function(msg) {
- let propsToMask = ['username','password','bypasscode','otpcode','questions','deviceid','requeststate','phonenumber','token','authntoken','trusttoken','userid'];
+ this.mask = function (msg) {
+ let propsToMask = ['username', 'password', 'bypasscode', 'otpcode', 'questions', 'deviceid', 'requeststate', 'phonenumber', 'token', 'authntoken', 'trusttoken', 'userid'];
var stars = '***';
var temp;
@@ -223,66 +223,66 @@ this.removeBtnAndShowSpinner = function(btn) {
}
return JSON.stringify(temp);
}
- catch(e) {
+ catch (e) {
return stars;
}
} //this.mask
- this.logMsg = function(msg) {
+ this.logMsg = function (msg) {
if (window.console && this.debugEnabled) {
console.log('LoginApp: ' + msg);
}
} // this.logMsg
- this.logWarning = function(msg) {
+ this.logWarning = function (msg) {
console.log('LoginApp (WARNING): ' + msg);
}
- this.removeSignupFunction = function() {
- Array.prototype.slice.call(document.querySelectorAll('.hidelater')).forEach(function(e) { // Making MS family (IE and Edge) happy
+ this.removeSignupFunction = function () {
+ Array.prototype.slice.call(document.querySelectorAll('.hidelater')).forEach(function (e) { // Making MS family (IE and Edge) happy
e.style.visibility = "hidden";
});
}
- this.replaceDiv = function(divid,replacement,dofocus) {
- // divname is the ID of the div to replace
- // replacement is the Element to replace it with
- // dofocus says "set the focus to the first text input"
+ this.replaceDiv = function (divid, replacement, dofocus) {
+ // divname is the ID of the div to replace
+ // replacement is the Element to replace it with
+ // dofocus says "set the focus to the first text input"
- // Note: for the signin-div the replacement div SHOULD havr a .id prop
- // matching the one that's being replacing
- if ( replacement.id != divid ) {
- this.logMsg( "WARNING: replacement div id=" + replacement.id + " does not match expected value of " + divid );
- }
+ // Note: for the signin-div the replacement div SHOULD havr a .id prop
+ // matching the one that's being replacing
+ if (replacement.id != divid) {
+ this.logMsg("WARNING: replacement div id=" + replacement.id + " does not match expected value of " + divid);
+ }
- // Localizing while replacement div still not visible.
- this.localize(replacement);
+ // Localizing while replacement div still not visible.
+ this.localize(replacement);
- var oldForm = document.getElementById(divid);
- oldForm.parentNode.replaceChild(replacement, oldForm);
+ var oldForm = document.getElementById(divid);
+ oldForm.parentNode.replaceChild(replacement, oldForm);
- this.showResendCodeOption(replacement, this, 10000);
- this.showResendEmail(replacement, this, 10000);
- this.showReinputUserName(replacement, this, 2000);
- this.showSwitchEnrollFactorOption(replacement, this);
+ this.showResendCodeOption(replacement, this, 10000);
+ this.showResendEmail(replacement, this, 10000);
+ this.showReinputUserName(replacement, this, 2000);
+ this.showSwitchEnrollFactorOption(replacement, this);
- // find the first text input field and put the focus there
- if ( dofocus ) {
- div = document.getElementById(divid);
- if ( div ) {
- let firstInput = div.querySelector('input[type="text"]');
- if (firstInput) firstInput.focus();
- }
+ // find the first text input field and put the focus there
+ if (dofocus) {
+ div = document.getElementById(divid);
+ if (div) {
+ let firstInput = div.querySelector('input[type="text"]');
+ if (firstInput) firstInput.focus();
}
+ }
}
// Performs form data validation and style form elements accordingly
- this.validateForm = function(formDiv) {
+ this.validateForm = function (formDiv) {
formDiv.querySelector("#submit-btn").disabled = true;
// Looking for input fields marked as required and empty.
const inputFields = formDiv.getElementsByTagName("INPUT");
var isError = false;
- for (i=0; i < inputFields.length; i++) {
+ for (i = 0; i < inputFields.length; i++) {
this.logMsg('Validating field ' + inputFields[i].id);
if (inputFields[i].required && inputFields[i].value.trim() === '') {
isError = true;
@@ -291,8 +291,8 @@ this.removeBtnAndShowSpinner = function(btn) {
}
}
if (isError) {
- let errorMessage = this.localizeMsg('error-required-fld','Required field empty');
- this.setLoginErrorMessage({code:'', msg:errorMessage});
+ let errorMessage = this.localizeMsg('error-required-fld', 'Required field empty');
+ this.setLoginErrorMessage({ code: '', msg: errorMessage });
formDiv.querySelector("#submit-btn").disabled = false;
return false;
}
@@ -302,8 +302,8 @@ this.removeBtnAndShowSpinner = function(btn) {
}
// Handles focusout event on input fields for styling the field
- this.handleFocusOutEvent = function(elem) {
- elem.addEventListener('focusout', function() {
+ this.handleFocusOutEvent = function (elem) {
+ elem.addEventListener('focusout', function () {
if (elem.value.trim().length == 0) {
elem.classList.add('on__error');
}
@@ -314,9 +314,9 @@ this.removeBtnAndShowSpinner = function(btn) {
}
// Handles onClick event for submiting form data.
- this.handleClickToSubmitEvent = function(formDiv, obj, methodName, includeAuthnFactor) {
+ this.handleClickToSubmitEvent = function (formDiv, obj, methodName, includeAuthnFactor) {
const self = this;
- formDiv.querySelector("#submit-btn").onclick = function() {
+ formDiv.querySelector("#submit-btn").onclick = function () {
if (obj.validateForm(formDiv)) {
const payload = obj.buildPayload(methodName, formDiv);
if (payload) { // Giving a chance for buildPayload to fail.
@@ -331,9 +331,9 @@ this.removeBtnAndShowSpinner = function(btn) {
}
// Handles onKeyPress event for submiting form data.
- this.handleKeyPressToSubmitEvent = function(formDiv, elem, obj, methodName, includeAuthnFactor) {
+ this.handleKeyPressToSubmitEvent = function (formDiv, elem, obj, methodName, includeAuthnFactor) {
const self = this;
- elem.onkeypress = function(event) {
+ elem.onkeypress = function (event) {
if (event.keyCode == 13) {
if (obj.validateForm(formDiv)) {
const payload = obj.buildPayload(methodName, formDiv);
@@ -350,14 +350,14 @@ this.removeBtnAndShowSpinner = function(btn) {
}
// Handles onClick event for handling forgotPassword.
- this.handleClickEvent = function(formDiv, obj) {
- formDiv.querySelector("#signin-forgot-pass").onclick = function() {
- obj.displayForgotPassWordForm(formDiv);
+ this.handleClickEvent = function (formDiv, obj) {
+ formDiv.querySelector("#signin-forgot-pass").onclick = function () {
+ obj.displayForgotPassWordForm(formDiv);
}
}
// Builds the expected credentials payload to the respective API in the SDK, here identified by methodName.
- this.buildPayload = function(methodName, formDiv) {
+ this.buildPayload = function (methodName, formDiv) {
let preferredFactorElem = document.getElementById("preferredFactorOption");
@@ -365,45 +365,67 @@ this.removeBtnAndShowSpinner = function(btn) {
case 'postCreds':
// ER #1. Saving the request origin. This is read later for determining the user preferred factor.
this.setUnPwOrigin("true");
- return {"username": document.getElementById("userid").value, "password": document.getElementById("password").value};
+ var data = {
+ "credentials": {
+ "username": document.getElementById("userid").value,
+ "password": document.getElementById("password").value,
+ "origin": window.location.origin,
+ }
+ }
+ if (document.getElementById("kmsi") != null) {
+ data.credentials["keepMeSignedIn"] = document.getElementById("kmsi").checked;
+ return data;
+ }
+ return data;
- case 'postUserName':
- this.setUnPwOrigin("true");
- return {"username": document.getElementById("userid").value};
+ case 'postUserNameFirst':
+ this.setUnPwOrigin("true");
+ var dataUserNameFirst = {
+ "backUpFactors": true,
+ "credentials": {
+ "username": document.getElementById("userid").value,
+ "origin": window.location.origin,
+ }
+ };
+ if (document.getElementById("kmsi") != null) {
+ dataUserNameFirst.credentials["keepMeSignedIn"] = document.getElementById("kmsi").checked;
+ return dataUserNameFirst;
+ }
+ return dataUserNameFirst;
case 'enrollSecurityQuestions':
- var secQuestions=[];
- var qID=[];
+ var secQuestions = [];
+ var qID = [];
numOfQuestions = formDiv.getElementsByTagName("SELECT");
- for(qi=0;qi' +
+ )
+ ) {
+ var preferredFactorDiv = document.createElement('div');
+ preferredFactorDiv.innerHTML =
+ '';
-
- formDiv.insertBefore(preferredFactorDiv, formDiv.querySelector("#submit-btn"));
- }
- // End of Issue #1
+ 'Set this factor as preferred' +
+ '';
- if (payload.trustedDeviceSettings) {
- var trustedDeviceDiv = document.createElement('div');
- trustedDeviceDiv.innerHTML =
- '';
+
+ // if we're rendering the checkbox it should be unchecked
+ // and the session data should be set to false
+ this.setTrustedDeviceOption(false);
+ // then add a listener when the value changes
+ trustedDeviceDiv.querySelector("#trustedDevice").addEventListener('change', function () {
+ self.setTrustedDeviceOption(this.checked);
+ });
+ formDiv.insertBefore(trustedDeviceDiv, formDiv.querySelector("#submit-btn"));
+ }
+ if (payload.nextOp.indexOf("getBackupFactors") > 0) {
+ // add the alternative button
+ var divHr = document.createElement('div');
+ divHr.classList.add('hr');
+ divHr.innerHTML = 'OR';
+ formDiv.appendChild(divHr);
+
+ let altFactorsMsg = this.localizeMsg('backup-btn', 'Use an Alternative Factor');
+
+ var altFactorsDivElem = document.createElement('div');
+ altFactorsDivElem.classList.add('sameline');
+ altFactorsDivElem.innerHTML = '' + altFactorsMsg + '';
+ formDiv.appendChild(altFactorsDivElem);
+
+ var div = document.createElement("div");
+ div.id = "backupFactorChooser";
+ div.class = "backupFactorChooser";
+ div.className = "backupFactorChooser hidden";
+ formDiv.appendChild(div);
+
+ formDiv.querySelector("#backupfactors-btn").addEventListener('click', function () {
+ this.style.display = "none";
+ var backupchooser = document.getElementById("backupFactorChooser");
+ backupchooser.style.display = "block";
+ backupchooser.innerHTML = '
Loading...
';
+ self.sdk.submitBackupFactors();
+ });
+ }
}
- }
- this.replaceDiv("signin-div",formDiv,true);
- }
- else
- if (step === "enrollment") {
- // SMS special case where we need to 'submitCreds' during enrollment
- if (which === 'SMS' && payload.SMS && payload.SMS.credentials[0] === "otpCode") {
- (this.AuthenticationFactorInfo[which]["loginFormFunction"])(formDiv,payload);
- }
- else {
- (this.AuthenticationFactorInfo[which]["enrollFormFunction"])(formDiv,payload);
+ this.replaceDiv("signin-div", formDiv, true);
}
- this.replaceDiv("signin-div",formDiv,true);
+ else
+ if (step === "enrollment") {
+ // SMS special case where we need to 'submitCreds' during enrollment
+ if (which === 'SMS' && payload.SMS && payload.SMS.credentials[0] === "otpCode") {
+ (this.AuthenticationFactorInfo[which]["loginFormFunction"])(formDiv, payload);
+ }
+ else {
+ (this.AuthenticationFactorInfo[which]["enrollFormFunction"])(formDiv, payload);
+ }
+ this.replaceDiv("signin-div", formDiv, true);
+ }
}
- }
}
// Builds the main form, allowing username/password posting + IDP selection
- // Logic has been moved into buildForm
- this.buildUidPwForm = function(formDiv,IDPdata) {
- this.buildForm(formDiv,"showUidPw",IDPdata,true);
+ // Logic has been moved into buildFirstForm
+ this.buildUidPwForm = function (formDiv, IDPdata) {
+ this.buildFirstForm(formDiv, true, IDPdata);
}
// Builds the main form, allowing IDP selection
- this.buildIdpChooserForm = function(formDiv,IDPdata,isFirstForm) {
- this.buildForm(formDiv,"showIdp",IDPdata,isFirstForm);
- }
-
- // builds the user name first form
- this.buildUidForm = function(formDiv,IDPdata) {
- this.buildForm(formDiv,"showUid",IDPdata,true);
+ this.buildIdpChooserForm = function (formDiv, IDPdata) {
+ this.buildFirstForm(formDiv, false, IDPdata);
}
// this function builds both the UID + PW and/or the IDP chooser form
// this is all in one function to avoid duplicating code or comments
// the boolean showUidPw determines whether to show the uid+pw portion
- this.buildForm = function(formDiv,showField,IDPdata,isFirstForm) {
+ this.buildFirstForm = function (formDiv, showUidPw, IDPdata) {
const self = this;
- var showUidOrUidPwFields = true;
// always show the header message
- if (isFirstForm) {
- formDiv.innerHTML =
- '
Welcome
';
+ formDiv.innerHTML =
+ '
Welcome
'
+ let userNameFirst = IDPdata ? IDPdata.userNameFirst : false;
+ if (userNameFirst) {
+ // IDPdata=IDPdata.payload;
+ IDPdata = IDPdata.payload.IDP;
}
-
// then show the UID + PW form if needed
- switch(showField) {
-
- case "showUidPw":
- formDiv.innerHTML +=
- 'Username' +
- 'Password';
- break;
-
- case "showUid":
- formDiv.innerHTML +=
- 'Username';
- break;
-
- default:
- showUidOrUidPwFields = false;
- }
-
- if (showUidOrUidPwFields) {
+ if (showUidPw) {
+ let keepMeSignedIn = JSON.parse(this.getLoginCtx())["keepMeSignedInEnabled"];
+ let password = "";
+ let checkbox = "";
+ if (keepMeSignedIn) {
+ checkbox = 'Keep me signed in';
+ }
+ if (!userNameFirst) {
+ password = 'Password'
+ }
formDiv.innerHTML +=
- '' +
- '' +
- '
' +
+ enrollmentOptions;
// this code iterates through the buttons and attaches the right function from AuthenticationFactorInfo to it
var buttons = formDiv.getElementsByClassName("submit");
- for( i = 0; i 0) {
+ enrollmentOptions = '
';
}
- this.replaceDiv("signin-div",formDiv,true);
+ this.replaceDiv("signin-div", formDiv, true);
document.getElementById("submit-btn").onclick = function () {
- self.sdk.createToken();
+ if (payload.nextOp.indexOf("createToken") >= 0) {
+ self.sdk.createToken();
+ }
+ else {
+ self.sdk.getEnrollmentFactors();
+ }
};
// Button event listener for enroll in another factors should only be available if enrollment is in nextOp array.
@@ -1139,12 +1226,10 @@ this.removeBtnAndShowSpinner = function(btn) {
self.sdk.getEnrollmentFactors();
};
}
-
-
} // this.displayEnrollmentSuccess
// Initiates enrollment in Time-Based OTP. The user will be sent a QR code to enroll his device (via OMA App) and asked to enter the TOTP.
- this.initEnrollOtpTotp = function(payload) {
+ this.initEnrollOtpTotp = function (payload) {
this.removeSignupFunction();
var formDiv = document.createElement('div');
@@ -1153,21 +1238,21 @@ this.removeBtnAndShowSpinner = function(btn) {
formDiv.id = 'signin-div';
formDiv.innerHTML = '
Loading...
';
- this.replaceDiv("signin-div",formDiv,true);
+ this.replaceDiv("signin-div", formDiv, true);
this.sdk.initEnrollOtpTotp();
} // this.initEnrollOtpTotp
- this.showAppLink = function() {
+ this.showAppLink = function () {
var IS_IPAD = navigator.userAgent.match(/iPad/i) != null,
- IS_IPHONE = !IS_IPAD && ((navigator.userAgent.match(/iPhone/i) != null) || (navigator.userAgent.match(/iPod/i) != null)),
- IS_IOS = IS_IPAD || IS_IPHONE,
- IS_ANDROID = !IS_IOS && navigator.userAgent.match(/android/i) != null,
- IS_MOBILE = IS_IOS || IS_ANDROID;
+ IS_IPHONE = !IS_IPAD && ((navigator.userAgent.match(/iPhone/i) != null) || (navigator.userAgent.match(/iPod/i) != null)),
+ IS_IOS = IS_IPAD || IS_IPHONE,
+ IS_ANDROID = !IS_IOS && navigator.userAgent.match(/android/i) != null,
+ IS_MOBILE = IS_IOS || IS_ANDROID;
// we're mimicking the behavior of the OOTB form here
// iPhones (but not iPads) and android devices will show the link that opens the OMA app
- if ( IS_IPHONE || IS_ANDROID ) {
+ if (IS_IPHONE || IS_ANDROID) {
return true;
}
else {
@@ -1176,31 +1261,34 @@ this.removeBtnAndShowSpinner = function(btn) {
} // this.showAppLink()
// Builds the form for Time-Based OTP, where the user is asked to enter the TOTP that shows up in his/her enrolled device (via OMA App)
- this.buildTOTPForm = function(formDiv,payload) {
-
+ this.buildTOTPForm = function (formDiv, payload) {
// Enrolling
- var qrCode=payload.TOTP.qrCode;
+ var qrCode = payload.TOTP ? payload.TOTP.qrCode : false;
if (qrCode) {
+ if (qrCode.content) {
+ let url = new URL(qrCode.content);
+ this.setSelectedDevice(url.searchParams.get("Deviceid"));
+ }
buttonText = "Enroll";
dataResKey = "enroll-totp-submit-btn";
formDiv.innerHTML += '
Enrolling in time-based OTP
';
- if ( this.showAppLink() ) {
+ if (this.showAppLink()) {
formDiv.innerHTML +=
- '
' +
- 'Scan the QR code with the Oracle Mobile Authenticator App.' +
- 'Then enter the code in the field below.' +
+ 'Scan the QR code with the Oracle Mobile Authenticator App.' +
+ 'Then enter the code in the field below.' +
'
' +
'
' +
- '' +
+ '' +
'
';
}
}
@@ -1219,25 +1307,25 @@ this.removeBtnAndShowSpinner = function(btn) {
'' +
'';
- this.handleClickToSubmitEvent(formDiv,this,'submitTOTP',payload.alternate);
- this.handleKeyPressToSubmitEvent(formDiv,formDiv.querySelector("#otpCode"),this,'submitTOTP',payload.alternate);
+ this.handleClickToSubmitEvent(formDiv, this, 'submitTOTP', payload.alternate);
+ this.handleKeyPressToSubmitEvent(formDiv, formDiv.querySelector("#otpCode"), this, 'submitTOTP', payload.alternate);
} //this.buildTOTPForm
// Builds the form for push notifications enrollment via OMA App.
- this.buildPushEnrollForm = function(formDiv,payload) {
+ this.buildPushEnrollForm = function (formDiv, payload) {
qrCode = payload.PUSH.qrCode;
formDiv.innerHTML += '
Enrolling in Push Notifications
';
- if ( this.showAppLink() ) {
+ if (this.showAppLink()) {
formDiv.innerHTML +=
- '
';
- if (formDiv.whichDisplayName) {
- formDiv.innerHTML +=
+ if (formDiv.whichDisplayName) {
+ formDiv.innerHTML +=
'
' +
- 'Notification sent to the Authenticator App on the following mobile device:' +
- '' + formDiv.whichDisplayName + '' +
+ 'Notification sent to the Authenticator App on the following mobile device:' +
+ '' + formDiv.whichDisplayName + '' +
'
' +
'';
- this.handleClickToSubmitEvent(formDiv,this,'submitAcceptTerms');
+ this.handleClickToSubmitEvent(formDiv, this, 'submitAcceptTerms');
} // buildTermsForm
// Displays a form with backup factors the user can choose from
- this.displayAltFactorsSubform = function(payload) {
+ this.displayAltFactorsSubform = function (payload) {
const self = this;
let otherFactorsDiv = document.createElement('div');
otherFactorsDiv.classList.add("alt-factor-pane");
@@ -1311,23 +1399,24 @@ this.removeBtnAndShowSpinner = function(btn) {
// which factor is currently on screen?
let currentFactor = document.getElementById("signin-div").whichFactorForm;
+
// which device displayName is currently being used?
let displayNameOnScreen = document.getElementById("signin-div").whichDisplayName;
- payload.nextAuthFactors.forEach(function(factor) {
- if ( self.AuthenticationFactorInfo[factor] ) {
+ payload.nextAuthFactors.forEach(function (factor) {
+ if (self.AuthenticationFactorInfo[factor]) {
// Case when user is enrolled with the same factor via multiples devices.
if (payload[factor] && payload[factor].enrolledDevices) {
- for (i=0; i < payload[factor].enrolledDevices.length; i++) {
+ for (i = 0; i < payload[factor].enrolledDevices.length; i++) {
if (displayNameOnScreen != payload[factor].enrolledDevices[i].displayName || currentFactor !== factor) {
let div = document.createElement('div');
//div.classList.add("tooltip");
div.classList.add("alt-factor-row");
div.innerHTML +=
'
' +
- 'Your password has been successfully reset.' +
- 'You can close this window.' +
+ 'Your password has been successfully reset.' +
+ 'You can close this window.' +
'
' +
- '' ;
+ '';
- this.replaceDiv("signin-div",formDiv,true);
+ this.replaceDiv("signin-div", formDiv, true);
} // this.displayResetPassWordSuccess
// This method works as the app main controller, directing requests to the appropriate methods based on the received payload from IDCS.
- this.nextOperation = function(payload) {
-
+ this.nextOperation = function (payload) {
this.logMsg("nextOperation: " + this.mask(payload));
if (payload.requestState && payload.nextOp) {
-
this.setRequestState(payload.requestState);
if (payload.nextOp[0] === 'credSubmit') {
if (payload.nextAuthFactors) {
-
- if (payload.nextAuthFactors.includes('USERNAME_PASSWORD')) {
- this.displayPasswordForm(payload);
+ var sameFactorMultipleDevices = false;
+ payload.nextAuthFactors.forEach(function (factor) {
+ if (payload[factor] && payload[factor].enrolledDevices && payload[factor].enrolledDevices.length > 0) {
+ sameFactorMultipleDevices = true;
+ }
+ });
+ // Fix on bug reported by Pulkit Agarwal on 12/04/18. Used to happen when MFA is active for a Social User that isn't registered in IDCS.
+ // We must send the user to enrollment where enrollment is also in nextOp array.
+ if (payload.nextOp[1] === "enrollment") {
+ this.sdk.getEnrollmentFactors();
+ }
+ // End of fix.
+ // If there's more than one nextAuthFactor or multiple devices for the same factor, we go to alternative factors flow.
+ else if (payload.nextAuthFactors.length > 1 && payload.nextAuthFactors.includes("USERNAME") && payload.nextOp.includes("credSubmit")) {
+ if (!this.getUnPwOrigin() || this.getUnPwOrigin() === "true") {
+ this.setPreferredFactor({ factor: payload.nextAuthFactors[0], displayName: payload.displayName });
+ this.setUnPwOrigin("false");
+ }
+ this.displayForm(payload.nextAuthFactors[0], "submitCreds", payload);
}
- else if (payload.nextAuthFactors.includes('IDP')) {
- this.displayIDPChooserForm(payload);
+ else if (payload.nextAuthFactors.length > 1 || sameFactorMultipleDevices) {
+ this.displayAltFactorsSubform(payload);
}
else {
- var sameFactorMultipleDevices = false;
- payload.nextAuthFactors.forEach(function(factor) {
- if (payload[factor] && payload[factor].enrolledDevices && payload[factor].enrolledDevices.length > 0) {
- sameFactorMultipleDevices = true;
- }
- });
- // Fix on bug reported by Pulkit Agarwal on 12/04/18. Used to happen when MFA is active for a Social User that isn't registered in IDCS.
- // We must send the user to enrollment where enrollment is also in nextOp array.
- if ( payload.nextOp[1] === "enrollment" ) {
- this.displayEnrollmentOptionsForm(payload);
- }
- // End of fix.
- // If there's more than one nextAuthFactor or multiple devices for the same factor, we go to alternative factors flow.
- else if (payload.nextAuthFactors.length > 1 || sameFactorMultipleDevices) {
- this.displayAltFactorsSubform(payload);
- }
-
- else {
- // ER #1
- // Doing this because the API response not always tell whether the factor is the preferred one.
- // Setting the user preferred factor. It's the one returned from username/password submit.
- // We may also come here via Social Login, in which case the origin is undefined.
- if (!this.getUnPwOrigin() || this.getUnPwOrigin() === "true") {
- this.setPreferredFactor({factor:payload.nextAuthFactors[0],displayName:payload.displayName});
- this.setUnPwOrigin("false");
- }
- // End of ER #1.
- this.displayForm(payload.nextAuthFactors[0],"submitCreds",payload);
+ // ER #1
+ // Doing this because the API response not always tell whether the factor is the preferred one.
+ // Setting the user preferred factor. It's the one returned from username/password submit.
+ // We may also come here via Social Login, in which case the origin is undefined.
+ if (!this.getUnPwOrigin() || this.getUnPwOrigin() === "true") {
+ this.setPreferredFactor({ factor: payload.nextAuthFactors[0], displayName: payload.displayName });
+ this.setUnPwOrigin("false");
}
+ // End of ER #1.
+ this.displayForm(payload.nextAuthFactors[0], "submitCreds", payload);
}
}
else
- if (payload.nextOp.indexOf('enrollment') == -1) { // Alternative factors case
- which = Object.keys(self.AuthenticationFactorInfo).filter( function(x) { return x in payload;});
- this.logMsg('nextOperation: Factor is ' + which[0]);
-
- if (typeof which[0] === 'undefined') { // PUSH alternative factor case, when there's no 'PUSH' in the payload.
- if (payload.status === 'pending' && payload.cause && payload.cause[0].code === 'AUTH-1108') {
- let signinDiv = document.getElementById("signin-div");
- if (signinDiv && signinDiv.whichFactorForm === "PUSH") {
- self.logMsg( signinDiv.whichFactorForm + " is active");
- this.logMsg('Waiting on ' + signinDiv.whichFactorForm + '[submitCreds] with payload ' + this.mask(payload));
+ if (payload.nextOp.indexOf('enrollment') == -1) { // Alternative factors case
+ which = Object.keys(self.AuthenticationFactorInfo).filter(function (x) { return x in payload; });
+ this.logMsg('nextOperation: Factor is ' + which[0]);
+
+ if (typeof which[0] === 'undefined') { // PUSH alternative factor case, when there's no 'PUSH' in the payload.
+ if (payload.status === 'pending' && payload.cause && payload.cause[0].code === 'AUTH-1108') {
+ let signinDiv = document.getElementById("signin-div");
+ if (signinDiv && signinDiv.whichFactorForm === "PUSH") {
+ self.logMsg(signinDiv.whichFactorForm + " is active");
+ this.logMsg('Waiting on ' + signinDiv.whichFactorForm + '[submitCreds] with payload ' + this.mask(payload));
+ }
+ else {
+ this.logMsg('About to display form for PUSH [submitCreds] with payload ' + this.mask(payload));
+ this.displayForm("PUSH", "submitCreds", payload);
+ }
+ }
+ }
+ else {
+ this.logMsg('About to display form for ' + which[0] + '[submitCreds] with payload ' + this.mask(payload));
+ if (which[0] === "EMAIL" && sessionStorage.getItem("userNameFirst")) {
+ sessionStorage.removeItem("userNameFirst")
}
else {
- this.logMsg('About to display form for PUSH [submitCreds] with payload ' + this.mask(payload));
- this.displayForm("PUSH","submitCreds",payload);
+ this.displayForm(which[0], "submitCreds", payload);
}
}
- }
- else {
- this.logMsg('About to display form for ' + which[0] + '[submitCreds] with payload ' + this.mask(payload));
- this.displayForm(which[0],"submitCreds",payload);
- }
- }
- else
- if (payload.EMAIL || payload.SECURITY_QUESTIONS || payload.PUSH || payload.TOTP) {
- which = Object.keys(self.AuthenticationFactorInfo).filter( function(x) { return x in payload;});
- this.logMsg('which[0] is ' + which[0]);
- this.displayForm(which[0],"enrollment",payload);
- }
- else
- if ( payload.nextOp[1] === "enrollment" ) {
- which = Object.keys(self.AuthenticationFactorInfo).filter( function(x) { return x in payload;});
- this.displayForm(which[0],"enrollment",payload);
- }
- else
- if (payload.SMS && payload.SMS.credentials[0] === "otpCode") {
- which = Object.keys(self.AuthenticationFactorInfo).filter( function(x) { return x in payload;});
- this.logMsg('which[0] is ' + which[0]);
- this.displayForm(which[0],"enrollment",payload);
- }
- else {
- this.logMsg('Do not know what to do with given payload.');
- }
+ }
+ else
+ if (payload.EMAIL || payload.SECURITY_QUESTIONS || payload.PUSH || payload.TOTP || payload.FIDO_AUTHENTICATOR) {
+ which = Object.keys(self.AuthenticationFactorInfo).filter(function (x) { return x in payload; });
+ this.logMsg('which[0] is ' + which[0]);
+ this.displayForm(which[0], "enrollment", payload);
+ }
+ else
+ if (payload.nextOp[1] === "enrollment") {
+ which = Object.keys(self.AuthenticationFactorInfo).filter(function (x) { return x in payload; });
+ this.displayForm(which[0], "enrollment", payload);
+ }
+ else
+ if (payload.SMS && payload.SMS.credentials[0] === "otpCode") {
+ which = Object.keys(self.AuthenticationFactorInfo).filter(function (x) { return x in payload; });
+ this.logMsg('which[0] is ' + which[0]);
+ this.displayForm(which[0], "enrollment", payload);
+ }
+ else {
+ this.logMsg('Do not know what to do with given payload.');
+ }
}
// Fix on bug reported by Pulkit Agarwal on 12/04/18. Used to happen when there was only one MFA method active.
// Added the check payload.nextOp.indexOf('createToken') >= 0 below.
@@ -1818,7 +1680,7 @@ this.removeBtnAndShowSpinner = function(btn) {
}
}
else if (payload.nextOp[0] === 'acceptTOU') {
- this.displayForm('TOU',"submitCreds",payload);
+ this.displayForm('TOU', "submitCreds", payload);
}
else {
this.logMsg('Do not know what to do with given payload.');
@@ -1830,32 +1692,32 @@ this.removeBtnAndShowSpinner = function(btn) {
-------------------------------------------- HELPER METHODS ----------------------------------------------------
---------------------------------------------------------------------------------------------------------------- */
- this.addErrorDetailsIfAny = function(errorElem, details) {
+ this.addErrorDetailsIfAny = function (errorElem, details) {
if (details != null) {
var detailsDiv = document.createElement('div');
detailsDiv.classList.add('newline');
- for (i=0; i < details.length; i++) {
+ for (i = 0; i < details.length; i++) {
detailsDiv.innerHTML += '' + details[i] + '';
}
errorElem.appendChild(detailsDiv);
}
}
- this.handleBackendError = function(error) {
+ this.handleBackendError = function (error) {
var errorMsg = '';
if (error) {
errorMsg = error.msg;
if (error.code.indexOf('AUTH-1120') != -1) {
- errorMsg = this.localizeMsg('error-AUTH-1120','Invalid state. Please, reinitiate login');
+ errorMsg = this.localizeMsg('error-AUTH-1120', 'Invalid state. Please, reinitiate login');
}
- else if (error.code.indexOf('AUTH-1112') != -1) {
- errorMsg = this.localizeMsg('error-AUTH-1112','Access denied');
+ else if (error.code.indexOf('AUTH-1112') != -1) {
+ errorMsg = this.localizeMsg('error-AUTH-1112', 'Access denied');
}
else if (error.code.indexOf('SDK-AUTH') != -1) {
- errorMsg = this.localizeMsg('error-' + error.code,error.msg);
+ errorMsg = this.localizeMsg('error-' + error.code, error.msg);
}
else if (error.code.indexOf('SSO-') != -1 && error.msg === 'undefined') {
- errorMsg = this.localizeMsg('error-' + error.code,'');
+ errorMsg = this.localizeMsg('error-' + error.code, '');
}
else {
this.logMsg('Passing backend error message as is: ' + errorMsg);
@@ -1864,15 +1726,14 @@ this.removeBtnAndShowSpinner = function(btn) {
return errorMsg;
}
-
- this.changeButtonOnError = function(button) {
+ this.changeButtonOnError = function (button) {
if (button) {
button.style.display = 'block';
button.disabled = false;
}
}
- this.clearErrorsOnScreenIfAny = function() {
+ this.clearErrorsOnScreenIfAny = function () {
var socialErrorElem = document.getElementById("social-login-error-msg");
if (socialErrorElem) {
socialErrorElem.innerHTML = '';
@@ -1883,7 +1744,7 @@ this.removeBtnAndShowSpinner = function(btn) {
}
}
- this.setLoginErrorMessage = function(error) {
+ this.setLoginErrorMessage = function (error) {
this.clearErrorsOnScreenIfAny();
@@ -1918,7 +1779,7 @@ this.removeBtnAndShowSpinner = function(btn) {
}
}
- this.getBackendErrorMsg = function() {
+ this.getBackendErrorMsg = function () {
var error = sessionStorage.getItem('backendError'); // This is set by the server-side backend
if (error) {
sessionStorage.removeItem('backendError');
@@ -1927,30 +1788,30 @@ this.removeBtnAndShowSpinner = function(btn) {
return;
}
- this.setAccessToken = function(at) {
+ this.setAccessToken = function (at) {
return sessionStorage.setItem("signinAT", at);
}
- this.getAccessToken = function() {
+ this.getAccessToken = function () {
return sessionStorage.getItem("signinAT");
}
- this.isIDPUserInIDCS = function() {
+ this.isIDPUserInIDCS = function () {
return sessionStorage.getItem("isIDPUserInIDCS");
}
- this.getIDPAuthnToken = function() {
+ this.getIDPAuthnToken = function () {
return sessionStorage.getItem("IDPAuthnToken");
}
- this.getSocialData = function(){
+ this.getSocialData = function () {
var socialData = {};
socialData.requestState = this.getRequestState();
socialData.userData = JSON.parse(sessionStorage.getItem('social.scimUserAttrs'));
return socialData;
};
- this.isSocialRegistrationRequired = function() {
+ this.isSocialRegistrationRequired = function () {
var isRequired = sessionStorage.getItem("social.needToRegister");
if (isRequired && isRequired === 'true') {
return true;
@@ -1959,136 +1820,146 @@ this.removeBtnAndShowSpinner = function(btn) {
}
};
- this.removeSocialData = function() {
+ this.removeSocialData = function () {
sessionStorage.removeItem('social.scimUserAttrs');
sessionStorage.removeItem('social.needToRegister');
}
- this.setRequestState = function(rs) {
+ this.getLoginCtx = function () {
+ return sessionStorage.getItem("initialState");
+ }
+
+ this.setRequestState = function (rs) {
sessionStorage.setItem("requestState", rs);
}
- this.getRequestState = function() {
+ this.getRequestState = function () {
return sessionStorage.getItem("requestState");
}
- this.getClientId = function() {
+ this.getClientId = function () {
return sessionStorage.getItem("clientId");
}
- this.getInitialState = function() {
- return sessionStorage.getItem("initialState");
+ this.getInitialState = function () {
+ return sessionStorage.getItem("initialState");
}
- this.setTrustedDeviceOption = function(trusted) {
+ this.setTrustedDeviceOption = function (trusted) {
sessionStorage.setItem("isDeviceTrusted", trusted);
}
- this.getTrustedDeviceOption = function() {
+ this.getTrustedDeviceOption = function () {
return sessionStorage.getItem("isDeviceTrusted");
}
// Issue #1
// The following six methods were introduced to support the preferred device feature.
- this.setPreferredFactor = function(factor) {
+ this.setPreferredFactor = function (factor) {
sessionStorage.setItem("preferredFactor", JSON.stringify(factor));
}
- this.getPreferredFactor = function() {
+ this.getPreferredFactor = function () {
return JSON.parse(sessionStorage.getItem("preferredFactor"));
}
// This captures the device object (containing deviceId and displayName) selected by the user.
- this.setSelectedDevice = function(device) {
+ this.setSelectedDevice = function (device) {
this.logMsg('Setting selectedDevice: ' + JSON.stringify(device));
sessionStorage.setItem("device", JSON.stringify(device));
}
- this.getSelectedDevice = function() {
+ this.getSelectedDevice = function () {
var selectedDevice = sessionStorage.getItem("device")
this.logMsg('Getting selectedDevice: ' + selectedDevice);
try {
return JSON.parse(selectedDevice);
}
- catch(e) {
+ catch (e) {
return null;
}
}
// As of IDCS 18.4.2, the preferred factor is the factor returned as a result of successful username/password submit.
// So it must be stored and retrieved at a later time.
- this.setUnPwOrigin = function(flag) {
+ this.setUnPwOrigin = function (flag) {
sessionStorage.setItem("unPwOrigin", flag)
}
- this.getUnPwOrigin = function() {
+ this.getUnPwOrigin = function () {
return sessionStorage.getItem("unPwOrigin");
}
// End of Issue #1.
// This object is used mostly by method displayForm, telling it which form to build.
- const self=this;
+ const self = this;
this.AuthenticationFactorInfo = {
USERNAME_PASSWORD: {
// this one is only used for the initial login screen
label: "Username and password",
- loginFormFunction: function (formdiv,payload) { self.buildUidPwForm(formdiv,payload);},
+ loginFormFunction: function (formdiv, payload) { self.buildUidPwForm(formdiv, payload); },
},
USERNAME: {
- // this one is only used for the initial login screen
label: "Username",
- loginFormFunction: function (formdiv,payload) { self.buildUidForm(formdiv,payload);},
+ loginFormFunction: function (formdiv, payload) { self.buildUidPwForm(formdiv, { 'payload': payload, 'userNameFirst': true }); },
},
IDP: {
// If the admin removes "local IDP" in the IDP Policies then IDCS asks custom login app
// to display only the IDP chooser on the intiial form
label: "Select an IDP",
- loginFormFunction: function (formdiv,payload) { self.buildIdpChooserForm(formdiv,payload.IDP,true);},
+ loginFormFunction: function (formdiv, payload) { self.buildIdpChooserForm(formdiv, payload.IDP); },
},
EMAIL: {
label: "Email",
description: "Send an email with a code to use",
- initEnrollFormFunction: function () { self.displayForm("spinner"), self.sdk.initEnrollOtpEmail();},
- enrollFormFunction: function (formDiv,payload) { self.buildOtpEmailEnrollmentForm(formDiv,payload);},
- loginFormFunction: function (formdiv,payload) { self.buildEmailOtpForm(formdiv,payload);},
+ initEnrollFormFunction: function () { self.displayForm("spinner"), self.sdk.initEnrollOtpEmail(); },
+ enrollFormFunction: function (formDiv, payload) { self.buildOtpEmailEnrollmentForm(formDiv, payload); },
+ loginFormFunction: function (formdiv, payload) { self.buildEmailOtpForm(formdiv, payload); },
+ },
+ FIDO_AUTHENTICATOR: {
+ label: "Fido Authenticator",
+ description: "Fido Authentication",
+ initEnrollFormFunction: function () { self.displayForm("spinner"), self.sdk.initEnrollFido(); },
+ enrollFormFunction: function (formDiv, payload) { self.buildFidoEnrollmentForm(formDiv, payload); },
+ loginFormFunction: function (formdiv, payload) { self.buildFidoAuthenticationForm(formdiv, payload); },
},
SECURITY_QUESTIONS: {
label: "Security Questions",
description: "Security question and answers",
- initEnrollFormFunction: function () { self.displayForm("spinner"), self.sdk.initEnrollSecurityQuestions();},
- enrollFormFunction: function (formDiv,payload) { self.buildSecurityQuestionsEnrollmentForm(formDiv,payload);},
- loginFormFunction: function (formdiv,payload) { self.buildSecQuestionsForm(formdiv,payload);},
+ initEnrollFormFunction: function () { self.displayForm("spinner"), self.sdk.initEnrollSecurityQuestions(); },
+ enrollFormFunction: function (formDiv, payload) { self.buildSecurityQuestionsEnrollmentForm(formDiv, payload); },
+ loginFormFunction: function (formdiv, payload) { self.buildSecQuestionsForm(formdiv, payload); },
},
SMS: {
label: "SMS",
description: "SMS to Mobile Number",
- enrollFormFunction: function (formDiv,payload) { self.buildSMSMobileEnrollmentForm(formDiv,payload);},
- loginFormFunction: function (formdiv,payload) { self.buildSmsOtpForm(formdiv,payload);},
+ enrollFormFunction: function (formDiv, payload) { self.buildSMSMobileEnrollmentForm(formDiv, payload); },
+ loginFormFunction: function (formdiv, payload) { self.buildSmsOtpForm(formdiv, payload); },
},
PUSH: {
label: "Oracle Authenticator App",
description: "Pop-up on the Oracle Mobile Authenticator",
- initEnrollFormFunction: function () { self.displayForm("spinner"), self.sdk.initEnrollPush();},
- enrollFormFunction: function (formDiv,payload) { self.buildPushEnrollForm(formDiv,payload);},
- loginFormFunction: function (formdiv,payload) { self.buildPushLoginForm(formdiv,payload);},
+ initEnrollFormFunction: function () { self.displayForm("spinner"), self.sdk.initEnrollPush(); },
+ enrollFormFunction: function (formDiv, payload) { self.buildPushEnrollForm(formDiv, payload); },
+ loginFormFunction: function (formdiv, payload) { self.buildPushLoginForm(formdiv, payload); },
},
TOTP: {
label: "Time-based OTP",
description: "OTP code from the Oracle Mobile Authenticator or another TOTP app.",
- initEnrollFormFunction: function () { self.displayForm("spinner"), self.sdk.initEnrollOtpTotp();},
+ initEnrollFormFunction: function () { self.displayForm("spinner"), self.sdk.initEnrollOtpTotp(); },
// this is not a mistake - buildTOTPForm does both enroll and regular
- enrollFormFunction: function (formDiv,payload) { self.buildTOTPForm(formDiv,payload);},
- loginFormFunction: function (formdiv,payload,device) { self.buildTOTPForm(formdiv,payload);},
+ enrollFormFunction: function (formDiv, payload) { self.buildTOTPForm(formDiv, payload); },
+ loginFormFunction: function (formdiv, payload, device) { self.buildTOTPForm(formdiv, payload); },
},
BYPASSCODE: {
label: "Bypass code",
description: "Use a security bypass code from your list",
- loginFormFunction: function (formdiv,payload) { self.buildBypasscodeLoginForm(formdiv,payload);},
+ loginFormFunction: function (formdiv, payload) { self.buildBypasscodeLoginForm(formdiv, payload); },
},
TOU: {
label: "Terms of Use",
description: "Terms of Use",
- loginFormFunction: function (formdiv,payload) { self.buildTermsForm(formdiv,payload);},
+ loginFormFunction: function (formdiv, payload) { self.buildTermsForm(formdiv, payload); },
}
// If/when enginering adds a new factor begin by copying and then uncommenting this block
// NEW_ONE: {
@@ -2102,20 +1973,21 @@ this.removeBtnAndShowSpinner = function(btn) {
// }
}
- this.getOperation = function() {
+ this.getOperation = function () {
return sessionStorage.getItem("operation");
}
- this.getToken = function() {
+ this.getToken = function () {
return decodeURIComponent(sessionStorage.getItem("token"));
}
- this.ToBeImplemented = function(which) {
- alert( "Case " + which + " needs to be implemented!");
+ this.ToBeImplemented = function (which) {
+ alert("Case " + which + " needs to be implemented!");
}
this.sdk = new IdcsAuthnSDK(this);
this.sdk.initAuthentication();
+
}; // function loginApp
const loginApp = new LoginApp();
diff --git a/idcs-authn-api-signin-app/run.sh b/idcs-authn-api-signin-app/run.sh
index 0f39795..8269fb9 100644
--- a/idcs-authn-api-signin-app/run.sh
+++ b/idcs-authn-api-signin-app/run.sh
@@ -6,6 +6,7 @@
export IDCS_URL=https://MYTENNANT.identity.oraclecloud.com
export IDCS_CLIENT_ID=1234567890abcdef1234567890abcdef
export IDCS_CLIENT_SECRET=12345678-abcd-1234-abcd-123456789abc
+export NODE_TLS_REJECT_UNAUTHORIZED=0
# if you want to use the app to do self registration uncomment line
# and include the ID of a self registration profile here: