NAM: Application Hosted Login Page and Passing Session Timeout and Other Login Failed Responses

NAM: Application Hosted Login Page and Passing Session Timeout and Other Login Failed Responses

I recently received requirements from a project to protect an application behind NAM (3.1.1) that had its own application login page. This login page would submit its login page authentication data to NAM and then be taken to the authenticated parts of the NAM proxied application.

Also they did not want to display any of the default NAM Authentication Cards.

Another requirement was to pass parameters back to the application login page when a user encountered things like:

  • Login Failed

  • Account Disabled

  • Intruder Lockout

  • Session Timeout (Not supported by NAM)



Yet another requirement was to allow users go straight to the application’s login page (via NAM) as well as dealing with users who book mark protected parts of the application. Under normal circumstances users would go straight to the application login page https://agw1.novell.com/app1/login.do

After much time spent reading documentation and posting on the forums here is how I made it work.

Initially NAM is configured like any other mixed public/private application.





Metadatahttps://agw.novell.com/nesp/idff/metadata
IDP Base URLhttps://idp.novell.com/nidp
Application Proxyhttps://agw1.novell.com/app1










Protected Resource List
/app1/*Contract_app1
/app1/login.doNone


The Contract



When the application’s login page posts the login data to the IDP, the IDP has no idea what contract it relates to. To address this in the Contract Contract_app1 under Authentication Card we specify a number of the ID attribute (eg 61).



Then in the application’s login page the form element looks like this:




<FORM id=login_form method=post name=IDPLogin action=https://idp.novell.com/nidp/idff/sso?id=61 &sid=0 AUTOCOMPLETE="off">



Also we need to tell the IDP that the contract is using a custom login page

Also in the Method of the contract we need to specify the property:






Property NameMainJSP
Property Valuetrue






We also need to specify the custom login page, the contents of which will be discussed latter:










Property NameJSP
Property Valueapp1login


Custom Login Page and Handling Standard Errors



As discussed previously we need to pass parameters back to the application’s login page on failed logins. To do this we need a custom login page to capture the error and redirect back to the applications login page with relevant flag.



Here's what we came up with:




<%@ page language="java" %>
<%@ page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>
<%@ page import="java.util.*" %>
<%@ page import="com.novell.nidp.*" %>
<%@ page import="com.novell.nidp.servlets.*" %>
<%@ page import="com.novell.nidp.resource.*" %>
<%@ page import="com.novell.nidp.resource.jsp.*" %>
<%@ page import="com.novell.nidp.ui.*" %>

<%
ContentHandler handler = new ContentHandler(request,response);

String hdrImage = "/custom_images/hhbimages.jpeg";
String err = (String) request.getAttribute(NIDPConstants.ATTR_LOGIN_ERROR);


String strURLBase = "https://agw1.novell.com/app1/login.do";
String redirectURL;

if (err == null)
{
redirectURL = strURLBase;

} else if (err.equals("Login failed, please try again."))

{
redirectURL = strURLBase + "?messageType=LoginFailed";

} else if (err.equals("User login has been disabled due to intruder detection."))
{

redirectURL = strURLBase + "?messageType=LockedAccount";

} else if (err.equals("Your login has been disabled."))
{

redirectURL = strURLBase + "?messageType=DisabledAccount";


} else {

redirectURL = strURLBase;

}

response.sendRedirect(redirectURL);



%>


Essentially if the attempts a login but fails with one of the following errors:



  • Login Failed

  • Account Disabled

  • Intruder Lockout


We redirect back to the application with the relevant “messageType=” in the query string.


The application’s code looks for the value of “messageType” in the query string and displays a nice message for the user.



Handling Session Timeouts.



By default the IDP does not have any inbuilt way that I'm aware of that indicates that the session has expired that can be used in the custom login page. After some help on the Novell forums we came up with a way to set a session cookie on a successful login, then add code to the custom login page to check if the cookie exists and pass a message back to the application login form “messageType=SessionTimedOut”



To set the cookie we need to modify top.jsp on the IDP as seen here:




<%@ page language="java" %>
<%@ page contentType="text/html" %>
<%@ page import="com.novell.nidp.ui.*" %>
<%@ page import="java.util.*" %>
<%@ page import="java.lang.*" %>
<%
UIHandler uh = new UIHandler(request,response);
String url = (String) request.getAttribute("url");
String target = (String) request.getParameter("target");

boolean CheckSetCookie = false;
if ((target.startsWith("https://agw1.novell.com/app1")))
{
Date now = new Date();
String timestamp = now.toString();

Cookie cookies [] = request.getCookies();
String cookieName = "IAMLoginSession";
Cookie myCookie = null;
int cookieSet = 0;

if (cookies != null)
{
for (int i = 0; i < cookies.length; i++)
{
if (cookies [i].getName().equals (cookieName))
{
//Cookie has been found, so the user has been here before
cookieSet = 1;
}
}
}

if (cookieSet == 0) {
//Cookie has not been found, setting new one
Cookie cookie = new Cookie ("IAMLoginSession",timestamp);
cookie.setPath("/nidp");
response.addCookie(cookie);
}

response.sendRedirect(url);
}

%>
<!DOCTYPE HTML PUBLIC "-//W3C//Dtd HTML 4.0 transitional//<%=uh.getLanguageCode()%>">
<html lang="<%=uh.getLanguageCode()%>">
<head>
<META HTTP-EQUIV="expires" CONTENT="0">
</head>
<body>

<script language="JavaScript">
top.location.href='<%=url%>';
</script>
</body>
</html>


Top.jsp is called on a successful authentication and in this modified version firstly checks to see if the target is the application we are interested in:



https://agw1.novell.com/app1



If it is then it's cookie IAMLoginSession already exists and if it doesn't sets the cookie value to the current date/time however the value is not used in my code.



Later on when the session expires and the user attempts to perform an action within the protected part of the application, the NESP redirects to the custom login page on the IDP. Now we need some code to check if the cookie exists and do something with it.




<%@ page language="java" %>
<%@ page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>
<%@ page import="java.util.*" %>
<%@ page import="com.novell.nidp.*" %>
<%@ page import="com.novell.nidp.servlets.*" %>
<%@ page import="com.novell.nidp.resource.*" %>
<%@ page import="com.novell.nidp.resource.jsp.*" %>
<%@ page import="com.novell.nidp.ui.*" %>

<%
ContentHandler handler = new ContentHandler(request,response);

String hdrImage = "/custom_images/hhbimages.jpeg";
String err = (String) request.getAttribute(NIDPConstants.ATTR_LOGIN_ERROR);


boolean foundCookie = false;

Cookie cookies [] = request.getCookies();
String cookieName = "IAMLoginSession";
int cookieSet = 0;

if (cookies != null)
{
for (int i = 0; i < cookies.length; i++) {
//out.println("<br/>" + cookies [i].getName());
if (cookies [i].getName().equals (cookieName))
{
//Cookie has been found, so the user has been here before
foundCookie = true;
}
}
}

String strURLBase = "https://agw1.novell.com/app1/login.do ";
String redirectURL;

if (err == null && !foundCookie)
{
redirectURL = strURLBase;

} else if (err == null && foundCookie)
{

redirectURL = strURLBase + "?messageType=SessionTimedOut";

} else if (err.equals("Login failed, please try again."))

{
redirectURL = strURLBase + "?messageType=LoginFailed";

} else if (err.equals("User login has been disabled due to intruder detection."))
{

redirectURL = strURLBase + "?messageType=LockedAccount";

} else if (err.equals("Your login has been disabled."))
{

redirectURL = strURLBase + "?messageType=DisabledAccount";


} else {

redirectURL = strURLBase;
}
response.sendRedirect(redirectURL);



%>


So what the updated custom login page code does is check for the existence of the cookie IAMLoginSession and if it exists set the boolean value foundCookie=true.


Then if there are no errors like Login Failed, we set the messageType=SessionTimedOut and pass that back to the application login page on the redirect.



So far this all seems to be working well.



I welcome any feedback on issues or ways this could be improved.



Labels (1)
Tags (1)

DISCLAIMER:

Some content on Community Tips & Information pages is not officially supported by Micro Focus. Please refer to our Terms of Use for more detail.
Comments
This all sounds very familiar...haha

Nice work AS

Good to see NAM can be as easily shoe horned as iChain was.
Nice job. Is this code still applicable to the 3.2 and 4.0 versions of NAM?
Hi ssripathy25,
we continue to have these customisations on the same version however the general logic should work on later versions. You may need to do some debugging.
In developing customisations I find it handy to add lines like:
out.println("<!--
PAGE:top.jsp-->");
out.println("<!--
url:" + url + "-->");
out.println("<!--
target:" + target + "-->");
out.println("<!--
idqueryString:" + idqueryString + "-->");
Then you can use a http tracing tool like Fiddler2 to see what values are in the jsp's and what jsp is what.
Top Contributors
Version history
Revision #:
3 of 3
Last update:
‎2020-01-31 22:07
Updated by:
 
The opinions expressed above are the personal opinions of the authors, not of Micro Focus. By using this site, you accept the Terms of Use and Rules of Participation. Certain versions of content ("Material") accessible here may contain branding from Hewlett-Packard Company (now HP Inc.) and Hewlett Packard Enterprise Company. As of September 1, 2017, the Material is now offered by Micro Focus, a separately owned and operated company. Any reference to the HP and Hewlett Packard Enterprise/HPE marks is historical in nature, and the HP and Hewlett Packard Enterprise/HPE marks are the property of their respective owners.