I have a HTML5/JQuery cordova hybrid application which communicates with external REST webservice to get the data for the page dynamic content. These REST resources are protected by Siteminder SSO. All calls to the webservice are intercepted by siteminder and if the session is not active it throws up the siteminder login challenge page.
How can we handle the siteminder login page in the mobile app?
Presently we have index.html on which onload, the page(index.html) is submitted and hits the protected REST service but siteminder intercepts to throw the challenge page. After authentication, it it able to access the protected REST service and returns a json result of "success" from the REST service.
Based on this, we need to invoke other pages/REST services from the mobile passign on the siteminder cookie for session verification. What is the correct way of achieving this?
Finally I have been able to get it working with the following approach:
- All the REST resources URL must be protected by siteminder.
Define a GET service which is also a protected resource and will be used for initiating the siteminder session.
e.g
@Context private HttpServletRequest httpRequest;
@GET
@Path("/OAMSSO")
@Produces(MediaType.APPLICATION_JSON)
public Response getOAMSSO() {
URI uri = null; UriBuilder uriBuilder = null;
String redirectHost = "https://localhost/callback";
uri = uriBuilder.queryParam("statusCode", "100")
.queryParam("authenticated", "true")
.queryParam("userName",
headers.getHeaderString("SM_USER")).build();
return Response.seeOther(uri).build();
}
In your JS, the following code will initiate the siteminder SSO Authentication in an InAppBrowser. InAppBrowser is a Cordova plugin which needs to be added to your project.
cordova plugin add cordova-plugin-inappbrowser
function getParameterByName(url, name) {
var match = RegExp('[?&]' + name + '=([^&]*)').exec(url);
return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
}
document.addEventListener("deviceReady", "onDeviceReady",false);
function onDeviceReady() {
callOAMSSO();
}
function callOAMSSO() {
var url = **<<yourProtectedServiceURL>>**/OAMSSO";
var target = '_blank';
var options = "location=yes,toolbar=yes,clearcache=yes,clearsessioncache,enableViewportScale=yes";
var redirectURL = "https://localhost/callback";
var ref = cordova.InAppBrowser.open(url, target, options);
ref.addEventListener('loadstart', loadstartCallback);
ref.addEventListener('exit', exitCallback);
function loadstartCallback(event) {
var url = event.url;
if(url.indexOf(redirectURL) > -1){
ref.close();
var statusCode = getParameterByName(url, 'statusCode');
var authenticated = getParameterByName(url, 'authenticated');
var userName = getParameterByName(url, 'userName');
if(statusCode && userName){
sessionStorage.userName = userName.toUpperCase();
sessionStorage.userNameisValid = "Y";
setTimeout(**invokeYourFunctionForOtherTasks**, 10);
}
}
}
function exitCallback() {
alert('Browser is closed...');
}
}
when your app opens, an InAppBrowser will open, and will try to fetch the OAMSSO protected resource. Sicne it is siteminder protected and no session is available, the SSO page opens up in the browser where the user can put in the credentials and submit. If the credentials are successful, siteminder will add a SMSESSION cookie and then redirect to the OAMSSO REST resource. The OAMSSO REST resource extracts the siteminder authenticated username and appends as a query param to the callback method i.e redirects to localhost/callback. This is just a dummy URL to identify that the user has been authenticated by siteminder. In the JS, you can check for this URL load, extract the username and then proceed to other tasks of your application. since the siteminder session is already active, you can access other protected resources of your REST service from you app.
Hope this helps anyone dealing with siteminder SSO authentication from Javascript.