Logoff/Logout function for a UI5 Apllication
Though I have been working on UI5 for sometime, I had never explored Logoff functionality. I always thought that it would be as simple as calling an API and redirecting to a logoff page. Once I started, there were so many hurdles and I got to learn a great deal about cookies and authentication. I am sharing this experience in implementing a “Logoff” functionality for a UI5 application. My aim of writing this blog is to share the learning as well as to explore if there are better approaches. Source: Numerous posts on stackoverflow.com
Set Up: UI5 application hosted in a Basis 740 SP5 system as NW Gateway server.
Loging off a user involves two steps
1. Invalidating the SSO cookies.
2. Deleting the Authentication cache stored by the browsers
Step 1. Invalidating the SSO cookies.
I learned that SAP provides a logoff service which can clear the SSO cookie in the browser. This is a service stored under ‘public’ node. When called as a GET request, this service returns set-cookie headers as response headers with an expiration date in the past. Browser, on receiving the set-cookie, sets these values with the current SSO cookies, thus invalidating them. If you are using a different server to host your UI application, check the documentation to find a similar logoff service.
Step 2. Deleting the Authentication cache stored by the browsers
This step differs from browser to browser. Always abused IE 🙂 does a better job by providing a javascript API to this task. For other browsers, you need to make a call to the server with dummy credentials so that browser receives a “401-Unauthorized” which forces the browser to delete the stored authorization headers. Again ever useful jQuery provides a call back function to handle 401 error so that user is not shown an awkward authorization credentials pop-up.
Below is the code I arrived at. I have only tested on latest versions of Mozilla, Chrome and IE. Also only Basic Authentication scenarios has been tested. Let me know your ideas and suggestions to improve this.
function logoff(){
$.ajax({
type: "GET",
url: "/sap/public/bc/icf/logoff", //Clear SSO cookies: SAP Provided service to do that
}).done(function(data){ //Now clear the authentication header stored in the browser
if (!document.execCommand("ClearAuthenticationCache")) {
//"ClearAuthenticationCache" will work only for IE. Below code for other browsers
$.ajax({
type: "GET",
url: "/sap/opu/odata/SOME/SERVICE", //any URL to a Gateway service
username: 'dummy', //dummy credentials: when request fails, will clear the authentication header
password: 'dummy',
statusCode: { 401: function() {
//This empty handler function will prevent authentication pop-up in chrome/firefox
} },
error: function() {
//alert('reached error of wrong username password')
}
});
}
})
}
Hi Krishna
I have had to do something similar before, the requirement was to trigger a clean up when the user closed the browser or redirected
when the application loads bind the exit function to the unload event, the exit function did a few things including clearing the user context.
with the unload event you have a very small amount of time to do your processing, often it wont wait round for an async callback, so i use a synchronous call instead
something like
jsp
For the solution we used a different approach, we did a page re-direct to a logout page and then cleared the cache using the below code
This worked on Mozilla, Chrome, Safari and IE.
Martin
Martin, Someone has to clear the SSO cookies. How did you achieve that?
What I saw was, even if I has missed one of the steps (SSO cookie and authentication cache), the application would login using the missed step.
Also ClearAuthenticationCache will work only for IE. Others will return False.
Sorry did not expand on the set-up for the logout page, we running the application as BSP so we define the logout page with the below ABAP
<%
CLASS cl_bsp_login_application DEFINITION LOAD.
DATA: lv_url TYPE string,
lv_params type string,
lv_path type string.
CONCATENATE '/sap/public/bsp/sap/public/bc/bsp/Logout.htm?IV_LANGUAGE=' IV_LANGUAGE into lv_path.
lv_url = CL_BSP_LOGIN_APPLICATION=>GET_SESSIONEXIT_URL( ).
lv_url = cl_http_utility=>escape_html( lv_url ).
lv_params = CL_BSP_LOGIN_APPLICATION=>SET_LOGOFF_URL_PARAM( url = lv_path ).
CONCATENATE CL_BSP_LOGIN_APPLICATION=>CO_BSP_APPLICATION lv_params
INTO lv_params SEPARATED BY '='.
lv_params = cl_http_utility=>escape_html( lv_params ).
%>
Then do the re-direct with the below HTML
var url = "<%= lv_url%>";
url += "&<%= lv_params%>";
self.location.href=url;
So yes you correct the ClearAuthenticationCache is our fail safe for IE.
Sorry for the not providing the complete picture.
Martin
Hi Krishna,
I tried to logout in my application using your code, I could logout from the desktop but I was not able logout in the mobile browser.when i clicked logout it shows authorization credential popup.
Hi guys,
is there a solution to prevent the authorization credentials pop-up in Safari too?
Cheers,
Sebastian.
Was there a solution for Safari ?
Hello Achint,
sorry for the late response.
For this described solution from Krishna Kishor Kammaje I found no solution for safari.
So currently I am just calling the icf service: "/sap/public/bc/icf/logoff" for logoff.
Regards,
Sebastian.
Thank you Karishna for such an excellent solution. Here I have enhanced your code so that the browser redirect itself to some useful web page or login page again after logoff.
Thank you Krishna, it works for me.
shell.attachLogoutButtonPress(function() {
if (!document.execCommand("ClearAuthenticationCache")) {
//"ClearAuthenticationCache" will work only for IE. Below code for other browsers
$.ajax({
type: "GET",
url: "/sap/opu/odata/SOME/SERVICE", //any URL to a Gateway service
username: 'dummy', //dummy credentials: when request fails, will clear the authentication header
password: 'dummy',
statusCode: { 401: function() {
} },
error: function() {
//alert('reached error of wrong username password')
}
});
}
Hi Lulu,
I have enabled the "logoff" through the following coding in my index.html file
var oAppHeader = new sap.ui.commons.ApplicationHeader("appHeader");
oAppHeader.setDisplayLogoff(true);
Now where do I need to write the code as mentioned by you?
In the main controller? or somewhere else?
Regards,
Firoz.
Got it !!
The code has to be placed as shown below:
var oAppHeader = new sap.ui.commons.ApplicationHeader("appHeader").attachLogoff(function(){
/////////////LOG OFF FUNCTION CODE STARTS HERE/////////////
});
Thanks.
I think the easiest way to logout User is using Launchpads/ushells-Container Service:
Simply invoke sap.ushell.Container.logout(); and the same as by clicking Fiori Launchpads Log-Off button should happen.....
This is working abs. fine but wheni am using this it is showing DOM structure manipulation... is there any alternate way to add log off in custom apps