$scope.submit = function (){
// showPin changes, so can not assign the corresponding function
// to submit, instead calling the corresponding function. This may
// lose context of function execution. In this case it's ok becuase there
// is no "this" keyword. But TODO: find a better way to do this.
if (!$scope.accountInfo.firstFactorMobileEnabled || $scope.userInfo.showPin){
submitUserPin();
}
else {
submitUserOnly();
}
}
function submitUserPin() {
if($scope.submitPinForm.$valid){
$scope.PinService.validatePin($scope.userInfo.userId, $scope.userInfo.pin, $scope.userInfo.rememberUserId).then(function(result) {
if(result.data.statusCode === 'SUCCESS'){
$scope.$state.go('auth');
}
else if(result.data.statusCode === 'PIN_AUTHENTICATION_FAILED_MAX_BAD_ATTEMPTS_REACHED'){
if ($scope.userInfo.authType === 'jwt') {
// BRCMVIP-6313 - For Entra ID case, changed the VIP side to display error page
$scope.$state.go('error');
} else {
$scope.$state.go('samlResponse');
}
}
else if(result.data.statusCode === 'SERVER_ERROR'){
$scope.$state.go('error');
}
else if(result.data.messages && result.data.messages.length > 0){
$rootScope.showMessage('error', result.data.messages[0].message);
angular.forEach(result.data.messages, function(obj, index) {
if(obj.field !== undefined && obj.field !== null && obj.field.length > 0) {
messages.addInlineMessage(obj.field, false, result.data.messages[index].message);
}
});
}
});
}else{
$rootScope.showMessage('error', $scope.$filter('translate')('error.pin.invalid.userid.or.pin'));
}
}
function submitUserOnly() {
if($scope.submitPinForm.userId.$valid){
VIPLoginService.getAuthenticationInfo({'userId' : $scope.userInfo.userId}).then(function(result) {
if(result.data.statusCode === 'SUCCESS') {
if(result.data.firstFactorPushCapable && result.data.pinSet){
//set the values in then to avoid user seeing the user noneEditable view.
$scope.$state.go('auth.mobilePush').then(function(){
UserInfo.setUserInfo(result.data);
UserInfo.setUserInfo({'showNonEditableUsername' : true, 'showPin' : true,
'rememberUserId' : $scope.userInfo.rememberUserId});
});
}
else {
UserInfo.setUserInfo({'showNonEditableUsername' : true, 'showPin' : true});
}
}
else if(result.data.statusCode === 'SERVER_ERROR'){
$scope.$state.go('error');
}
else{
UserInfo.setUserInfo({'showNonEditableUsername' : true, 'showPin' : true});
}
}, function(reason) {
$rootScope.clearMessage();
$scope.$state.go('error');
});
}else{
$rootScope.showMessage('error', $scope.$filter('translate')('error.pin.invalid.userid.or.pin')); // TODO: change generic message
}
}
$scope.goToUserOnly = function() {
UserInfo.setUserInfo({'showNonEditableUsername' : false, 'showPin' : false});
}
}]);
'use strict';
angular.module('vipLogin.controllers')
.controller('ResetPinController', ['$scope', '$rootScope', 'pinPolicy', 'messageUtils', function($scope, $rootScope, pinPolicy, messages) {
// Always display PIN Reset Message on this page
$rootScope.showMessage('error', $scope.$filter('translate')('pin.reset.message.onexpiry'));
$scope.pinPolicy = pinPolicy;
$scope.resetPin = function() {
if($scope.resetPinForm.$valid){
$scope.PinService.resetPin($scope.userId, $scope.pin.currentPin, $scope.pin.newPin).then(function(result) {
if(result.data.statusCode === 'SUCCESS'){
$scope.$state.go('samlResponse');
}
else if(result.data.statusCode === 'PIN_AUTHENTICATION_FAILED_MAX_BAD_ATTEMPTS_REACHED'){
if ($scope.userInfo.authType === 'jwt') {
// BRCMVIP-6313 - For Entra ID case, changed the VIP side to display error page
$scope.$state.go('error');
} else {
$scope.$state.go('samlResponse');
}
}
else{
$rootScope.showMessage('error', result.data.messages[0].message);
angular.forEach(result.data.messages, function(obj, index) {
if(obj.field !== undefined && obj.field !== null && obj.field.length > 0) {
messages.addInlineMessage(obj.field, false, result.data.messages[index].message);
}
});
}
});
}
else {
$rootScope.showMessage('error', $scope.$filter('translate')('error.pin.invalid.entry'));
}
};
}]);
'use strict';
angular.module('vipLogin.controllers')
.controller("FidoController", ["$scope", "$rootScope", "$timeout", "vip", 'VIPLoginService', 'FidoService', function ($scope, $rootScope, $timeout, vip, VIPLoginService, FidoService) {
$scope.mobileFallback = $scope.userInfo.mobileFallbackEnabled;
$scope.isBlockVipLoginRegEnabled = $scope.userInfo.blockVipLoginRegEnabled;
$scope.fidoService = FidoService;
$scope.preAuthID = "testID";
$scope.fidoSelection = $scope.$filter('translate')('fido.option2');
// ????????
VIPLoginService.setSAMResponseToSSP('false');
$scope.userInfo.shouldRedirectToNgSSSP = 'false';
if ($scope.userInfo.securityKeyEnabled) {
$scope.fidoSelection = $scope.$filter('translate')('fido.option1');
}
// May not need this as done in the ngHeader directive
VIPLoginService.getCobrandingInfo().then(function(result){
$scope.cobrandingEnabled=result.data.cobrandingEnabled;
if($scope.cobrandingEnabled){
$scope.cobrandingUrl=result.data.cobrandingImageURL;
}else{
$scope.cobrandingUrl="app/images/SymcLogo150x40.jpg";
}
});
$scope.modalShown = false;
$scope.toggleModal = function() {
$scope.modalShown = !$scope.modalShown;
};
$scope.reloadRedirecttoNgSSPLink = function () {
if ($scope.userInfo.useOldSSP === 'true') {
$scope.modalShown = !$scope.modalShown;
} else {
VIPLoginService.setSAMResponseToSSP('true');
$scope.userInfo.shouldRedirectToNgSSSP = 'true';
}
}
$scope.stateSwitch = function(result) {
if (result.data.requestedClientView == "RESET_PIN") {
// Authentication was successful but there is still a task to be performed before a successful response
$scope.$state.go('pin.reset');
if (result.data.messages) {
$rootScope.addPendingMessage('error', result.data.messages[0].message);
}
}
else if (result.data.statusCode === 'SUCCESS') {
// Redirect the uer back to the issuer
//$scope.$state.go('samlResponse');
if ($scope.userInfo.shouldRedirectToNgSSSP === 'true' && ($scope.userInfo.authType === 'SAM' || $scope.userInfo.authType === 'oidc')) {
// Redirect the user to My VIP
VIPLoginService.setSAMResponseToSSP('false');
$scope.userInfo.shouldRedirectToNgSSSP = 'false';
$scope.$state.go('newUserGoToSsp');
} else {
// OIDC integration
if ($scope.userInfo.authType === 'oidc') {
$scope.$state.go('oidcResponse');
} else {
// Redirect the uer back to the issuer
$scope.$state.go('samlResponse');
}
}
}
else if (result.data.statusCode === 'STRONG_AUTHENTICATION_FAILED_MAX_BAD_ATTEMPTS_REACHED') {
if ($scope.userInfo.authType === 'jwt') {
// BRCMVIP-6313 - For Entra ID case, changed the VIP side to display error page
$scope.$state.go('error');
} else {
$scope.$state.go('samlResponse');
}
}
else{
$rootScope.showMessage('error', result.data.messages[0].message);
angular.forEach(result.data.messages, function(obj, index) {
if(obj.field !== undefined && obj.field !== null && obj.field.length > 0) {
messages.addInlineMessage(obj.field, false, result.data.messages[index].message);
}
});
}
};
$scope.skipPasswordlessAuth = function() {
if ($scope.userInfo.requestedClientView == "OOB") {
$scope.$state.go('auth.oobOptions');
}
// If the required information for mobile or RC is not found, go directly to OTP
else if(!$scope.userInfo.viploginAppID || !$scope.userInfo.customerJurhash){
$scope.$state.go('auth.securityCode');
}
// When user has mobile push enabled
else if($scope.userInfo.mobilePushEnabled) {
$scope.$state.go('auth.mobilePush');
}
// When user cannot use any security code type creds (auth level doesn't allow it)
else if(!$scope.userInfo.securityCodeTypeCredEnabled) {
$scope.$state.go('auth.registerCredentialNoSecurityCode');
}
else {
$scope.$state.go('auth.securityCode');
}
}
$scope.submitPasswordlessAuth = function() {
var credType="SECURITY_KEY";
var selectedCredType = $scope.fidoSelection.toUpperCase()
if( selectedCredType === "BIOMETRIC") {
credType = selectedCredType;
}
$scope.fidoService.preAuthenticateFido(credType).then(function (result) {
var domainName = $scope.getDomainName();
var preAuthChallenge = result.data.preAuthMessage;
$scope.preAuthID = result.data.preAuthID;
var data = JSON.parse(atob(preAuthChallenge))
data['rpId'] = domainName;
var publicKey = $scope.preformatGetAssertReq(data);
return navigator["credentials"].get({ "publicKey": publicKey }).then(
function (response) {
var getAssertionResponse = $scope.publicKeyCredentialToJSON(response);
var assertionJsonStr = JSON.stringify(getAssertionResponse)
var encodedMessage = btoa(assertionJsonStr);
if ($scope.userInfo.authType === 'oidc') {
// Fingerprint biometric
VIPLoginService.setAuthenticationMethod('FIDO');
}
$scope.fidoService.authenticateFido(encodedMessage, $scope.preAuthID).then(function(result){
$scope.stateSwitch(result);
}).catch(function(err) {
$scope.$apply(function(){
$rootScope.showMessage('error', err.message);
});
});
}
).catch(function(err) {
$scope.$apply(function(){
$rootScope.showMessage('error', err.message);
});
});
});
return;
};
$scope.goOtherCreds = function () {
$scope.usSpinnerService.spin('spinnerRef');
$timeout(function () {
$scope.usSpinnerService.stop('spinnerRef');
$scope.$state.go('auth.securityCode');
}, 1000);
};
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
// Use a lookup table to find the index.
var lookup = new Uint8Array(256);
for (var i = 0; i < chars.length; i++) {
lookup[chars.charCodeAt(i)] = i;
}
$scope.encode = function (arraybuffer) {
var bytes = new Uint8Array(arraybuffer),
i, len = bytes.length, base64url = '';
for (i = 0; i < len; i += 3) {
base64url += chars[bytes[i] >> 2];
base64url += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];
base64url += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];
base64url += chars[bytes[i + 2] & 63];
}
if ((len % 3) === 2) {
base64url = base64url.substring(0, base64url.length - 1);
} else if (len % 3 === 1) {
base64url = base64url.substring(0, base64url.length - 2);
}
return base64url;
}
$scope.decode = function (base64string) {
var bufferLength = base64string.length * 0.75,
len = base64string.length, i, p = 0,
encoded1, encoded2, encoded3, encoded4;
var bytes = new Uint8Array(bufferLength);
for (i = 0; i < len; i += 4) {
encoded1 = lookup[base64string.charCodeAt(i)];
encoded2 = lookup[base64string.charCodeAt(i + 1)];
encoded3 = lookup[base64string.charCodeAt(i + 2)];
encoded4 = lookup[base64string.charCodeAt(i + 3)];
bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
}
return bytes.buffer
}
$scope.getDomainName = function () {
var hostName = document.location.hostname
return hostName.substring(hostName.lastIndexOf(".", hostName.lastIndexOf(".") - 1) + 1);
}
$scope.publicKeyCredentialToJSON = function (pubKeyCred) {
if (pubKeyCred instanceof Array) {
var arr = [];
for (var i=0; i < pubKeyCred.length; i++)
arr.push($scope.publicKeyCredentialToJSON(pubKeyCred[i]));
return arr
}
if (pubKeyCred instanceof ArrayBuffer) {
$scope.encode(pubKeyCred);
return $scope.encode(pubKeyCred)
}
if (pubKeyCred instanceof Object) {
var obj = {};
for (var key in pubKeyCred) {
obj[key] = $scope.publicKeyCredentialToJSON(pubKeyCred[key])
}
return obj
}
return pubKeyCred
}
/**
* Decodes arrayBuffer required fields.
*/
$scope.preformatGetAssertReq = function (getAssert) {
getAssert["challenge"] = $scope.decode(getAssert["challenge"]);
/*for (var allowCred of getAssert["allowCredentials"]) {
allowCred["id"] = $scope.decode(allowCred["id"]);
}*/
var allowedCreds = getAssert["allowCredentials"];
for (var i = 0; i< allowedCreds.length; i++) {
allowedCreds[i].id = $scope.decode(allowedCreds[i].id);
}
return getAssert
}
$scope.goFidoAuth = function () {
$scope.usSpinnerService.spin('spinnerRef');
$timeout(function () {
$scope.usSpinnerService.stop('spinnerRef');
}, 1000);
if ($scope.userInfo && $scope.userInfo.fidoEnabled == true) {
var domainName = $scope.getDomainName();
var data = JSON.parse(atob($scope.userInfo.fidoPreAuthenticationChallenge))
data['rpId'] = domainName;
var navigatorCallback = function (response) {
var getAssertionResponse = $scope.publicKeyCredentialToJSON(response);
var assertionJsonStr = JSON.stringify(getAssertionResponse)
console.log(assertionJsonStr);
var encodedMessage = btoa(assertionJsonStr);
console.log(encodedMessage);
$scope.ValidationService.validateFido(encodedMessage).then(function (result) {
$scope.stateSwitch(result);
});
}
var publicKey = $scope.preformatGetAssertReq(data);
return navigator["credentials"].get({ "publicKey": publicKey }).then(
navigatorCallback
);
}
}
}]);
'use strict';
angular.module('vipLogin.controllers')
.controller("SecurityCodeController", ["$scope", "$rootScope", "$timeout", "vip", 'VIPLoginService', function ($scope, $rootScope, $timeout, vip, VIPLoginService) {
$scope.mobileFallback = $scope.userInfo.mobileFallbackEnabled;
$scope.isBlockVipLoginRegEnabled = $scope.userInfo.blockVipLoginRegEnabled;
$scope.usedOOBAuthenticationMethod = $scope.userInfo.usedOOBAuthenticationMethod;
// AuthnReq flow with onlyFidoCred, decision deferred to here to check the user OOB options
if (!$scope.userInfo.fidoAllowed && $scope.userInfo.onlyFidoCred) {
if ($scope.userInfo.authType === 'SAM' && $scope.userInfo.options == null) {
// This flow is programatically triggered the OOB flow without the user to click
// Don't have a security code'. For the SAM flow, the OOB controller visited
// twice then then display OOB options for the user.
// After the user clicked the selected OOB option, the oobResponse will redirect
// to this SC controller again. So, adding the check for the userInfo.option
// can tell if this is the user clicked the selected options after 2 rounds of
// Ping Pong/OOB flow.
$scope.$state.go('auth.oobOptions');
}
}
// May not need this as done in the ngHeader directive
VIPLoginService.getCobrandingInfo().then(function(result){
$scope.cobrandingEnabled=result.data.cobrandingEnabled;
if($scope.cobrandingEnabled){
$scope.cobrandingUrl=result.data.cobrandingImageURL;
}else{
$scope.cobrandingUrl="app/images/SymcLogo150x40.jpg";
}
});
$scope.modalShown = false;
$scope.toggleModal = function() {
$scope.modalShown = !$scope.modalShown;
};
$scope.reloadRedirecttoNgSSPLink = function () {
// BRCMVIP-4261 Oidc loop
if ($scope.userInfo.authType === 'jwt' || $scope.userInfo.authType === 'oidc') {
VIPLoginService.setJwtResponseToSSP('true');
} else {
VIPLoginService.setSAMResponseToSSP('true');
}
$scope.userInfo.shouldRedirectToNgSSSP = 'true';
}
$scope.hashCode = function(str) {
var hash = 0;
for (var i = 0, len = str.length; i < len; i++) {
var chr = str.charCodeAt(i);
hash = (hash << 5) - hash + chr;
hash |= 0; // Convert to 32bit integer
}
return "" + hash;
}
$scope.generateHMACMD5 = function(data, secretKey) {
var jsonString = JSON.stringify(data );
return $scope.hashCode(jsonString + secretKey);
}
$scope.checkResponseModified = function(result) {
var vipContentLength = result.headers('vip-content-length');
var generatedContentLength = $scope.generateHMACMD5(result.data, $scope.userInfo.vipContentLengthSecretKey);
// If response is modified
if (vipContentLength !== generatedContentLength) {
var errorResponse = {
"messages": [
{
"field": null,
"message": ["You could not be signed in at this time. Contact your administrator for assistance."]
}
],
"numberOfBadAttempts": 1,
"requestedClientView": "",
"statusCode": "ERROR"
};
// override the response with error
result.data = errorResponse;
}
}
$scope.stateSwitch = function(result) {
if (result.data.requestedClientView == "RESET_PIN") {
// Authentication was successful but there is still a task to be performed before a successful response
$scope.$state.go('pin.reset');
if (result.data.messages) {
$rootScope.addPendingMessage('error', result.data.messages[0].message);
}
}
else if (result.data.statusCode === 'SUCCESS') {
if ($scope.IntelligentAuthenticationService.getRememberDevice()) {
$scope.$state.go('auth.rememberDeviceConfirmation');
} else {
// For the Azure case, the destination to redirect the SAML assertion
// is done and the server side via 'samlResponse'
// For SAM case, we need to execute the ping-pong flow after the 2FA SUCCESS
// So, the destination to redirect is done here.
// OIDC integration
if ($scope.userInfo.shouldRedirectToNgSSSP === 'true' && ($scope.userInfo.authType === 'SAM' || $scope.userInfo.authType === 'oidc')) {
// Redirect the user to My VIP
VIPLoginService.setSAMResponseToSSP('false');
$scope.userInfo.shouldRedirectToNgSSSP = 'false';
$scope.$state.go('newUserGoToSsp');
} else {
// OIDC integration
if ($scope.userInfo.authType === 'oidc') {
$scope.$state.go('oidcResponse');
} else {
// Redirect the uer back to the issuer
$scope.$state.go('samlResponse');
}
}
}
}
else if (result.data.statusCode === 'STRONG_AUTHENTICATION_FAILED_MAX_BAD_ATTEMPTS_REACHED') {
if ($scope.userInfo.authType === 'oidc') {
$scope.$state.go('oidcResponse');
} else if ($scope.userInfo.authType === 'jwt') {
// BRCMVIP-6313 - For Entra ID case, changed the VIP side to display error page
$scope.$state.go('error');
} else {
// Redirect the uer back to the issuer
$scope.$state.go('samlResponse');
}
}
else{
$rootScope.showMessage('error', result.data.messages[0].message);
angular.forEach(result.data.messages, function(obj, index) {
if(obj.field !== undefined && obj.field !== null && obj.field.length > 0) {
messages.addInlineMessage(obj.field, false, result.data.messages[index].message);
}
});
}
};
$scope.vip = vip; // vip is injected from resolve
$scope.vip.api.df.set({
onSuccess: function(data){
// Stop the spinner
$scope.usSpinnerService.stop('spinnerRef');
// Validate the ticket returned in the message. It must wrap that in a promise
$scope.ValidationService.validate(data.ticket, $scope.VIPLoginService.rememberUserId).then(function(result) {
$scope.checkResponseModified(result);
$scope.stateSwitch(result);
});
},
onFailure: function(){
// Stop the spinner
$scope.usSpinnerService.stop('spinnerRef');
},
onError: function(){
// Stop the spinner
$scope.usSpinnerService.stop('spinnerRef');
}
});
$scope.submitSecurityCode = function() {
if($scope.securityCodeForm.$valid){
// Skip the remember device before redirecting to the My VIP so as to be consistent with old SSP flow.
if ($scope.userInfo.shouldRedirectToNgSSSP === 'true' && $scope.userInfo.authType === 'SAM') {
$scope.ValidationService.validate($scope.securityCode).then(function(result) {
$scope.checkResponseModified(result);
$scope.stateSwitch(result);
});
} else {
// Removed iaEnabled checking - VIPAWS-17208
if ($scope.userInfo.deviceFingerprintEnabled) {
$scope.IntelligentAuthenticationService.setCode($scope.securityCode);
if ($scope.$cookies.getObject($scope.userInfo.userId) == 'neverRememberDevice') {
$scope.usSpinnerService.spin('spinnerRef');
$scope.IntelligentAuthenticationService.setRememberDevice(false);
$scope.IntelligentAuthenticationService.validate($scope.vip, $scope.userInfo, true);
} else if ($scope.IntelligentAuthenticationService.getDeviceName() || !($scope.IntelligentAuthenticationService.getShowRememberDevice())) {
// Start the spinner
$scope.usSpinnerService.spin('spinnerRef');
$scope.IntelligentAuthenticationService.validate($scope.vip, $scope.userInfo, true);
} else if ($scope.userInfo.adminDeletionPolicy && ($scope.userInfo.maxConnectedBindings <= $scope.userInfo.connectedBindings)) {
$scope.$state.go('auth.rememberDeviceBindingError');
} else {
$scope.$state.go('auth.rememberDeviceProvision');
}
} else {
$scope.ValidationService.validate($scope.securityCode).then(function (result) {
$scope.checkResponseModified(result);
$scope.stateSwitch(result);
});
}
}
// OIDC integration
if ($scope.userInfo.authType === 'oidc' && !$scope.usedOOBAuthenticationMethod) {
VIPLoginService.setAuthenticationMethod('OTP');
}
}
};
$scope.goOobOptions = function() {
$scope.usSpinnerService.spin('spinnerRef');
$timeout(function() {
$scope.usSpinnerService.stop('spinnerRef');
$scope.$state.go('auth.oobOptions');
}, 1000);
};
var toMyVIP = $scope.isDisplayRedirectToMyVIPNote();
if (!$scope.mobileFallback) {
if (!$scope.userInfo.hasCredentials) {
// If mobileFallback disabled, and the user click register later and come to this page
// we want to block it.
// also, another case is: For a new user and click register now, then OOB page which user
// clicked sendOOB, then brought back to here.
if (toMyVIP) {
// register now case, setRegistrationForNewUser() already called to send to My VIP
} else if ($scope.userInfo.shouldRedirectToNgSSSP === 'true') {
// New user without credential and landed OOB then here to enter received OTP
} else {
if ($scope.userInfo.authType === 'oidc') {
VIPLoginService.setOidcError('access_denied', 'The authentication failed.');
$scope.$state.go('oidcResponse');
} else {
$scope.$state.go('policydenied');
}
}
} else if (!toMyVIP && $scope.userInfo.hasCredentials) {
// This is the corner case: MO push enabled, MO Fallback disabled and no credential binding
// (either no credential bound or all previous bound credentials not in Enabled state)
if ($scope.userInfo.authType === 'oidc') {
VIPLoginService.setOidcError('access_denied', 'The authentication failed.');
$scope.$state.go('oidcResponse');
} else {
$scope.$state.go('policydenied');
}
} else {
// During the Mobile Push, Add or Manager credentials clicked
// we will allow the OTP for registration.
}
}
}]);
'use strict';
angular.module('vipLogin.controllers')
.controller("RegisterCredentialController", ["$scope", 'VIPLoginService', function ($scope, VIPLoginService) {
$scope.modalShown = false;
$scope.customDisableRegMessage = $scope.userInfo.customDisableRegMessage
$scope.toggleModal = function() {
$scope.modalShown = !$scope.modalShown;
};
$scope.perform2FABeforeRegisterCredential = function() {
if ($scope.userInfo.useOldSSP === 'true') {
$scope.modalShown = !$scope.modalShown;
} else {
if ($scope.userInfo.require2FAForFirstTimeLogin) {
// Set to 'true' to preserve the redirecting note
// after the OOB page reload after ping-pong flow
VIPLoginService.setSAMResponseToSSP('true');
$scope.userInfo.shouldRedirectToNgSSSP = 'true';
$scope.$state.go('auth.oobOptions');
} else {
VIPLoginService.setSAMResponseToSSP('false');
$scope.userInfo.shouldRedirectToNgSSSP = 'false';
$scope.$state.go('newUserGoToSsp');
}
}
};
$scope.registerLater = function() {
// For new user, the OTP for registration indicator will no credential binding from context
VIPLoginService.setRegistrationForNewUser('true');
$scope.$state.go('auth.securityCode');
};
}]);
'use strict';
angular.module('vipLogin.controllers')
.controller("RememberDeviceController", ["$scope", "$rootScope", "vip", 'VIPLoginService', function ($scope, $rootScope, vip, VIPLoginService) {
var fallbackState = $scope.userInfo.mobilePushEnabled ? 'auth.mobilePush' : 'auth.securityCode';
fallbackState = $scope.userInfo.hasCredentials ? fallbackState : 'auth.registerCredential';
fallbackState = $scope.userInfo.securityCodeTypeCredEnabled ? fallbackState: 'auth.registerCredentialNoSecurityCode';
fallbackState = $scope.userInfo.hasAllowedAuthMethods ? fallbackState: 'samlResponse';
$scope.vip = vip; // vip is injected from resolve
$scope.deviceName = $scope.IntelligentAuthenticationService.getDeviceName();
$scope.translationData = {
maxConnectedBindings: $scope.userInfo.maxConnectedBindings
};
$scope.vip.api.df.set({
onSuccess: function(data){
// Stop the spinner
$scope.usSpinnerService.stop('spinnerRef');
// Validate the ticket returned in the message. It must wrap that in a promise
$scope.ValidationService.validate(data.ticket, $scope.VIPLoginService.rememberUserId).then(function(result) {
if ($scope.userInfo.passive) {
$scope.$state.go('samlResponse');
}
else if (result.data.requestedClientView == "RESET_PIN") {
// Authentication was successful but there is still a task to be performed before a successful response
$scope.$state.go('pin.reset');
if (result.data.messages) {
$rootScope.addPendingMessage('error', result.data.messages[0].message);
}
}
else if (result.data.statusCode === 'SUCCESS') {
if ($scope.IntelligentAuthenticationService.getRememberDevice()) {
$scope.$state.go('auth.rememberDeviceConfirmation');
} else {
$scope.$state.go('samlResponse');
}
}
else {
// When authenticate User failed with the ticket, return back to security code view
if(fallbackState == 'auth.securityCode' && !$scope.userInfo.hasSecurityCredential){
$scope.VIPLoginService.getOobInfo().then(function(result){
if(result.data.options != null && result.data.options.length==1 && result.data.options[0].type !='VOICE'){
$scope.VIPLoginService.sendOob({'selectedOobId' : result.data.options[0].id }).then(function(result){
$scope.addPendingMessage(angular.lowercase(result.data.statusCode), result.data.messages[0].message[0]);
$scope.$state.go('auth.securityCode');
});
}else{
$scope.$state.go('auth.oobOptions');
}
});
}
else {
$scope.$state.go(fallbackState);
}
if (result.data.messages) {
$rootScope.addPendingMessage('error', result.data.messages[0].message);
}
}
});
},
onFailure: function(data){
// Stop the spinner
$scope.usSpinnerService.stop('spinnerRef');
if ($scope.userInfo.passive) {
$scope.$state.go('samlResponse');
} else {
$scope.IntelligentAuthenticationService.setShowRememberDevice(data.showRememberDevice);
if(fallbackState == 'auth.securityCode' && !$scope.userInfo.hasSecurityCredential){
$scope.VIPLoginService.getOobInfo().then(function(result){
if(result.data.options != null && result.data.options.length==1 && result.data.options[0].type !='VOICE'){
$scope.VIPLoginService.sendOob({'selectedOobId' : result.data.options[0].id }).then(function(result){
$scope.addPendingMessage(angular.lowercase(result.data.statusCode), result.data.messages[0].message[0]);
$scope.$state.go('auth.securityCode');
});
}else{
$scope.$state.go('auth.oobOptions');
}
});
}
else {
$scope.$state.go(fallbackState);
}
if ($scope.$state.current.name == "auth.rememberDevice") {
if ($scope.userInfo.connectedBindings > 0) {
if (data.showRememberDevice) {
$rootScope.addPendingMessage('warning', $scope.$filter('translate')('error.remember.device.unrecognized.device.fail'));
} else {
$rootScope.addPendingMessage('warning', $scope.$filter('translate')('error.remember.device.fail'));
}
}
}
}
},
onError: function(){
// Stop the spinner
$scope.usSpinnerService.stop('spinnerRef');
if ($scope.userInfo.passive) {
$scope.$state.go('samlResponse');
} else {
$rootScope.addPendingMessage('error', $scope.$filter('translate')('error.remember.device.error'));
$scope.$state.go(fallbackState);
}
}
});
$scope.rememberDeviceSubmit = function () {
if ($scope.rememberDeviceSubmitForm.$valid) {
$scope.usSpinnerService.spin('spinnerRef');
$scope.IntelligentAuthenticationService.setRememberDevice(true);
$scope.IntelligentAuthenticationService.setDeviceName($scope.deviceName);
$scope.IntelligentAuthenticationService.validate($scope.vip, $scope.userInfo, true);
}
};
$scope.securityCodeSubmit = function (never) {
$scope.usSpinnerService.spin('spinnerRef');
if (never) {
var current = new Date();
var expiredDate = new Date(current);
// set neverRememberDevice for 2 years
expiredDate.setMonth(current.getMonth() + 24);
$scope.$cookies.putObject($scope.userInfo.userId, 'neverRememberDevice', { path: '/viplogin', expires: expiredDate });
}
$scope.IntelligentAuthenticationService.setShowRememberDevice(false);
$scope.IntelligentAuthenticationService.setRememberDevice(false);
$scope.IntelligentAuthenticationService.validate($scope.vip, $scope.userInfo, true);
};
if ($scope.$state.current.name == "auth.rememberDevice") {
$scope.usSpinnerService.spin('spinnerRef');
$scope.IntelligentAuthenticationService.validate($scope.vip, $scope.userInfo, false);
// Not matched AMR value in RFC8176 - use OTP for now
VIPLoginService.setAuthenticationMethod('OTP');
}
}]);
'use strict';
/**
* Due to the XSRF token verification, this is changed in 2015_5 to use $http instead of $window.
* It was using $window.location.href, but $window.location.href does not add XSRF token header,
* Therefore, changed it to use $http.
*
* In this approach, I bind this response html to a div in the template. So that when the response
* html loaded to the div, that div has one line of JavaScript to trigger the form submit. This
* will behavior as the same as redirect from the browser URL.
*
* Note: This still does not solve the initial action which when SAML comes in, it should check the
* XSRF token too. This will be done in the future release.
*
*/
angular.module('vipLogin.controllers')
.controller("SamlResponseController", ['$http', '$scope', '$sce', function($http, $scope, $sce){
$http.get('/viplogin/saml2/post/samlresponse').then(function(response){
$scope.response = $sce.trustAsHtml(response.data);
});
}]).controller("CancelResponseController", ['$http', '$scope', '$sce', '$window', function($http, $scope, $sce, $window){
$http.post('/viplogin/assertiontype').then(function(response) {
if (response.status === 200) {
if (response.data.contextFound === "TRUE") {
if (response.data.assertionType === "ASSERTION_LOGIN" || response.data.assertionType === "ASSERTION_LOGIN_EXTERNAL") {
$http.post('/viplogin/saml2/post/cancelandreturnegidp').then(function (response) {
$window.location.href = response.data;
});
} else {
$http.get('/viplogin/saml2/post/cancelandreturn').then(function (response) {
$scope.response = $sce.trustAsHtml(response.data);
});
}
} else {
// No cancelUrl to be redirected as the session has expired
$scope.response = $sce.trustAsHtml(response.data);
}
} else {
$scope.response = $sce.trustAsHtml(response.data);
}
});
}]).controller("PasswordResponseController", ['$http', '$scope', '$sce', '$window', function($http, $scope, $sce, $window){
$http.post('/viplogin/assertiontype').then(function(response) {
if (response.status === 200) {
if (response.data.contextFound === "TRUE") {
if (response.data.assertionType === "ASSERTION_LOGIN" || response.data.assertionType === "ASSERTION_LOGIN_EXTERNAL") {
$http.post('/viplogin/saml2/post/passwordReturnToEgIdp').then(function (response) {
$window.location.href = response.data;
});
} else {
$http.get('/viplogin/saml2/post/cancelandreturn').then(function (response) {
$scope.response = $sce.trustAsHtml(response.data);
});
}
} else {
// No cancelUrl to be redirected as the session has expired
$scope.response = $sce.trustAsHtml(response.data);
}
} else {
$scope.response = $sce.trustAsHtml(response.data);
}
});
}]).controller("NewUserGoToSSPController", ['$http', '$scope', '$sce', function($http, $scope, $sce){
$http.get('/viplogin/saml2/post/newusersamltossp').then(function(response){
$scope.response = $sce.trustAsHtml(response.data);
});
}]).controller("CredMgmtGoToSSPController", ['$http', '$scope', '$sce', function($http, $scope, $sce){
$http.get('/viplogin/saml2/post/credmgmtsamltossp').then(function(response){
$scope.response = $sce.trustAsHtml(response.data);
});
}]).controller("RedirectOOBController", ['$http', '$scope', '$sce', function($http, $scope, $sce){
$http.get('/viplogin/requestoobfromidpfortemppassword').then(function(response){
$scope.response = $sce.trustAsHtml(response.data);
});
}]).controller("AuthResponseController", ['$http', '$scope', '$sce', function($http, $scope, $sce){
$http.get('/viplogin/oidc/authresponse').then(function(response){
$scope.response = $sce.trustAsHtml(response.data);
});
}]);
'use strict';
angular.module('vipLogin.controllers')
.controller("GenericErrorController", ['$scope', '$state', function ($scope, $state) {
$scope.$state = $state; // this is being used in the template
// Added to control if the Symc cobranding logo should display
$scope.cobrandingSymcLogo = "";
if (!$scope.cobrandingUrl.indexOf("Symc") >=0) {
$scope.cobrandingSymcLogo = "app/images/SymcLogo150x40.jpg";
}
}]);
'use strict';
angular.module('vipLogin.controllers')
.controller("CustomRedirectController", ["$scope", "$rootScope", "$timeout", "vip", 'VIPLoginService', function ($scope, $rootScope, $timeout, vip, VIPLoginService) {
$scope.useCustomDescription = $scope.userInfo.useCustomDescription;
$scope.doContinue = function() {
$scope.$state.go('oidcResponse');
};
function toSM() {
$timeout(function () {
$scope.$state.go('oidcResponse');
}, 10000);
}
toSM();
}]);
'use strict';
angular.module('vipLogin.services').
factory('UserInfo', [function(){
var userInfo = {};
return {
// Get user info for the current user
getUserInfo: function () {
return userInfo;
},
setUserInfo: function (data) {
for(var propertyName in data){
userInfo[propertyName] = data[propertyName];
}
}
};
}]);
angular.module('vipLogin.services').
factory('VIPLoginService', ['$http', function($http){
return {
// Get user info for the current user
getAuthenticationInfo: function (data) {
return $http.post('/viplogin/authenticationinfo', data);
},
setRememberDeviceAuthInfo: function (showRememberDevice, rememberDevice) {
return $http.post('/viplogin/rememberDeviceAuthInfo',
{'showRememberDevice' : showRememberDevice, 'rememberDevice' : rememberDevice});
},
setRememberDeviceAuthInfoWithDeviceName: function (showRememberDevice, rememberDevice, deviceName) {
return $http.post('/viplogin/rememberDeviceAuthInfo',
{'showRememberDevice' : showRememberDevice, 'rememberDevice' : rememberDevice, 'deviceName' : deviceName});
},
// Get account info for the current user
getAccountInfo: function () {
return $http.post('/viplogin/accountinfo');
},
// Get OOB options for the current user
getOobInfo: function() {
return $http.post('/viplogin/oobinfo');
},
// Get cobranding information for account
getCobrandingInfo: function() {
return $http.post('/viplogin/cobranding');
},
// Send an OOB request
sendOob: function(data) {
return $http.post('/viplogin/oobsend', data);
},
getAssertionType: function() {
return $http.post('/viplogin/assertiontype');
},
setJwtResponseToSSP: function(connecttossp) {
// BRCMVIP-4261 Oidc loop
return $http.post('/viplogin/jwtresponsetossp', {'connectToSsp' : connecttossp});
},
setSAMResponseToSSP: function(connecttossp) {
return $http.post('/viplogin/samresponsetossp', {'connectToSsp' : connecttossp});
},
setAuthenticationMethod: function(authmethod) {
return $http.post('/viplogin/authenticationmethod', {'authMethod' : authmethod});
},
setOidcError: function(error, error_desc) {
return $http.post('/viplogin/oidcerrordesc', {'error':error, 'errorDesc':error_desc});
},
setRegistrationForNewUser: function(newuserregistration) {
return $http.post('/viplogin/registrationfornewuser', {'newUserregistration' : newuserregistration});
}
};
}]);
'use strict';
angular.module('vipLogin.services').
factory('ValidationService', ['$http', function($http){
return {
// Validate PIN
validatePin: function (userId, pin, rememberUserId) {
return $http.post('/viplogin/authenticateuserwithpin', {'userId':userId, 'pin':pin, 'rememberUserId':rememberUserId});
},
// Validate 2FA
validate: function (otp, rememberUserId) {
return $http.post('/viplogin/authenticateuserwithsecuritycode', {'securityCode':otp, 'rememberUserId':rememberUserId});
},
// Update validation status to failed
denyvalidation: function () {
return $http.post('/viplogin/updateauthenticationstatus', {'status':'denied', 'type':'mobile'});
}
};
}]);
'use strict';
angular.module('vipLogin.services')
.service('VipSdkService', ['$q', '$timeout', '$window', function($q, $timeout, $window){
return {
// Get vip JavaScript from User Services.
getVip : function(userServicesHost, viploginAppID){
var deferred = $q.defer(), libs = {};
$script([
userServicesHost + '/vipuserservices/resources/js/v_1_0/vip?initCredArray=ia,mo,provsc&appId=' + viploginAppID
], 'vipSdk');
$script.ready('vipSdk', function() {
libs.vip = $window.vip;
$timeout(function(){
deferred.resolve(libs);
}, 0);
});
return deferred.promise;
}
};
}]);
'use strict';
angular.module('vipLogin.services').
factory('PinService', ['$http', function($http){
return {
// Validate PIN
validatePin: function (userId, pin, rememberUserId) {
return $http.post('/viplogin/authenticateuserwithpin', {'userId':userId, 'pin':pin, 'rememberUserId':rememberUserId});
},
// Reset PIN
resetPin: function(userId, currentPin, newPin) {
return $http.post('/viplogin/resetuserpin', {'userId':userId, 'oldPin':currentPin, 'pin':newPin})
},
// Get Pin Restriction Policies
getPinPolicy: function () {
return $http.post('/viplogin/pinpolicy');
}
};
}]);
'use strict';
angular.module('vipLogin.services').
factory('FidoService', ['$http', function($http){
return {
// Fido Pre Auth
preAuthenticateFido: function (credType) {
var hostName = document.location.hostname;
var documentDomain = hostName.substring(hostName.lastIndexOf(".", hostName.lastIndexOf(".") - 1) + 1);
return $http.post('/viplogin/preauthenticateuserwithfido', {'credType':credType, 'documentDomain': documentDomain});
},
// Fido Auth
authenticateFido: function(authMessage, preAuthID) {
return $http.post('/viplogin/authenticateUserWithFido', {'preAuthID': preAuthID, 'authenticationMessage':authMessage});
}
};
}]);
'use strict';
angular.module('vipLogin.services').
factory('IntelligentAuthenticationService', function() {
var ia = {
rememberDevice: false,
showRememberDevice: null,
deviceName: null,
code: null
};
return {
getRememberDevice: function () {
return ia.rememberDevice;
},
setRememberDevice: function (rememberDevice) {
if (rememberDevice) {
ia.rememberDevice = rememberDevice;
} else {
ia.rememberDevice = false;
}
},
getShowRememberDevice: function () {
return ia.showRememberDevice;
},
setShowRememberDevice: function (showRememberDevice) {
if (showRememberDevice) {
ia.showRememberDevice = showRememberDevice;
} else {
ia.showRememberDevice = false;
}
},
getDeviceName: function () {
return ia.deviceName;
},
setDeviceName: function (deviceName) {
ia.deviceName = deviceName;
},
getCode: function () {
return ia.code;
},
setCode: function (code) {
ia.code = code;
},
validate: function (vip, userInfo, provsc) {
if (provsc) {
var provReqData = {
user: userInfo.userId,
code: ia.code,
rememberDevice: ia.rememberDevice.toString(),
friendlyName: ia.deviceName,
rpJurHash: userInfo.customerJurhash,
clientIpAddress: userInfo.clientIpAddress
};
vip.api.df.provisionTagAndGenerateSecurityCode(provReqData, ia.rememberDevice);
} else {
var valReqData = {
user: userInfo.userId,
rpJurHash: userInfo.customerJurhash,
clientIpAddress: userInfo.clientIpAddress
};
vip.api.df.generateSecurityCode(valReqData);
}
}
};
});
'use strict';
angular.module('vipLogin.services').factory('messageUtils', ['validationManager',
function(validationManager) {
var el,
elementModifier = "vipLoginElementModifier",
addInlineMessage = function(fieldId, errorKey, errorMsg) {
if(fieldId) {
el = angular.element('#'+fieldId);
}
if(el) {
validationManager.setElementValidationError(el, errorKey, typeof errorMsg === 'object' ? errorMsg.join('
') : errorMsg);
}
},
addMessage = function(type, errorKey, errorMsg) {
//TODO add logic to put message at top message banner
};
return {
addInlineMessage: addInlineMessage,
addMessage: addMessage
};
}
]);
angular.module('vipLogin.services')
.factory('angularTranslateErrorMessageResolver', [
'$q',
'$http',
'$translate',
'$filter',
function ($q, $http, $translate, $filter) {
var currentCulture = 'en_US',
getMessageKeyTypeOverride = function (errorType, el) {
var overrideKey;
if (el) {
// try and find an attribute which overrides the given error type in the form of errorType-err-type="someMsgKey"
errorType += '-err-type';
overrideKey = el.attr(errorType);
if (overrideKey === undefined) {
overrideKey = el.attr('data-ng-' + errorType) || el.attr('ng-' + errorType);
}
if (overrideKey) {
// overrideKey = overrideKey.replace(/[\W]/g, '');
}
}
return overrideKey;
},
getMessageTypeOverride = function (errorType, el) {
var overrideKey;
if (el) {
// try and find an attribute which overrides the given error type in the form of errorType-err-type="someMsgKey"
errorType += '-err-msg';
overrideKey = el.attr(errorType);
}
return overrideKey;
},
resolve = function (errorType, el) {
var defer = $q.defer(),
errMsg,
parameters = [],
parameter,
messageTypeOverride;
errMsg = $filter('translate')(errorType);
messageTypeOverride = getMessageKeyTypeOverride(errorType, el);
if (messageTypeOverride) {
errMsg = $filter('translate')(messageTypeOverride);
}
messageTypeOverride = getMessageTypeOverride(errorType, el);
if (messageTypeOverride) {
errMsg = messageTypeOverride;
}
if (errMsg === undefined) {
errMsg = $filter('translate')('defaultMsg').format(errorType);
}
if (el && el.attr) {
try {
parameter = el.attr(errorType);
if (parameter === undefined) {
parameter = el.attr('data-ng-' + errorType) || el.attr('ng-' + errorType);
}
parameters.push(parameter || '');
errMsg = errMsg.format(parameters);
} catch (e) {}
}
defer.resolve(errMsg);
return defer.promise;
};
return {
resolve: resolve
};
}
]);
angular.module('vipLogin.services')
.factory('vipLoginErrorMessageResolver', [
'$q',
'$http',
function ($q, $http) {
var currentCulture = 'en_US',
getMessageTypeOverride = function (errorType, el) {
var overrideKey;
if (el) {
// try and find an attribute which overrides the given error type in the form of errorType-err-type="someMsgKey"
errorType += '-err-type';
overrideKey = el.attr(errorType);
if (overrideKey === undefined) {
overrideKey = el.attr('data-ng-' + errorType) || el.attr('ng-' + errorType);
}
if (overrideKey) {
// overrideKey = overrideKey.replace(/[\W]/g, '');
}
}
return overrideKey;
},
resolve = function (errorType, el) {
var defer = $q.defer(),
errMsg,
parameters = [],
parameter,
messageTypeOverride;
errMsg = vipValidation.errorMessages[currentCulture][errorType];
messageTypeOverride = getMessageTypeOverride(errorType, el);
if (messageTypeOverride) {
errMsg = vipValidation.errorMessages[currentCulture][messageTypeOverride];
}
if (errMsg === undefined) {
errMsg = vipValidation.errorMessages[currentCulture].defaultMsg.format(errorType);
}
if (el && el.attr) {
try {
parameter = el.attr(errorType);
if (parameter === undefined) {
parameter = el.attr('data-ng-' + errorType) || el.attr('ng-' + errorType);
}
parameters.push(parameter || '');
errMsg = errMsg.format(parameters);
} catch (e) {}
}
defer.resolve(errMsg);
return defer.promise;
};
return {
resolve: resolve
};
}
]);
angular.module('vipLogin.services')
.factory('vipLoginElementModifier', [
function () {
var reset = function (el) {
angular.forEach(el.find('span'), function (spanEl) {
spanEl = angular.element(spanEl);
if (spanEl.hasClass('error-msg') || spanEl.hasClass('form-control-feedback') || spanEl.hasClass('control-feedback')) {
spanEl.remove();
}
});
el.removeClass('has-success has-error has-feedback');
},
findWithClassElementAsc = function (el, klass) {
var parent = el;
for (var i = 0; i <= 3; i += 1) {
if (parent !== undefined && parent.hasClass(klass)) {
break;
} else if (parent !== undefined) {
parent = parent.parent();
}
}
return parent;
},
findWithClassElementDesc = function (el, klass) {
var child;
for (var i = 0; i < el.children.length; i += 1) {
child = el.children[i];
if (child !== undefined && angular.element(child).hasClass(klass)) {
break;
} else if (child.children !== undefined) {
child = findWithClassElementDesc(child, klass);
if (child.length > 0) {
break;
}
}
}
return angular.element(child);
},
findFormGroupElement = function (el) {
return findWithClassElementAsc(el, 'form-group');
},
findInputGroupElement = function (el) {
return findWithClassElementDesc(el, 'input-group');
},
insertAfter = function (referenceNode, newNode) {
referenceNode[0].parentNode.insertBefore(newNode[0], referenceNode[0].nextSibling);
},
addValidationStateIcons = false,
enableValidationStateIcons = function (enable) {
addValidationStateIcons = enable;
},
makeValid = function (el) {
var frmGroupEl = findFormGroupElement(el),
inputGroupEl = findInputGroupElement(frmGroupEl[0]);
reset(frmGroupEl);
//frmGroupEl.addClass('has-success ' + (inputGroupEl.length > 0 ? '' : 'has-feedback'));
if (addValidationStateIcons) {
var iconElText = '
';
if (inputGroupEl.length > 0) {
iconElText = iconElText.replace('form-', '');
iconElText = '
' + iconElText + '' + errorMsg + '');
reset(frmGroupEl, inputGroupEl);
frmGroupEl.addClass('has-error ' + (inputGroupEl.length > 0 ? '' : 'has-feedback'));
insertAfter(inputGroupEl.length > 0 ? inputGroupEl : el, helpTextEl);
if (addValidationStateIcons) {
var iconElText = '
';
if (inputGroupEl.length > 0) {
iconElText = iconElText.replace('form-', '');
iconElText = '
' + iconElText + ' '
};
});
'use strict';
//
angular.module('vipLogin.directives')
.directive('ngHeader', function () {
return {
restrict: 'C', //This means that it will be used as an attribute and NOT as an element. I don't like creating custom HTML elements
replace: true,
//templateUrl: "app/partials/ngHeader.html",
controller: ['$scope', 'VIPLoginService','$sce', function($scope, VIPLoginService,$sce){
return VIPLoginService.getCobrandingInfo().then(function(result){
$scope.cobrandingEnabled=result.data.cobrandingEnabled;
if($scope.cobrandingEnabled){
$scope.cobrandingUrl=result.data.cobrandingImageURL;
}else{
$scope.cobrandingUrl="app/images/SymcLogo150x40.jpg";
}
$scope.trustedSecureSeal = function() {
$scope.hostName="";
return $sce.trustAsHtml($scope.hostName);
};
VIPLoginService.getAssertionType().then(function(response){
$scope.getHeader = "app/partials/ngHeader-eg-idp.html";
});
});
}],
template: "