How to Bypass Oracle Apps R12 Login

Recently we have a requirement to create a custom JSP Page to bypass Oracle Apps Login rather launching Oracle Apps Main Home Page through silent Login. Before I discuss about the creation of JSP I want to throw some light about the background of getting this kind of weird requirement.

Its about integrating third party Login Server to Oracle Applications server for security reasons as Oracle applications server is exposed to external users for use and there is high risk of attack over the Internet. This security featue is implemented using Reverse Proxy technique. First I will make you all understand what is Reverse Proxy. It is a kind of proxy server which retrieves resources from other servers on behalf of client. Basically it is security device installed over the network in order to secure HTTP servers e.g Oracle Applications server from the attack of users. one such security device is IBM Tivoli Access Manager(TAM) which works on Reverse Proxy.

The external users will get that TAM login page where they will enter TAM username,generally it is users’ email id and password, generated by TAM server. The same username should be present in Oracle Applications Database and there is a 1:1 mapping of TAM password and Oracle password for the same username. Please note, Oracle Password and TAM password may not be same. As soon as external users enter username and TAM password, TAM uses the authentication feature of Oracle Applications and if it is successfully authenticated, then users are redirected to Oracle Apps main home page where responsibility, menu and functions are visible.

Here I must mention one very important thing that when user launches TAM login page, the user visualizes TAM’s own URL and throughout all the transactions they will see TAM URL only, even for Oracle apps pages also that does mean TAM URL will override the Oracle Apps Host Address URL. So what I mentioned earlier that TAM works on reverse proxy technique to enable security for external users and to protect Oracle Apps Server from any possible external attack over the internet.

Problem Description:

This entire process of launching TAM login page, entering credentials, being validated taking user to Oracle Apps main home page was possible and working fine for Oracle apps version 11i as in 11i the apps login page is a static JSP Page and integration of TAM server and Oracle Apps server was pretty simple.

But in Oracle Apps R12, once the user enter credentials in TAM login page, being validated instead of taking user to the Oracle Apps main home page, it lands user to oracle apps login page, that does mean TAM is unsuccessful to penetrate the oracle login feature so that it can make user silently login to Oracle apps or rather bypass Oracle login feature.

The reason behind this is the login page in R12 viz. RF.jsp is no longer a static JSP Page as in 11i viz. AppslocalLogin.jsp but its a dynamic JSP Page, as the login Page is being generated upon execution of some javascripts. Because of this, TAM and Apps Integration was not working as it was working earlier in Oracle Apps 11i.

Now, I will give a high level overview of the login flow in R12. As soon as URL of the instance is typed in the address bar of the web browser, first AppsLocalLogin.jsp is invoked, which in turn executes some javascript and generates RF.jsp, which is nothing but the Oracle Apps R12 login page, where user has to enter credentials viz. username and password in order to login , then the entered username and password is being validated by MainLoginPG.xml, an OA Page and controller MainLoginCO.class attached to this page, which internally uses fndvald.jsp which in turn invokesA�AuthenticateUser.class Servlet. If the authentication is successful then the user will be redirected to HomePG.xml where user will be able to see the responsibilities,menus and functions attached to the concerned user. Please note internally it invokes so many JSP Servlet classes like WebAppsContext. The flow given above is solely based on my understanding and it is just for basic understanding.

Solution Approach:

At first I have created a dummy Login page which is acting Third Party Login Page. where user will enter credentials and internally it will invoke AppsLocalLogin.jsp. We have to amend the changes in this AppsLocalLogin.jsp file, where we will retrieve the credentials entered in the third party login page and with the same we will further forward the request to theA�AuthenticateUser servlet, which validate the credentials using oracle’s seeded user authentication feature and let the user land into Oracle Apps Main page.

Solution:

Now I will delve into the coding details:

First we have to design an dummy third party login page. Here is the code written for building the JSP page, lets say DummyLogin.jsp, its basically very rudimentary in nature:

<%
@page contentType="text/html" pageEncoding="UTF-8"%>
 <html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 <title>Login Page</title>
 </head>
 <body>
 <h1>Login Page</h1>
 <center>
 <h2>Signup Details</h2>
 <form action="AppsLocalLogin.jsp" method="POST"> <br/>
 Username:<input type="text" name="uid"><br/>
 Password:<input type="password" name="pwd"> <br/>
 <input type="submit" value="Submit">
 </form>
 </center>
 </body>
 </html>

Please note request method is POST as we don’t want to send the username and password through URL appending and POST is more secure than GET method. Once the Submit button is clicked, the page will invoke AppsLocalLogin.jsp which is mentioned in the form action.

Now, we have to get the username and password in the AppsLocalLogin.jsp

String username=request.getParameter("uid");
 String password=request.getParameter("pwd");

Then we have to invoke the AuthenticateUser servlet using JSP Forward architecture. The reason behind using this architecture not the SendRedirectURL is because in sendRedirectURL username and password will be shown in the URL and moreover there will be an entry in the Apache Access Log which is not desirable. To avoid this circumstance and to make the client-server communication more secure, we have used JSP Forward architecture. Here is the code snippet:

