'use strict'; // Declare app level module which depends on filters, and services angular.module('vipLogin', ['vipLogin.controllers','vipLogin.services','vipLogin.directives','ui.router','ngSanitize','ipCookie','angularSpinner','pascalprecht.translate','jcs-autoValidate']) .config(['$stateProvider', '$urlRouterProvider', '$httpProvider', function($stateProvider, $urlRouterProvider, $httpProvider) { //ajax global timeout set to 60secs $httpProvider.defaults.timeout = 60000; // By default go to /home, it's a decision making state. $urlRouterProvider.otherwise("/home"); $stateProvider .state('home', { // The home state will decide which module to start with pin or auth url : "/home", template : '', controller : 'HomeController' }) .state('pin', { // templateUrl : "app/partials/container.html", templateProvider: function($http, $templateFactory) { return $http.post('/viplogin/assertiontype').then(function(response){ if (response.status === 200) { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/container-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } else { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/genericError-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } }); }, resolve : { // Get the accountInfo before activating the 'auth' state accountInfo : ['VIPLoginService', function(VIPLoginService){ return VIPLoginService.getAccountInfo().then(function(result){ return result.data; }); }] }, controller : 'PinController' }) .state('pin.userPinLogin', { // templateUrl : "app/partials/userPinLogin.html", templateProvider: function($http, $templateFactory) { return $http.post('/viplogin/assertiontype').then(function(response){ if (response.status === 200) { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/userPinLogin-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } else { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/genericError-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } }); }, onEnter: function($rootScope){ $rootScope.clearAndShowPendingMessage(); }, controller : 'UserPinLoginController' }) .state('pin.reset', { templateUrl : "app/partials/resetPin-eg-idp.html", resolve : { // Get the pinPolicy pinPolicy : ['PinService', function(PinService){ return PinService.getPinPolicy().then(function(result){ return result.data; }); }] }, onEnter: function($rootScope){ $rootScope.clearAndShowPendingMessage(); }, controller : 'ResetPinController' }) .state('pin.cancelReset', { templateProvider: function($http, $templateFactory) { return $http.post('/viplogin/assertiontype').then(function(response){ if (response.status === 200) { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/cancelResetPin-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } else { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/genericError-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } }); } }) .state('auth', { // Note: we don't use abstract here because we need this state to be activated individually. So that // it can go to other state based on userInfo. Therefore, do not set this to abstract even though this // state will not be activated just by itself. It's a transitional state. //templateUrl : "app/partials/container.html", templateProvider: function($http, $templateFactory) { return $http.post('/viplogin/assertiontype').then(function(response){ if (response.status === 200) { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/container-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } else { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/genericError-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } }); }, resolve : { // Get the userInfo before activating the 'auth' state // FIXME: return userInfo is not needed, use UserInfo in the controller instead userInfo : ['VIPLoginService', 'UserInfo', function(VIPLoginService, UserInfo){ return VIPLoginService.getAuthenticationInfo().then(function(result){ UserInfo.setUserInfo(result.data); return UserInfo.getUserInfo(); }); }] }, controller : 'AuthController' }) .state('auth.fido', { // Do not specify url, this state is not allowed to navigate by typing in a url // url : "", // templateUrl : "app/partials/securityCode.html", templateProvider: function ($http, $templateFactory) { return $http.post('/viplogin/assertiontype').then(function (response) { if (response.status === 200) { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/passwordlessAuth.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } else { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/genericError-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } }); }, resolve: { // userInfo is injected from parent state 'auth', this will load the vip JavaScript vip: ['VipSdkService', 'userInfo', function (VipSdkService, userInfo) { return VipSdkService.getVip(userInfo.vipUserServicesURL, userInfo.viploginAppID).then(function (result) { return result.vip; }); }] }, onEnter: function ($rootScope) { $rootScope.clearAndShowPendingMessage(); }, controller: 'FidoController' } ) .state('auth.securityCode', { // Do not specify url, this state is not allowed to navigate by typing in a url // url : "", // templateUrl : "app/partials/securityCode.html", templateProvider: function($http, $templateFactory) { return $http.post('/viplogin/assertiontype').then(function(response){ if (response.status === 200) { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/securityCode-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } else { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/genericError-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } }); }, resolve : { // userInfo is injected from parent state 'auth', this will load the vip JavaScript vip : ['VipSdkService', 'userInfo', function(VipSdkService, userInfo){ return VipSdkService.getVip(userInfo.vipUserServicesURL, userInfo.viploginAppID).then(function(result){ return result.vip; }); }] }, onEnter: function($rootScope){ $rootScope.clearAndShowPendingMessage(); }, controller : 'SecurityCodeController' }) .state('auth.mobilePush', { // Do not specify url, this state is not allowed to navigate by typing in a url // url : "", //templateUrl : "app/partials/mobilePush.html", templateProvider: function($http, $templateFactory) { return $http.post('/viplogin/assertiontype').then(function(response){ if (response.status === 200) { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/mobilePush-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } else { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/genericError-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } }); }, resolve : { // userInfo is injected from parent state 'auth', this will load the vip JavaScript vip : ['VipSdkService', 'userInfo', function(VipSdkService, userInfo){ return VipSdkService.getVip(userInfo.vipUserServicesURL, userInfo.viploginAppID).then(function(result){ return result.vip; }); }] }, onEnter: function($rootScope){ $rootScope.clearAndShowPendingMessage(); }, controller : 'MobilePushController' }) .state('auth.oobOptions', { // Do not specify url, this state is not allowed to navigate by typing in a url // url : "", //templateUrl : "app/partials/oobOptions.html", templateProvider: function($http, $templateFactory) { return $http.post('/viplogin/assertiontype').then(function(response){ if (response.status === 200) { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/oobOptions-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } else { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/genericError-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } }); }, resolve : { // Get OOB Options before activating the 'oobOptions' state. oobResponse : ['$state', 'VIPLoginService', function($state, VIPLoginService){ return VIPLoginService.getOobInfo().then(function(result){ return result.data; }); }] }, onEnter: function($rootScope){ $rootScope.clearAndShowPendingMessage(); }, controller : 'OobOptionsController' }) .state('redirectOOB', { // Do not specify url, this state is not allowed to navigate by typing in a url // url : "", templateUrl : "app/partials/genericRedirect.html", controller : 'RedirectOOBController' }) .state('auth.registerCredential', { // Do not specify url, this state is not allowed to navigate by typing in a url // url : "", //templateUrl : "app/partials/registerCredential.html", templateProvider: function($http, $templateFactory) { return $http.post('/viplogin/assertiontype').then(function(response){ if (response.status === 200) { if (response.data.contextFound === "TRUE") { // This is temporary solution that the 1st time user refresh page during OOB // For the new flow, the registerCredential is done at the ngSSP, the viplogin // will only perform the authentication using OOB. There is no registerCredential // page for the new flow. return $templateFactory.fromUrl("app/partials/registerCredential-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } else { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/genericError-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } }); }, controller : 'RegisterCredentialController' }) .state('auth.registerCredentialNoSecurityCode', { // Do not specify url, this state is not allowed to navigate by typing in a url // url : "", templateUrl : "app/partials/registerCredentialNoSecurityCode.html", controller : 'RegisterCredentialController' }) .state('auth.rememberDevice', { // Do not specify url, this state is not allowed to navigate by typing in a url // url : "", resolve : { // userInfo is injected from parent state 'auth', this will load the vip JavaScript vip : ['VipSdkService', 'userInfo', function(VipSdkService, userInfo){ return VipSdkService.getVip(userInfo.vipUserServicesURL, userInfo.viploginAppID).then(function(result){ return result.vip; }); }] }, controller : 'RememberDeviceController' }) .state('auth.rememberDeviceProvision', { // Do not specify url, this state is not allowed to navigate by typing in a url // url : "", //templateUrl: "app/partials/rememberDeviceProvision.html", templateProvider: function($http, $templateFactory) { return $http.post('/viplogin/assertiontype').then(function(response){ if (response.status === 200) { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/rememberDeviceProvision-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } else { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/genericError-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } }); }, resolve : { // userInfo is injected from parent state 'auth', this will load the vip JavaScript vip : ['VipSdkService', 'userInfo', function(VipSdkService, userInfo){ return VipSdkService.getVip(userInfo.vipUserServicesURL, userInfo.viploginAppID).then(function(result){ return result.vip; }); }] }, onEnter: function($rootScope){ $rootScope.clearAndShowPendingMessage(); }, controller: 'RememberDeviceController' }) .state('auth.rememberDeviceSubmit', { // Do not specify url, this state is not allowed to navigate by typing in a url // url : "", //templateUrl : "app/partials/rememberDeviceSubmit.html", templateProvider: function($http, $templateFactory) { return $http.post('/viplogin/assertiontype').then(function(response){ if (response.status === 200) { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/rememberDeviceSubmit-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } else { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/genericError-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } }); }, resolve : { // userInfo is injected from parent state 'auth', this will load the vip JavaScript vip : ['VipSdkService', 'userInfo', function(VipSdkService, userInfo){ return VipSdkService.getVip(userInfo.vipUserServicesURL, userInfo.viploginAppID).then(function(result){ return result.vip; }); }] }, controller : 'RememberDeviceController' }) .state('auth.rememberDeviceConfirmation', { // Do not specify url, this state is not allowed to navigate by typing in a url // url : "", //templateUrl: "app/partials/rememberDeviceConfirmation.html", templateProvider: function($http, $templateFactory) { return $http.post('/viplogin/assertiontype').then(function(response){ if (response.status === 200) { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/rememberDeviceConfirmation-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } else { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/genericError-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } }); }, resolve : { // userInfo is injected from parent state 'auth', this will load the vip JavaScript vip : ['VipSdkService', 'userInfo', function(VipSdkService, userInfo){ return VipSdkService.getVip(userInfo.vipUserServicesURL, userInfo.viploginAppID).then(function(result){ return result.vip; }); }] }, onEnter: function($rootScope){ $rootScope.clearAndShowPendingMessage(); }, controller : 'RememberDeviceController' }) .state('auth.rememberDeviceBindingError', { // Do not specify url, this state is not allowed to navigate by typing in a url // url : "", //templateUrl: "app/partials/rememberDeviceBindingError.html", templateProvider: function($http, $templateFactory) { return $http.post('/viplogin/assertiontype').then(function(response){ if (response.status === 200) { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/rememberDeviceBindingError-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } else { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/genericError-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } }); }, resolve : { // userInfo is injected from parent state 'auth', this will load the vip JavaScript vip : ['VipSdkService', 'userInfo', function(VipSdkService, userInfo){ return VipSdkService.getVip(userInfo.vipUserServicesURL, userInfo.viploginAppID).then(function(result){ return result.vip; }); }] }, onEnter: function($rootScope){ $rootScope.clearAndShowPendingMessage(); }, controller : 'RememberDeviceController' }) .state('cancelResponse', { // Do not specify url, this state is not allowed to navigate by typing in a url // url : "", templateUrl : "app/partials/genericRedirect.html", controller : 'CancelResponseController' }) .state('passwordResponse', { // Do not specify url, this state is not allowed to navigate by typing in a url // url : "", templateUrl : "app/partials/genericRedirect.html", controller : 'PasswordResponseController' }) .state('samlResponse', { // Do not specify url, this state is not allowed to navigate by typing in a url // url : "", //templateUrl : "app/partials/genericRedirect.html", templateProvider: function($http, $templateFactory) { return $http.post('/viplogin/assertiontype').then(function(response){ if (response.status === 200) { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/genericRedirect-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } else { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/genericError-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } }); }, controller : 'SamlResponseController' }) .state('oidcResponse', { templateProvider: function($http, $templateFactory) { return $http.post('/viplogin/assertiontype').then(function(response){ if (response.status === 200) { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/genericRedirect-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } else { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/genericError-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } }); }, controller : 'AuthResponseController' }) .state('newUserGoToSsp', { // Do not specify url, this state is not allowed to navigate by typing in a url // url : "", //templateUrl : "app/partials/genericRedirect.html", templateProvider: function($http, $templateFactory) { return $http.post('/viplogin/assertiontype').then(function(response){ if (response.status === 200) { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/genericRedirect-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } else { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/genericError-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } }); }, controller : 'NewUserGoToSSPController' }) .state('credMgmtGoToSsp', { // Do not specify url, this state is not allowed to navigate by typing in a url // url : "", templateUrl : "app/partials/genericRedirect.html", onEnter: function(VIPLoginService, IntelligentAuthenticationService){ if (IntelligentAuthenticationService.getDeviceName()) { VIPLoginService.setRememberDeviceAuthInfoWithDeviceName( String(IntelligentAuthenticationService.getShowRememberDevice()), String(IntelligentAuthenticationService.getRememberDevice()), String(IntelligentAuthenticationService.getDeviceName())); } else if (IntelligentAuthenticationService.getShowRememberDevice() != null) { VIPLoginService.setRememberDeviceAuthInfo( String(IntelligentAuthenticationService.getShowRememberDevice()), String(IntelligentAuthenticationService.getRememberDevice())); } }, controller : 'CredMgmtGoToSSPController' }) .state('auth.registrationdenied', { templateProvider: function($http, $templateFactory) { return $http.post('/viplogin/assertiontype').then(function(response){ if (response.status === 200) { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/registrationdenied-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } else { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/registrationdenied-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } }); }, controller : 'RegisterCredentialController' }) .state('error', { // Do not specify url, this state is not allowed to navigate by typing in a url // url : "", //templateUrl : "app/partials/genericError.html", templateProvider: function($http, $templateFactory) { return $http.post('/viplogin/assertiontype').then(function(response){ if (response.status === 200) { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/genericError-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } else { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/genericError-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } }); }, controller : 'GenericErrorController' }) .state('policydenied', { // Do not specify url, this state is not allowed to navigate by typing in a url // url : "", //templateUrl : "app/partials/genericError.html", templateProvider: function($http, $templateFactory) { return $http.post('/viplogin/assertiontype').then(function(response){ if (response.status === 200) { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/policydenied-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } else { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/policydenied-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } }); }, controller : 'GenericErrorController' }) .state('signedouterror', { // Do not specify url, this state is not allowed to navigate by typing in a url // url : "", //templateUrl : "app/partials/signedoutError.html", templateProvider: function($http, $templateFactory) { return $http.post('/viplogin/assertiontype').then(function(response){ if (response.status === 200) { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/genericError-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } else { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/genericError-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } }); }, controller : 'GenericErrorController' }); }]) // Interceptors .config(['$httpProvider', '$provide', function($httpProvider, $provide) { // Redirect Interceptor takes care of the error handling when server returns 401 or 500 $provide.factory('redirectInterceptor', ['$q', '$injector', function($q, $injector){ return { 'responseError': function(rejection) { if(rejection.status === 401){ // Using $injector here to inject the $state object. // Then using .go method in $state to transition to error state $injector.get('$state').go('signedouterror'); }else if( rejection.status === 500) { // Using $injector here to inject the $state object. // Then using .go method in $state to transition to error state $injector.get('$state').go('error'); } return $q.reject(rejection); } }; }]); // Spinner Interceptor is used to start and stop the spinner when a request is sent and a response is received. $provide.factory('spinnerInterceptor', ['$q', 'usSpinnerService', function($q, usSpinnerService){ return { 'request': function(config) { //start the spinner before send a request. usSpinnerService.spin('spinnerRef'); return config || $q.when(config); }, 'response': function(response) { //stop the spinner after receive the response. usSpinnerService.stop('spinnerRef'); return response || $q.when(response); } }; }]); // $http error logging Interceptor is used to send logs back to server $provide.factory('errorLoggingInterceptor', ['$q', 'applicationLoggingService', function($q, applicationLoggingService){ return { 'response': function(response) { if(response.status === null || response.status === 500 || response.status === 503 || response.status === 404) { var error = { method: response.config.method, url: response.config.url, message: response.data, status: response.status }; applicationLoggingService.error(JSON.stringify(error)); } return response || $q.when(response); } }; }]); // Push the interceptor to the interceptors $httpProvider.interceptors.push('redirectInterceptor'); $httpProvider.interceptors.push('spinnerInterceptor'); $httpProvider.interceptors.push('errorLoggingInterceptor'); //initialize get if not there if (!$httpProvider.defaults.headers.get) { $httpProvider.defaults.headers.get = {}; } //disable IE ajax request caching $httpProvider.defaults.headers.get['If-Modified-Since'] = '0'; //request JSON response $httpProvider.defaults.headers.get['Accept'] = 'application/json'; $httpProvider.defaults.headers.post['Accept'] = 'application/json'; }]) .config(['$translateProvider', function($translateProvider){ $translateProvider.useUrlLoader('/viplogin/translation'); // We set a language (framework needs it), // we use the server side servlet mechanism to figure out the locale to be consistent with the client and server rendering var language = "server_pick"; $translateProvider.preferredLanguage(language); }]) .run([ 'validator', function (validator) { validator.setValidElementStyling(false); }]) .run(function ($rootScope) { $rootScope.responsive = { XS : 200, SM : 767, MD : 1100, LG : 1200, isXsDevice : function() { return $(window).width() >= this.XS && $(window).width() < this.SM; }, isSmDevice : function() { return $(window).width() >= this.SM && $(window).width() < this.MD; }, isMdDevice : function() { return $(window).width() >= this.MD && $(window).width() < this.LG; }, isLgDevice : function() { return $(window).width() >= this.LG; } }; }); /** * Define the modules */ angular.module('jcs-autoValidate') .run(['validator','angularTranslateErrorMessageResolver', function (validator, errorMessageResolver) { validator.setErrorMessageResolver(errorMessageResolver.resolve); } ]); //now register the custom element modifier with the auto-validate module and set it as the default one for all elements angular.module('jcs-autoValidate') .run(['validator', 'vipLoginElementModifier', function (validator, vipLoginElementModifier) { validator.registerDomModifier(vipLoginElementModifier.key, vipLoginElementModifier); validator.setDefaultElementModifier(vipLoginElementModifier.key); } ]); angular.module('vipLogin.controllers', []); angular.module('vipLogin.services', []); angular.module('vipLogin.directives', []); 'use strict'; angular.module('vipLogin.controllers') .controller('PinController', ['$scope', '$state', '$filter', 'PinService', 'accountInfo', 'applicationLoggingService', function($scope, $state, $filter, PinService, accountInfo, applicationLoggingService) { // $scope.$state is used for all children controllers. In the child controller, use $scope.$state to go to a new state $scope.$state = $state; // accountInfo is available to children state by using $scope.accountInfo $scope.accountInfo = accountInfo; // PinService is available to children state by using $scope.PinService $scope.PinService = PinService; // $filter is available to children state by using $scope.$filter $scope.$filter = $filter; // applicationLoggingService is available to children state by using $scope.applicationLoggingService $scope.applicationLoggingService = applicationLoggingService; // Added to control if powered by 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("HomeController", ['$state', '$scope', '$rootScope', 'VIPLoginService', function($state, $scope, $rootScope, VIPLoginService){ // README: the message element is in home.jsp and it belongs to $rootScope. // 1. When show a message, call $rootScope.showMessage. This will show the message on // the current active state. // 2. When show a message in the next state, for example you have $state.go("newSate") // and you want to show the message in newState, you should call $rootScope.addPendingMessage // 3. in app.js, most of the children state has onEnter callback, which it calls $rootScope.clearAndShowPendingMessage // This method not only clear the current message, but also show the pending message in the new state. // 4. If you really want to clear all the message, call $rootScope.clearMessage //This function clear the current messages. And look at the pending messages. //If the pending messages has been defined, show them. $rootScope.clearAndShowPendingMessage = function(){ if ($rootScope.message) { //if there is a pending message, show it and remove the pending message. if($rootScope.message.pendingMessageStatus && $rootScope.message.pendingMessageStatusMessage) { $rootScope.message.status = $rootScope.message.pendingMessageStatus; $rootScope.message.statusMessage = $rootScope.message.pendingMessageStatusMessage; $rootScope.message.pendingMessageStatus = ''; $rootScope.message.pendingMessageStatusMessage = ''; } else { $rootScope.message.status = ''; $rootScope.message.statusMessage = ''; } } else { $rootScope.message = {}; } } // Clear the messages $rootScope.clearMessage = function(){ $rootScope.message = {}; } // Show the successful message or error message $rootScope.showMessage = function(status, statusMessage){ if (!$rootScope.message) { $rootScope.message = {}; } $rootScope.message.status= status; $rootScope.message.statusMessage = statusMessage; } // Add pending message for the next activated state. $rootScope.addPendingMessage = function(status, statusMessage){ if (!$rootScope.message) { $rootScope.message = {}; } $rootScope.message.pendingMessageStatus = status; $rootScope.message.pendingMessageStatusMessage = statusMessage; } // This needs to be in $rootScope because there is a "send again" in the message, which is in rootScope. $rootScope.sendOob = function(selectedOobId){ VIPLoginService.sendOob({'selectedOobId' : selectedOobId}).then(function(result){ var message = ''; if (angular.lowercase(result.data.statusCode) === 'success') { // Here the message is in a directive 'compile', it's also dynamically generated in runtime. // So the message will need to be compile again and link again in order to have the ng-click // to work. So see example in container.html, the message is passed in to the "compile" directive message = result.data.messages[0].message[0]; message += ' ' + '' + result.data.messages[1].message + ''; } else { message = result.data.messages[0].message; } $rootScope.addPendingMessage(angular.lowercase(result.data.statusCode), message); $state.go('auth.securityCode'); }); } // When home.js is activated, it will go to the initial state that server sends back. Otherwise, go to error state. $state.go($rootScope.initState || 'error'); }]); 'use strict'; angular.module('vipLogin.controllers') .controller('AuthController', ['$http', '$scope', '$state', 'VIPLoginService', 'usSpinnerService', 'userInfo', '$filter', 'ipCookie', 'IntelligentAuthenticationService', 'ValidationService', 'applicationLoggingService', function($http, $scope, $state, VIPLoginService, usSpinnerService, userInfo, $filter, ipCookie, IntelligentAuthenticationService, ValidationService, applicationLoggingService) { // $scope.$state is used for all children controllers. In the child controller, use $scope.$state to go to a new state $scope.$state = $state; // children state can start the spinner by using $scope.usSpinnerService $scope.usSpinnerService = usSpinnerService; // userInfo is available to children state by using $scope.userInfo $scope.userInfo = userInfo; // VIPLoginService is available to children state by using $scope.VIPLoginService $scope.VIPLoginService = VIPLoginService; // $filter is available to children state by using $scope.$filter $scope.$filter = $filter; // ipCookie is available to children state by using $scope.ipCookie $scope.ipCookie = ipCookie; // IntelligentAuthenticationService is available to children state by using $scope.IntelligentAuthenticationService $scope.IntelligentAuthenticationService = IntelligentAuthenticationService; // ValidationService is available to children state by using $scope.ValidationService $scope.ValidationService = ValidationService; // applicationLoggingService is available to children state by using $scope.applicationLoggingService $scope.applicationLoggingService = applicationLoggingService; $scope.isBlockVipLoginRegEnabled = $scope.userInfo.blockVipLoginRegEnabled; if ($scope.userInfo.authType === 'jwt' || $scope.userInfo.authType === 'SAM' || $scope.userInfo.authType === 'myvip' || $scope.userInfo.authType === 'oidc') { // Apply MO_FALLBACK_OTP policy to Azure, SAM, MyVIP and oidc. } else { $scope.userInfo.mobileFallbackEnabled = true; VIPLoginService.setRegistrationForNewUser('true'); } if($scope.userInfo.deviceFingerprintEnabled) { if (userInfo.showRememberDevice != null) { IntelligentAuthenticationService.setShowRememberDevice(userInfo.showRememberDevice == 'true'); } if (userInfo.rememberDevice != null) { IntelligentAuthenticationService.setRememberDevice(userInfo.rememberDevice == 'true'); } if (userInfo.deviceName != null) { IntelligentAuthenticationService.setDeviceName(userInfo.deviceName); } } /* revert BRCMVIP-4094 test if ($scope.userInfo.authType === 'jwt' || $scope.userInfo.authType === 'oidc') { */ if ($scope.userInfo.authType === 'jwt') { if ($scope.userInfo.displayJWTLink === true && $scope.userInfo.hasCredentials) $scope.isJWT = true; else $scope.isJWT = false; } $scope.reloadPage = function() { if ($scope.isJWT === true) { VIPLoginService.setJwtResponseToSSP('true'); $scope.userInfo.displayJWTLink = false; $scope.isJWT = false; } } $scope.isDisplayAddorManagerLinkForAllowFallBack = function() { // OIDC integration if ($scope.userInfo.authType === 'SAM' || $scope.userInfo.authType === 'jwt' || $scope.userInfo.authType === 'oidc') { return false; } else { return false; } } $scope.isDisplayRedirectNotice = function() { /* revert BRCMVIP-4094 test if ($scope.userInfo.authType === 'oidc' && $scope.isJWT === false && $scope.userInfo.hasCredentials) return true; */ if ($scope.userInfo.authType === 'jwt' && $scope.isJWT === false && $scope.userInfo.hasCredentials) return true; else if ($scope.userInfo.authType === 'jwt' && !$scope.userInfo.hasCredentials ) return true; else return false; } // MO Fallback to display Add or Manage a Credentail clicked in MobilePush page only for SAM and Azure, $scope.isMOFallbackDisplayRedirectToNgSSPLink = function() { if ($scope.userInfo.authType === 'SAM' || $scope.userInfo.authType === 'jwt') { if ($scope.userInfo.shouldRedirectToNgSSSP === 'true') { return false; } else { return true; } } } // When Add or Manage a Credentail clicked, $scope.isDisplayRedirectToNgSSPLink = function() { // OIDC integration if ($scope.userInfo.authType !== 'SAM') { // explicitly sdded the checking for oidc to show that add a new point // this function will be impacted. if ($scope.userInfo.authType === 'oidc') { /* revert BRCMVIP-4094 test return false; */ } else { return false; } } if ($scope.userInfo.shouldRedirectToNgSSSP === 'false') { return true; } else { return false; } } $scope.isDisplayRedirectToNgSSPNote = function() { if ($scope.userInfo.authType === 'jwt' && $scope.userInfo.shouldRedirectToNgSSSP === 'true') { return true; } // OIDC integration if ($scope.userInfo.authType === 'oidc' && $scope.userInfo.shouldRedirectToNgSSSP === 'true') { return true; } if ($scope.userInfo.authType !== 'SAM') { return false; } if ($scope.userInfo.shouldRedirectToNgSSSP === 'true') { return true; } else { return false; } } $scope.isDisplayRedirectToMyVIPNote = function() { if ($scope.userInfo.shouldRedirectToNgSSSP === 'true') { return true; } else { return false; } } // Only goes into state changing logic if current state is 'auth' if ($state.current.name == 'auth') { // Handle any error cases first if ($scope.userInfo.statusCode == "ERROR") { if ($scope.userInfo.authType === 'oidc') { VIPLoginService.setOidcError('access_denied', 'Resource is not available.'); $scope.$state.go('oidcResponse'); } else { $state.go('error'); } } else if ($scope.userInfo.myVIPAuthOobOnly) { $state.go('auth.oobOptions'); } else if(!$scope.userInfo.hasAllowedAuthMethods && !($scope.userInfo.iaEnabled || $scope.userInfo.deviceFingerprintEnabled)) { $state.go('samlResponse'); } else if (!$scope.userInfo.fidoAllowed && $scope.userInfo.onlyFidoCred) { if ($scope.userInfo.authType !== 'SAM') { // Not AuthnReq, honor the onlyFidoCred and check the user OOB options if ($scope.userInfo.hasUserOob) { $state.go('auth.oobOptions'); } else { $state.go('policydenied'); } } else { // deter to check the user OOB options $state.go('auth.securityCode'); } } else if($scope.userInfo.fidoAllowed && ($scope.userInfo.bioMetricEnabled || $scope.userInfo.securityKeyEnabled)) { $state.go('auth.fido'); } // When the user needs to be redirected to OOB, the server sends back a requestedClientView = OOB // Always check if another view was requested before doing other processing else if ($scope.userInfo.requestedClientView == "OOB") { VIPLoginService.getOobInfo().then(function(result){ if(result.data.options!=null && result.data.options.length==1 && result.data.options[0].type !='VOICE'){ VIPLoginService.sendOob({'selectedOobId' : result.data.options[0].id }).then(function(result){ $scope.addPendingMessage(angular.lowercase(result.data.statusCode), result.data.messages[0].message[0]); $state.go('auth.securityCode'); }); }else{ $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){ $state.go('auth.securityCode'); } // Do the rest of the state checks // When user had ia/df enabled else if(($scope.userInfo.iaEnabled || $scope.userInfo.deviceFingerprintEnabled) && (IntelligentAuthenticationService.getShowRememberDevice() == null)){ $state.go('auth.rememberDevice'); } // When user has mobile push enabled else if($scope.userInfo.mobilePushEnabled) { $state.go('auth.mobilePush'); } // When user does not have any credentials else if(!$scope.userInfo.hasCredentials) { // Added to fix the bug if refresh the browser, the old UI register credential displayed $http.post('/viplogin/assertiontype').then(function(response){ if (response.status === 200) { if (response.data.contextFound === "TRUE") { // OIDC integration if ($scope.userInfo.authType === 'oidc') { if ($scope.userInfo.blockVipLoginRegEnabled) { VIPLoginService.setOidcError('invalid_scope', 'Registration blocked.'); $scope.$state.go('oidcResponse'); } else { $state.go('auth.registerCredential'); } } else if (response.data.assertionType === "ASSERTION_LOGIN" || response.data.assertionType === "ASSERTION_LOGIN_EXTERNAL") { if ($scope.userInfo.authType === 'jwt') { if ($scope.userInfo.blockVipLoginRegEnabled) { $state.go('auth.registrationdenied'); } else { $state.go('auth.registerCredential'); } } else { $state.go('auth.oobOptions'); } } else { if ($scope.userInfo.blockVipLoginRegEnabled) { $state.go('auth.registrationdenied'); } else { $state.go('auth.registerCredential'); } } } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } else { if (response.data.contextFound === "TRUE") { return $templateFactory.fromUrl("app/partials/genericError-eg-idp.html"); } else { return $templateFactory.fromUrl("app/partials/signedoutError-eg-idp.html"); } } }); } // When user cannot use any security code type creds (auth level doesn't allow it) else if(!$scope.userInfo.securityCodeTypeCredEnabled) { $state.go('auth.registerCredentialNoSecurityCode'); } else { if($scope.userInfo.hasSecurityCredential){ $state.go('auth.securityCode'); } else{ VIPLoginService.getOobInfo().then(function(result){ if(result.data.options != null && result.data.options.length==1 && result.data.options[0].type !='VOICE'){ var selectedOOBIDD = result.data.options[0].id; VIPLoginService.sendOob({'selectedOobId' : selectedOOBIDD }).then(function(result){ $scope.addPendingMessage(angular.lowercase(result.data.statusCode), result.data.messages[0].message[0]); $state.go('auth.securityCode'); }); }else{ $state.go('auth.oobOptions'); } }); } } // Added to control if powered by Symc cobranding logo will display $scope.cobrandingSymcLogo = ""; if (!($scope.cobrandingUrl.indexOf("Symc") >= 0)) { $scope.cobrandingSymcLogo = "app/images/SymcLogo150x40.jpg"; } } }]); 'use strict'; angular.module('vipLogin.controllers') .controller("MobilePushController", ['$scope', '$rootScope', 'vip', 'VIPLoginService', function ($scope, $rootScope, vip, VIPLoginService) { var options = $scope.userInfo.sendFirstFactorPush ? { "additionalPushData" : {"showFirstFactor" : true} } : undefined; var fallbackState = $scope.userInfo.sendFirstFactorPush ? 'pin.userPinLogin' : 'auth.securityCode'; fallbackState = $scope.userInfo.securityCodeTypeCredEnabled ? fallbackState: 'auth.registerCredentialNoSecurityCode'; // added for MO_FALLBACK_OTP - VIPAWS-12682 $scope.mobileFallback = $scope.userInfo.mobileFallbackEnabled; $scope.isBlockVipLoginRegEnabled = $scope.userInfo.blockVipLoginRegEnabled; $scope.isOIDC = $scope.userInfo.authType === 'oidc' ? true : false; $scope.isSAM = $scope.userInfo.authType === 'SAM' ? true : false; var stopMobliePushTimer; var timeToStopMobilePushInMS = 55000; //55 seconds var stopMobilePushCallback = function(){ // Stop the spinner $scope.usSpinnerService.stop('spinnerRef'); $scope.applicationLoggingService.error("Unable to receive response from messaging services within " + timeToStopMobilePushInMS + "ms") $rootScope.addPendingMessage('error', $scope.$filter('translate')('error.mobile.push.send.fail')); $scope.$state.go(fallbackState); }; // check if vip JavaScripts is available if(!vip) { $rootScope.addPendingMessage('error', $scope.$filter('translate')('error.mobile.push.send.fail')); $scope.$state.go(fallbackState); return; }; $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 { 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' || result.data.statusCode === 'STRONG_AUTHENTICATION_FAILED_MAX_BAD_ATTEMPTS_REACHED' || result.data.statusCode === 'SUCCESS_WITH_FIRST_FACTOR') { if ($scope.userInfo.authType === 'oidc') { VIPLoginService.setOidcError('access_denied', 'The authentication failed.'); $scope.$state.go('oidcResponse'); } 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.vip = vip; // vip is injected from resolve // First configure the mobile push credential $scope.vip.api.mo.set({ user: $scope.userInfo.userId, requestId: generateRequestId(), rpJurHash: $scope.userInfo.customerJurhash, onPushSucceed: function(message) { // this is needed to enter Angular context after the callback $scope.$apply(function(){ $scope.userInfo.mobilePushCreds = message.pushTo; $scope.userInfo.numbersChallengeValue = message.numbersChallengeValue; // Stop the spinner $scope.usSpinnerService.stop('spinnerRef'); }); clearTimeout(stopMobliePushTimer); }, onApprove: function(message){ // Removed iaEnabled checking - VIPAWS-17208 if ($scope.userInfo.deviceFingerprintEnabled && !($scope.userInfo.sendFirstFactorPush)) { $scope.IntelligentAuthenticationService.setCode(message); if ($scope.ipCookie($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 { // Validate the ticket returned in the message. It must wrap that in a promise $scope.ValidationService.validate(message, $scope.userInfo.rememberUserId).then(function (result) { $scope.stateSwitch(result); }); } }, onRequestChanged: function(message){ // modified for MO_FALLBACK_OTP - VIPAWS-12682 if ($scope.mobileFallback) { $rootScope.addPendingMessage('error', $scope.$filter('translate')('error.mobile.push.auth.cross.browser')); $scope.$state.go(fallbackState); } else { if ($scope.userInfo.authType === 'oidc') { VIPLoginService.setOidcError('access_denied', 'The authentication failed.'); $scope.$state.go('oidcResponse'); } else { $scope.$state.go('policydenied'); } } }, onDeny: function(message){ // Update the validation result as denied to the cloud $scope.ValidationService.denyvalidation().then(function(result){ if(result.data.statusCode === 'SUCCESS'){ if($scope.userInfo.MFaForIaEnabledJh === true){ $scope.$state.go('error'); } else { // Removed iaEnabled checking - VIPAWS-17208 if ($scope.userInfo.deviceFingerprintEnabled && !($scope.userInfo.sendFirstFactorPush)) { $scope.IntelligentAuthenticationService.setCode(message); $scope.usSpinnerService.spin('spinnerRef'); $scope.IntelligentAuthenticationService.setRememberDevice(false); $scope.IntelligentAuthenticationService.validate($scope.vip, $scope.userInfo, true); } else { if ($scope.userInfo.authType === 'oidc' || $scope.userInfo.authType === 'SAM') { if ($scope.userInfo.authType === 'oidc') { VIPLoginService.setOidcError('access_denied', 'The authentication failed.'); $scope.$state.go('oidcResponse'); } else { $scope.$state.go('error'); } } else { $scope.$state.go('samlResponse'); } } } } else { // If the API fails, show error and take user to security page // modified for MO_FALLBACK_OTP - VIPAWS-12682 if ($scope.mobileFallback) { $rootScope.addPendingMessage('error', '' + $scope.$filter('translate')('error.mobile.push.auth.fail.1') +' ' + $scope.$filter('translate')('error.mobile.push.auth.fail.2')); $scope.$state.go(fallbackState); } else { if ($scope.userInfo.authType === 'oidc') { VIPLoginService.setOidcError('access_denied', 'The authentication failed.'); $scope.$state.go('oidcResponse'); } else { $scope.$state.go('policydenied'); } } } }); }, onError: function(message){ $scope.$apply(function(){ clearTimeout(stopMobliePushTimer); // Stop the spinner $scope.usSpinnerService.stop('spinnerRef'); // modified for MO_FALLBACK_OTP - VIPAWS-12682 if ($scope.mobileFallback) { $rootScope.addPendingMessage('error', $scope.$filter('translate')('error.mobile.push.send.fail')); $scope.$state.go(fallbackState); } else { if ($scope.userInfo.authType === 'oidc') { VIPLoginService.setOidcError('access_denied', 'The authentication failed.'); $scope.$state.go('oidcResponse'); } else { $scope.$state.go('policydenied'); } } }); } }); $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.stateSwitch(result); }); }, onFailure: function(){ // Stop the spinner $scope.usSpinnerService.stop('spinnerRef'); }, onError: function(){ // Stop the spinner $scope.usSpinnerService.stop('spinnerRef'); } }); // Define a resendPush function for resend mobile push request. $scope.resendPush = function () { // If user has timed-out, go to error page and do not resend push. $scope.VIPLoginService.getAuthenticationInfo().then(function(result) { if(result.data.statusCode === 'SUCCESS') { // First unsubscribe the old channel $scope.vip.api.mo.cancelPush(); // Create a new request ID // Assign the onPushSucced callback again. The only difference between this onPushSucceed and the original one // is this one shows a successful message. $scope.vip.api.mo.set({ requestId: generateRequestId(), onPushSucceed: function(message) { // this is needed to enter Angular context after the callback $scope.$apply(function(){ $scope.userInfo.mobilePushCreds = message.pushTo; $scope.userInfo.numbersChallengeValue = message.numbersChallengeValue; $scope.usSpinnerService.stop('spinnerRef'); $rootScope.showMessage('success', $scope.$filter('translate')('success.mobile.push.sent') + ''); }); clearTimeout(stopMobliePushTimer); } }); sendPush(); } else { $rootScope.clearMessage(); if ($scope.userInfo.authType === 'oidc') { VIPLoginService.setOidcError('access_denied', 'The authentication failed.'); $scope.$state.go('oidcResponse'); } else { $scope.$state.go('error'); } } }, function(reason) { $rootScope.clearMessage(); if ($scope.userInfo.authType === 'oidc') { VIPLoginService.setOidcError('access_denied', 'The authentication failed.'); $scope.$state.go('oidcResponse'); } else { $scope.$state.go('error'); } }); }; $scope.userAnotherOption = function() { try{ clearTimeout(stopMobliePushTimer); vip.api.mo.cancelPush(); }catch(err){ $scope.applicationLoggingService.error("Unable to cancel mobile push, failed with error: " + err); } $scope.$state.go(fallbackState); }; function sendPush() { if ($scope.userInfo.authType === 'oidc') { VIPLoginService.setAuthenticationMethod('PUSH'); } try{ // Start the spinner $scope.usSpinnerService.spin('spinnerRef'); // clear pushTo $scope.userInfo.mobilePushCreds = []; $scope.userInfo.numbersChallengeValue = null; $scope.vip.api.mo.sendPush(options); stopMobliePushTimer = setTimeout(stopMobilePushCallback, timeToStopMobilePushInMS); }catch(err){ // Stop the spinner $scope.usSpinnerService.stop('spinnerRef'); $scope.applicationLoggingService.error("Error sending push. " + err); $rootScope.addPendingMessage('error', $scope.$filter('translate')('error.mobile.push.send.fail')); $scope.$state.go(fallbackState); } } function generateRequestId() { var prefix = "viplogin_"; var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'; var requestIdLength = 20; var requestId = ''; for (var i=0; i 0) { // Available OOB retrieved and continue processing } else { if ($scope.userInfo.authType === 'oidc') { VIPLoginService.setOidcError('access_denied', 'The authentication failed.'); $scope.$state.go('oidcResponse'); } else { $scope.$state.go('policydenied'); } return; } } } } // Map the type of OOB options to the label if($scope.userInfo.options){ for (var i=0; i<$scope.userInfo.options.length; i++) { switch($scope.userInfo.options[i].type){ case 'EMAIL' : $scope.userInfo.options[i].label = $scope.$filter('translate')('oob.option.email'); break; case 'VOICE' : $scope.userInfo.options[i].label = $scope.$filter('translate')('oob.option.voice'); break; case 'SMS' : $scope.userInfo.options[i].label = $scope.$filter('translate')('oob.option.sms'); break; default: $scope.userInfo.options[i].label = $scope.$filter('translate')('oob.option.other'); break; } } } // If oobResponse returns a redirect flag, it means it needs to go to SSG to get OOB Options if (oobResponse.redirect) { if($scope.userInfo.deviceFingerprintEnabled) { if ($scope.IntelligentAuthenticationService.getDeviceName()) { $scope.VIPLoginService.setRememberDeviceAuthInfoWithDeviceName( String($scope.IntelligentAuthenticationService.getShowRememberDevice()), String($scope.IntelligentAuthenticationService.getRememberDevice()), String($scope.IntelligentAuthenticationService.getDeviceName())); } else { $scope.VIPLoginService.setRememberDeviceAuthInfo( String($scope.IntelligentAuthenticationService.getShowRememberDevice()), String($scope.IntelligentAuthenticationService.getRememberDevice())); } } $scope.$state.go('redirectOOB'); return; } else if ($scope.userInfo.options && $scope.userInfo.options.length > 0){ // default the first one as selected $scope.oobOption = $scope.userInfo.options[0].id; } else if(oobResponse.messages && oobResponse.messages.length > 0){ $rootScope.addPendingMessage(angular.lowercase(oobResponse.statusCode), oobResponse.messages[0].message); $scope.$state.go('auth.securityCode'); return; } // The sendOob options logic should be in the current controller. However, there is a send Again link // which will call the same function. But that link is in the home controller which is the $rootScope // Here I just call the $rootScope's sendOob. $scope.sendOob = function(){ $rootScope.sendOob($scope.oobOption); // OIDC integration if ($scope.userInfo.authType === 'oidc') { $scope.userInfo.usedOOBAuthenticationMethod = true; if ($scope.userInfo.options) { for (var i = 0; i < $scope.userInfo.options.length; i++) { if ($scope.userInfo.options[i].id === $scope.oobOption) { switch ($scope.userInfo.options[i].type) { case 'EMAIL': VIPLoginService.setAuthenticationMethod('OTP'); break; case 'VOICE': VIPLoginService.setAuthenticationMethod('TEL'); break; case 'SMS': VIPLoginService.setAuthenticationMethod('SMS'); break; default: VIPLoginService.setAuthenticationMethod('OTP'); break; } } } } } } if (!$scope.userInfo.hasCredentials) { $scope.isDisabled = true; } $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'; } if (!$scope.mobileFallback) { // if MO fallback is disabled and land to OOB, then allowed to My VIP $scope.userInfo.shouldRedirectToNgSSSP = 'true'; VIPLoginService.setSAMResponseToSSP('true'); } }]); 'use strict'; angular.module('vipLogin.controllers') .controller("UserPinLoginController", ['$scope', '$rootScope', 'VIPLoginService', 'messageUtils', 'UserInfo', function ($scope, $rootScope, VIPLoginService, messages, UserInfo) { $scope.toggleModal = function() { $scope.modalShown = !$scope.modalShown; }; $scope.userInfo = UserInfo.getUserInfo(); // this logic should be the same as the logic in userPinLogin.html //
$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'){ $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'){ $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') { $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.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 { // 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.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.stateSwitch(result); }); } else { // Removed iaEnabled checking - VIPAWS-17208 if ($scope.userInfo.deviceFingerprintEnabled) { $scope.IntelligentAuthenticationService.setCode($scope.securityCode); if ($scope.ipCookie($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) { var allHeaders = result.headers(); var contentLength = result.headers('Content-Length'); var vipContentLength = result.headers('vip-content-length'); // If response is modified if (vipContentLength !== contentLength) { 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(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.userInfo.MFaForIaEnabledJh && ($scope.IntelligentAuthenticationService.getShowRememberDevice() == null)){ 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); } }else{ 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'); $scope.userInfo.MFaForIaEnabledJh = false 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) { $scope.ipCookie($scope.userInfo.userId, 'neverRememberDevice', { expires: 180 }); } $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.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 = ''); 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 = '
' }; }); '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: "" } }).directive('ngFooter', 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 transclude: false, replace: true, templateUrl: "app/partials/ngFooter.html" } }); 'use strict'; // angular.module('vipLogin.directives') .directive('inlineHelp', function() { return { // Restrict it to be an attribute in this case restrict: 'C', // responsible for registering DOM listeners as well as updating the DOM link: function(scope, element, attrs) { element.poshytip({ className: 'tip-blue', showTimeout: 1, alignTo: 'target', alignX: 'right', alignY: 'center', offsetY: 5, allowTipHover: true, liveEvents: true, showOn: 'none', offsetX: 10, closeButton: true, closeImage: '', content: function() { return $(this).find(".inlineHelpContent").html(); } }); element.click(function(e) { element.poshytip('show'); }); $(document).mouseup(function (e) { try{ var container = $(".tip-blue"); if (container.has(e.target).length === 0 && $(element).length >0) { element.poshytip('hide'); } }catch(e){} }); } }; }) .directive('qtipHelp', function() { return { restrict: 'A C', link: function(scope, element, attrs) { var my = attrs.qtipMy || 'top center', at = attrs.qtipAt || 'bottom center', target = attrs.qtipTarget || element, show = attrs.qtipShow || 'click focus', hide = attrs.qtipHide || 'mouseout blur', suppress = attrs.qtipSuppress || false, content = attrs.alt || attrs.title, //render = scope.$parent.$eval(attrs.qtipRender || true), render = true, className = attrs.qtipClassName || 'qtip-viplogin'; if(!angular.isElement(target)) { target = angular.element('#'+target); } if(render === true) { element.qtip({ content: content, show: show, hide: hide, suppress: suppress, style: { classes: 'qtip-viplogin', tip: { corner: 'top center' }, def: false }, position: { my: my, at: at, target: target, adjust: { resize: true } } }); } } }; }); 'use strict'; angular.module('vipLogin.directives').directive('match', [function () { return { restrict: 'A', scope:true, require: 'ngModel', link: function (scope, elem , attrs,control) { var checker = function () { //get the value of the first pin, attrs.match refer to the value that pass in from match="newPin" var newPin = scope.$eval(attrs.match); //get the value of the confirm pin var confirmNewPin = scope.$eval(attrs.ngModel); console.log("newPin: " + newPin + " confirmNewPin: " + confirmNewPin); return newPin === confirmNewPin; }; scope.$watch(checker, function (n) { console.log("listener is called with value : " + n); control.$setValidity("match", n); }); } }; }]); angular.module('vipLogin.directives').directive('equals', function() { return { restrict: 'A', // only activate on element attribute require: '?ngModel', // get a hold of NgModelController link: function(scope, elem, attrs, ngModel) { if(!ngModel) return; // do nothing if no ng-model // watch own value and re-validate on change scope.$watch(attrs.ngModel, function() { validate(); }); // observe the other value and re-validate on change attrs.$observe('equals', function (val) { validate(); }); var validate = function() { // values var val1 = ngModel.$viewValue; var val2 = attrs.equals; // set validity ngModel.$setValidity('equals', ! val1 || ! val2 || val1 === val2); }; } } }); // experimental to avoid ngMaxlength clearing and setting model to undefined. angular.module('vipLogin.directives').directive('vipMaxlength', function() { return { require: 'ngModel', link: function (scope, element, attrs, ctrl) { var maxlength = Number(attrs.myMaxlength); function fromUser(text) { if (text.length > maxlength) { var transformedInput = text.substring(0, maxlength); ctrl.$setViewValue(transformedInput); ctrl.$render(); return transformedInput; } return text; } ctrl.$parsers.push(fromUser); } }; }); angular.module('vipLogin.directives').directive('onFinishRender', function ($timeout) { return { restrict: 'A', link: function (scope, element, attr) { if (scope.$last === true) { scope.$evalAsync(attr.onFinishRender); } } } }); angular.module('vipLogin.directives').directive("changeDevicenameDirective", function($interpolate) { return { compile: function (telem, tattrs) { var interpolateFn = $interpolate(telem.html(), true); telem.empty(); return function(scope, elem, attrs){ scope.$watch(interpolateFn, function (value) { var currentText = value; if (currentText.length > 21) { currentText = currentText.substring(0, 18) + '...'; } elem.text(currentText); }); } } } }); angular.module('vipLogin.directives').directive("changeRemembernameDirective", function($interpolate) { return { compile: function (telem, tattrs) { var interpolateFn = $interpolate(telem.html(), true); telem.empty(); return function(scope, elem, attrs){ scope.$watch(interpolateFn, function (value) { var currentText = value; if (currentText.length > 18) { currentText = currentText.substring(0, 15) + '...'; } elem.text(currentText); }); } } } });