- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
10-07-2019 02:02 AM
Hello,
I am facing an issue with the plugin e-signature and the widget approval for the service portal. We are in new york version so it should be fine as it's written in the documentation , but when an user clicks on the approve button, they are not "forced" to authenticate as they should. We can only see a quick pop up as the authentification is done by SSO. We would like to display a login/password window for every approval.
I guess the issue comes from the spAuthModal but I can't find the code on the platform. As it's working fine in the backend.
Does anyone have a solution for this issue?
Solved! Go to Solution.
- Labels:
-
Service Portal Development
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
10-08-2019 05:19 AM
So finally in my case, I have been able to do the double authentication by adding my modal in the widget, and removing the call to the OOB authentification. I have also modified the client controller by adding functions to auth the user as it's done in the login widget.
So this is my modal :
<div class="modal" id="LoginModalCenter">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLongTitle">Approver Authentification</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form class="form-signin" ng-submit="c.login(c.username, c.password)" method="post">
<div class="list-group-item">
<label for="username" class="sr-only ng-binding">${User name}</label>
<input id="username" name="username" autocapitalize="off" class="form-control no-border ng-pristine ng-valid ng-empty ng-touched" type="text" placeholder="${User name}" autofocus="true" ng-model="c.username" ng-change="c.onUsernameChange()" role="textbox" aria-invalid="false">
</div>
<div class="list-group-item">
<label for="password" class="sr-only ng-binding">${Password}</label>
<input id="password" name="password" class="form-control no-border ng-pristine ng-untouched ng-valid ng-empty" type="password" placeholder="${Password}" ng-model="c.password" role="textbox" ng-change="c.onPasswordChange()" aria-invalid="false">
</div>
<button name="login" type="submit" class="btn btn-lg btn-primary btn-block">
${Ok}
</button>
<div ng-if="c.message" class="alert alert-danger" role="alert">{{c.message}}</div>
</form>
</div>
</div>
And this is my client controller
function ($scope, spUtil, snRecordWatcher,spUIActionsExecuter,spModal,spAuthModal, $http, $window, $location, urlTools, glideUserSession, glideSystemProperties) {
var c = this;
if ($scope.options.portal == true || $scope.options.portal == 'true') {
$scope.contentColClass = "col-xs-12";
$scope.options.portal = true;
} else {
$scope.options.portal = false;
$scope.contentColClass = "col-sm-9";
}
$scope.data.op = "";
snRecordWatcher.initList("sysapproval_approver", "state=requested^approver=" + window.NOW.user_id);
function get() {
spUtil.update($scope);
}
$scope.$on('record.updated', function(name, data) {
get();
})
var ESIGNATURE = {
TYPE: "form",
APPROVE_SYS: "cbfe291147220100ba13a5554ee4904d",
REJECT_SYS: "580f711147220100ba13a5554ee4904b"
};
$scope.approve = function(id, esigRequired) {
// var requestParams = {
// username: $scope.data.esignature.username,
// userSysId: $scope.data.esignature.userSysId
// };
// var username= $scope.data.esignature.username;
// var userSysId= $scope.data.esignature.userSysId;
// if($scope.data.esignature.e_sig_required && esigRequired) {
// spUIActionsExecuter.executeFormAction(ESIGNATURE.APPROVE_SYS, "sysapproval_approver" , id, [] , "", requestParams).then(function(response) {});
// } else {
// $scope.data.op = "approved";
// $scope.data.target = id;
//get();
// }
$scope.data.target = id;
$scope.data.op = "approved";
$('#LoginModalCenter').modal('toggle');
}
$scope.reject = function(id, esigRequired) {
// var requestParams = {
// username: $scope.data.esignature.username,
// userSysId: $scope.data.esignature.userSysId
// };
// if($scope.data.esignature.e_sig_required && esigRequired) {
// spUIActionsExecuter.executeFormAction(ESIGNATURE.REJECT_SYS, "sysapproval_approver" , id, [] , "", requestParams).then(function(response) {
// });
// } else {
$scope.data.op = "rejected";
$scope.data.target = id;
$('#LoginModalCenter').modal('toggle');
//get();
// }
}
// pagination
$scope.previousPage = function() {
if ($scope.data.pagination.currentPage > 1)
$scope.data.pagination.currentPage = $scope.data.pagination.currentPage - 1;
else
$scope.data.pagination.currentPage = 0;
get();
}
$scope.nextPage = function() {
$scope.data.pagination.currentPage = $scope.data.pagination.currentPage+1;
get();
}
c.login = function(username, password) {
var url = spUtil.getURL({sysparm_type: 'view_form.login'});
// If the page isn't public then the id in the
// url won't match the rendered page id.
//var pageId = $location.search().id || $scope.page.id;
//var isLoginPage = $scope.portal.login_page_dv == pageId;
//console.log("URL"+url);
return $http({
method: 'post',
url: url,
data: urlTools.encodeURIParameters({
'sysparm_type': 'login',
'ni.nolog.user_password': true,
'user_name': username,
'user_password': password,
'get_redirect_url': true
}),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}).then(function(response) {
if (!response.data) {
//console.log("Error");
c.message = $scope.data.errorMsg;
return;
}
if (response.data.status == 'success') {
//$scope.data.op = "approved";
//$scope.data.target = id;
//console.log("ID ? : "+$scope.data.target);
get();
$('#LoginModalCenter').modal('toggle');
return "success";
//$window.location = response.data.redirect_url;
} else {
// wrong username or password
c.password = "";
c.message =("Wrong password or username");
//spUtil.addErrorMessage("Wrong password") ;
return "failure";
//$scope.data.auth_response = "failure";
//c.message = response.data.message;
//c.password = "";
}
}, function errorCallback(response) {
// error
c.message = $scope.data.errorMsg;
});
};
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
10-07-2019 03:45 AM
I have finally managed to find a solution, it's more like a workaround :
In the server script instead of
if($scope.data.esignature.e_sig_required && esigRequired) {
spUIActionsExecuter.executeFormAction(ESIGNATURE.APPROVE_SYS, "sysapproval_approver" , id, [] , "", requestParams).then(function(response) {});
I have used this :
spModal.open({
title: 'Approver Authentification',
widget: 'login_widget'
}).then(function(){
$scope.data.op = "approved";
$scope.data.target = id;
get();
});
So my widget login_widget is just a simple authentification widget, you can copy it from the OOB widget SimpleLoginUI
You will need to do the same for the rejection part
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
10-07-2019 07:23 PM
Is this an intentional double auth?
If the user is already signed in what purpose is there in making them sign in again? If this is a security / preventative human error issue, it may be easier to just implement a confirmation dialog box rather than making the user sign in again, especially if you already have SSO implemented which is designed to remove the need for users to log in constantly.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
10-08-2019 01:16 AM
Yes this is an intentional double auth, as for some audit/process we need to achieve this double auth.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
10-08-2019 05:19 AM
So finally in my case, I have been able to do the double authentication by adding my modal in the widget, and removing the call to the OOB authentification. I have also modified the client controller by adding functions to auth the user as it's done in the login widget.
So this is my modal :
<div class="modal" id="LoginModalCenter">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLongTitle">Approver Authentification</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form class="form-signin" ng-submit="c.login(c.username, c.password)" method="post">
<div class="list-group-item">
<label for="username" class="sr-only ng-binding">${User name}</label>
<input id="username" name="username" autocapitalize="off" class="form-control no-border ng-pristine ng-valid ng-empty ng-touched" type="text" placeholder="${User name}" autofocus="true" ng-model="c.username" ng-change="c.onUsernameChange()" role="textbox" aria-invalid="false">
</div>
<div class="list-group-item">
<label for="password" class="sr-only ng-binding">${Password}</label>
<input id="password" name="password" class="form-control no-border ng-pristine ng-untouched ng-valid ng-empty" type="password" placeholder="${Password}" ng-model="c.password" role="textbox" ng-change="c.onPasswordChange()" aria-invalid="false">
</div>
<button name="login" type="submit" class="btn btn-lg btn-primary btn-block">
${Ok}
</button>
<div ng-if="c.message" class="alert alert-danger" role="alert">{{c.message}}</div>
</form>
</div>
</div>
And this is my client controller
function ($scope, spUtil, snRecordWatcher,spUIActionsExecuter,spModal,spAuthModal, $http, $window, $location, urlTools, glideUserSession, glideSystemProperties) {
var c = this;
if ($scope.options.portal == true || $scope.options.portal == 'true') {
$scope.contentColClass = "col-xs-12";
$scope.options.portal = true;
} else {
$scope.options.portal = false;
$scope.contentColClass = "col-sm-9";
}
$scope.data.op = "";
snRecordWatcher.initList("sysapproval_approver", "state=requested^approver=" + window.NOW.user_id);
function get() {
spUtil.update($scope);
}
$scope.$on('record.updated', function(name, data) {
get();
})
var ESIGNATURE = {
TYPE: "form",
APPROVE_SYS: "cbfe291147220100ba13a5554ee4904d",
REJECT_SYS: "580f711147220100ba13a5554ee4904b"
};
$scope.approve = function(id, esigRequired) {
// var requestParams = {
// username: $scope.data.esignature.username,
// userSysId: $scope.data.esignature.userSysId
// };
// var username= $scope.data.esignature.username;
// var userSysId= $scope.data.esignature.userSysId;
// if($scope.data.esignature.e_sig_required && esigRequired) {
// spUIActionsExecuter.executeFormAction(ESIGNATURE.APPROVE_SYS, "sysapproval_approver" , id, [] , "", requestParams).then(function(response) {});
// } else {
// $scope.data.op = "approved";
// $scope.data.target = id;
//get();
// }
$scope.data.target = id;
$scope.data.op = "approved";
$('#LoginModalCenter').modal('toggle');
}
$scope.reject = function(id, esigRequired) {
// var requestParams = {
// username: $scope.data.esignature.username,
// userSysId: $scope.data.esignature.userSysId
// };
// if($scope.data.esignature.e_sig_required && esigRequired) {
// spUIActionsExecuter.executeFormAction(ESIGNATURE.REJECT_SYS, "sysapproval_approver" , id, [] , "", requestParams).then(function(response) {
// });
// } else {
$scope.data.op = "rejected";
$scope.data.target = id;
$('#LoginModalCenter').modal('toggle');
//get();
// }
}
// pagination
$scope.previousPage = function() {
if ($scope.data.pagination.currentPage > 1)
$scope.data.pagination.currentPage = $scope.data.pagination.currentPage - 1;
else
$scope.data.pagination.currentPage = 0;
get();
}
$scope.nextPage = function() {
$scope.data.pagination.currentPage = $scope.data.pagination.currentPage+1;
get();
}
c.login = function(username, password) {
var url = spUtil.getURL({sysparm_type: 'view_form.login'});
// If the page isn't public then the id in the
// url won't match the rendered page id.
//var pageId = $location.search().id || $scope.page.id;
//var isLoginPage = $scope.portal.login_page_dv == pageId;
//console.log("URL"+url);
return $http({
method: 'post',
url: url,
data: urlTools.encodeURIParameters({
'sysparm_type': 'login',
'ni.nolog.user_password': true,
'user_name': username,
'user_password': password,
'get_redirect_url': true
}),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}).then(function(response) {
if (!response.data) {
//console.log("Error");
c.message = $scope.data.errorMsg;
return;
}
if (response.data.status == 'success') {
//$scope.data.op = "approved";
//$scope.data.target = id;
//console.log("ID ? : "+$scope.data.target);
get();
$('#LoginModalCenter').modal('toggle');
return "success";
//$window.location = response.data.redirect_url;
} else {
// wrong username or password
c.password = "";
c.message =("Wrong password or username");
//spUtil.addErrorMessage("Wrong password") ;
return "failure";
//$scope.data.auth_response = "failure";
//c.message = response.data.message;
//c.password = "";
}
}, function errorCallback(response) {
// error
c.message = $scope.data.errorMsg;
});
};
}