<%
String customUrl = "/AuthenticateUser?username="+username+"&password="+password;
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);
try {
%>
<jsp:forward page="<%=customUrl%>" />
<%
} catch(Exception e) {
%>
<b>Error occured : <%= e.getMessage()%></b>
<%= e%>

Here is the entire JSP file after having amended the changes:

<%-- $Header: AppsLocalLogin.jsp 120.9.12010000.2 2011/08/16 19:41:12 ctilley ship $ --%>
<%@ page import='oracle.apps.fnd.sso.SessionMgr'%>
 <%@ page import='oracle.apps.fnd.sso.SSOUtil'%>
 <%@ page import='oracle.apps.fnd.sso.SecureHttpRequest'%>
 <%@ page import='oracle.apps.fnd.common.WebAppsContext'%>
 <%@ page import='oracle.apps.fnd.common.LangInfo'%>
 <%@ page import='oracle.apps.fnd.sso.Utils'%>
 <%@ page import='oracle.apps.fnd.login.LoginPage'%>
 <%@ page import='oracle.apps.fnd.util.URLEncoder'%>
 <%@ page import='java.util.Enumeration'%>
 <%@ page import='java.sql.Connection'%>
 <%@ page session="false" %>
<%
String username=request.getParameter("uid");
 String password=request.getParameter("pwd");
 Utils.setRequestCharacterEncoding(request);
WebAppsContext wctx = null;
 boolean alreadySet = false;
Connection conn = null;
 if (Utils.isAppsContextAvailable()) {
 wctx = Utils.getAppsContext();
 alreadySet = true;
 } else {
 wctx = Utils.getAppsContext();
 }
 request = SecureHttpRequest.check(request,wctx);
 String requestUrl = request.getParameter("requestUrl");
 out.println("requestUrl="+requestUrl);
 try {
 String params;
 StringBuffer tmp = new StringBuffer();
 tmp.append("requestUrl=");
 if( requestUrl != null && !requestUrl.equals(""))
 tmp.append(URLEncoder.encode(requestUrl,SessionMgr.getCharSet()));
Enumeration paramNames = request.getParameterNames();
 while (paramNames != null && paramNames.hasMoreElements()) {
 String name = (String) paramNames.nextElement();
 out.println("name="+name);
 if (!(name.equals("requestUrl")))
 {
 String value = request.getParameter(name);
 out.println("value="+value);
 tmp.append("&");
 // Restoring original encoding
 tmp.append(oracle.apps.fnd.util.URLEncoder.encode(name,SessionMgr.getCharSet()));
 tmp.append("=");
 tmp.append(oracle.apps.fnd.util.URLEncoder.encode(value,SessionMgr.getCharSet()));
 }
 }
conn = Utils.getConnection();
 boolean getIcxLang = false;
 String langCode = request.getParameter("langCode");
 out.println("langCode="+langCode);
 String sessionLang = null;
 if ( langCode != null)
 {
 // This is from language selection bean
 if (SessionMgr.isInstalledLanguage(langCode))
 {
 sessionLang = langCode;
 Utils.writeToLog("sso/html", "Language: "+langCode+" is installed", wctx);
 }
 else
 {
 getIcxLang = true;
 Utils.writeToLog("sso/html", "Language: "+langCode+" is not installed in apps", wctx);
 }
}
 else
 {
 // try getting language from browser
 Utils.writeToLog("sso/html", "trying to get browser's Language", wctx);
 String browserLanguages = request.getHeader("Accept-Language");
 out.println("browserLanguages="+browserLanguages);
 Utils.writeToLog("sso/html", "Browser Language:"+browserLanguages, wctx);
 sessionLang = LoginPage.getAppsLangFromBrowser(browserLanguages, wctx);
 getIcxLang = (sessionLang == null || sessionLang.equals(""));
 }
 String cval = SessionMgr.getAppsCookie(request);
 out.println("cval="+cval);
 String pNlsLanguage = null;
 if(cval!= null && !cval.equals("-1") && !cval.equals("") )
 {
 Utils.writeToLog("sso/html", "Session exists:: "+cval+" setting lang :: "+langCode, wctx);
 LangInfo info = wctx.getLangInfo(sessionLang , null, conn);
 pNlsLanguage = info.getNLSLanguage();
 out.println("pNlsLanguage="+pNlsLanguage);
 wctx.validateSession(cval);
 boolean check = wctx.setLanguageContext(pNlsLanguage, null, null, null, null, null, null);
 out.println("check="+check);
 } else {
 SessionMgr.createGuestSession(request, response, false, sessionLang);
 }
String returnUrl = SSOUtil.getLocalLoginRFUrl(tmp.toString());
 out.println("returnUrl="+returnUrl);
 //response.sendRedirect(returnUrl);
 //if(username==null)
 String customUrl = "/AuthenticateUser?username="+username+"&password="+password;
 response.setHeader("Cache-Control", "no-cache");
 response.setHeader("Pragma", "no-cache");
 response.setDateHeader("Expires", 0);
 try {
 %>
 <jsp:forward page="<%=customUrl%>" />
 <%
 } catch(Exception e) {%>
 <b>Error occured : <%= e.getMessage()%></b>
 <%= e%>
 <%
 }
 }
 catch(Exception e)
 {
 Utils.writeToLog("sso/html", "Exception occurred"+e.toString(), wctx);
 throw new Exception(e.toString());
 }
 finally {
 if (alreadySet == false) {
 Utils.releaseAppsContext();
 }
 }
 %>

So, after this change user will enter credentials in theA�DummyLogin.jsp and upon successful validation of the credentials, it will take user to the Oracle Apps Main Home Page. Here is the screenshots attached:

Login_Page_using_JSP

Now once user enters the credentials, having validated successfully user will be able to see the following Oracle Apps Main Home Page:

I hope this article will help you in many aspects. If you have got any other better opinion, please put your valuable comment.

Leave a Reply

Your email address will not be published. Required fields are marked *

Show my latest post here