CDCClientServlet.java revision 260c0e92fa817a5012f1546a7905a98fdfea43fa
/**
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2005 Sun Microsystems Inc. All Rights Reserved
*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the License). You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* See the License for the specific language governing
* permission and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* Header Notice in each file and include the License file
* at opensso/legal/CDDLv1.0.txt.
* If applicable, add the following below the CDDL Header,
* with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* $Id: CDCClientServlet.java,v 1.6 2009/01/12 18:57:12 madan_ranganath Exp $
*
* Portions Copyrighted 2010-2014 ForgeRock AS.
*/
/**
* The <code>CDCClientServlet</code> is the heart of the Cross Domain Single Signon mechanism of OpenAM in the DMZ
* along with the distributed auth.
* <br/>
* The following is the algorithm used by the program:
* <ol>
* <li>If request does not contain SSO related cookie or policy has generated some advices then redirect request to
* the distributed auth service.</li>
* <li>If request contains SSO related cookie and no advices.</li>
* <ul>
* <li>Tunnel the Request to OpenAM.</li>
* <li>Send the received AuthNResponse as Form POST to the original request requested using the goto parameter in
* the query string.</li>
* </ul>
* </ol>
*/
public class CDCClientServlet extends HttpServlet {
private static final char QUESTION_MARK = '?';
private static final char AMPERSAND = '&';
private static final char EQUAL_TO = '=';
private static final char SEMI_COLON = ';';
private static final char SPACE = ' ';
private static String cdcAuthURI;
private static final String RESPONSE_HEADER_ALERT =
"X-DSAME-Assertion-Form";
private static final String RESPONSE_HEADER_ALERT_VALUE =
"true";
static {
initConfig();
}
private static SSOTokenManager tokenManager;
private static String authURLCookieName;
private static String authURLCookieDomain;
private static String deployDescriptor;
"false"))).booleanValue();
private static boolean cookieEncoding =
/**
* @param config the ServletConfig object that contains configutation
* information for this servlet.
* @exception ServletException if an exception occurs that interrupts
* the servlet's normal operation.
*/
if (debug.messageEnabled()) {
+"Initializing...");
}
try {
} catch (SSOException ssoe) {
ssoe);
}
}
/**
* Handles the HTTP GET request.
*
* @param request an HttpServletRequest object that contains the request
* the client has made of the servlet.
* @param response an HttpServletResponse object that contains the response
* the servlet sends to the client.
* @exception ServletException if an input or output error is detected when
* the servlet handles the GET request
* @exception IOException if the request for the GET could not be handled
*/
throws ServletException, IOException {
}
/**
* Handles the HTTP POST request.
*
* @param request an HttpServletRequest object that contains the request
* the client has made of the servlet.
* @param response an HttpServletResponse object that contains the response
* the servlet sends to the client.
* @exception ServletException if an input or output error is detected when
* the servlet handles the GET request
* @exception IOException if the request for the GET could not be handled
*/
{
}
/**
* The method redirects the user to the authentication module if he is not
* authenticated; else redirects him back to the original referrer.
*
* @param request an HttpServletRequest object that contains the request
* the client has made of the servlet.
* @param response an HttpServletResponse object that contains the response
* the servlet sends to the client.
* @exception ServletException if an input or output error is detected when
* the servlet handles the GET request
* @exception IOException if the request for the GET could not be handled
*/
if (debug.messageEnabled()) {
+ request.getQueryString());
}
if (targetParameter == null) {
}
// if check if goto ot target have invalid strings, to avoid
// accepting invalid injected javascript.
if (debug.messageEnabled()) {
+ " and target: " + targetParameter);
}
return;
}
return;
}
}
}
/* Steps to be done
* 1. If no SSOToken or policy advice present , forward to
* authentication.
* 2. If SSOToken is valid tunnel request to the backend AM's
* CDCServlet and Form POST the received response to the agent.
*/
// Check for a valid SSOToken in the request. If SSOToken is not found
// or if the token is invalid, redirect the user for authentication.
// Also re-direct if there are policy advices in the query string
// collect advices in parsedRequestParams[0] String and rest of params
// other than original goto url in parsedRequestParams[1] String.
// Redirect to authentication
} else {
// tunnel request to AM
// send the request to the CDCServlet of AM where the session
// was created.
}
}
/**
* This the main method of this servlet which takes in the request
* opens a URLConnection to the CDCServlet endpoint in the
* OpenAM, and tunnels the request content to it.
* It parses the Response received and if the HTTP_STATUS is "HTTP_OK"
* or "HTTP_MOVED_TEMP" POSTs the received Liberty Authn Response to the
* goto URL specified in the original request.
*/
throws ServletException, IOException
{
try {
} catch (SessionException se) {
+" OpenAM instance to forward to.", se);
"Cannot locate OpenAM instance to forward to");
}
if (sessionServiceURL == null) {
"Cannot locate OpenAM instance to forward to");
}
// replace "sessionservice" by cdcservlet in obtained URL
// we use naming so that we get the URL of the exact server
// where the session is located and get the right deployment
// descriptor.
// if any
// CDCServletURL
// save the go to URL of the agent side to ultimately
// POST to.
try {
connection.setDoOutput( true );
connection.setUseCaches( false );
// replay cookies
if (strCookies != null)
{ if (debug.messageEnabled()) {
+"cookies = " + strCookies);
}
}
// dont wish to follow redirect to agent, since
// the response needs to go via the CDCClientServlet.
HttpURLConnection.setFollowRedirects(false);
// Receiving input from CDCServlet on the AM server instance
if (debug.messageEnabled()) {
+"response back from "+CDCServletURL);
}
// Check response code
(connection.getResponseCode() ==
{
/**
* Read the response back from CDCServlet, got a redirect
* since this response contains the "LARES" ( Liberty
* authn response, which needs to be posted back to the
* dest url (agent).
*/
int len;
char[] buf = new char[1024];
}
if (debug.messageEnabled()) {
+"Received response data = " + inString);
}
// put the received Liberty Auth Response
// in the servlet's response.
} else {
+"code NOT OK/MOVED_TEMP ");
+ CDCServletURL);
}
} catch (ConnectException ce) {
// Debug the exception
if (debug.warningEnabled()) {
}
}
}
// Get cookies string from HTTP request object
// above call would return pure sid in iPlanetDirectoryPro cookie
// independent of container encoding
}
if (debug.messageEnabled()) {
+"Cookie name = " + cookieName);
+"Cookie val= "+ cookieVal);
}
cookieStr = new StringBuilder();
} else {
}
}
}
}
return strCookies;
}
/**
* Gathers the parameters in the request as a HTTP URL string.
* to form request parameters and policy advice String array.
* It collects all the parameters from the original request except
* the original goto url and any advice parameters.
* Note: All the paramters will be url decoded by default., we should
* make sure that these values are encoded again
*
* @param request an HttpServletRequest object that contains the request
* the client has made of the servlet.
* @return An String array, index 0 is policy advice, index 1 is rest of the
* request parameters
*/
if (adviceList == null) {
adviceList = new StringBuilder();
} else {
}
}
} else {
}
}
}
}
if (debug.messageEnabled()) {
+"Advice List is = " + adviceList);
}
if (adviceList == null) {
} else {
}
} else {
}
}
/**
* Redirects the HTTP request to the Authentication module.
* It gets the authentication url from <code>SystemProperties</code>.
* @param request an HttpServletRequest object that contains the request
* the client has made of the servlet.
* @param response an HttpServletResponse object that contains the response
* the servlet sends to the client.
* @exception IOException If an input or output exception occurs
*/
throws IOException {
if (debug.messageEnabled()) {
}
// Check if user has authenticated to another OpenAM
// instance
if (authCookie != null) {
if (debug.messageEnabled()) {
+"got an authenticated URL= " + authURL);
}
}
try {
policyAdviceList != null) {
}
if (debug.messageEnabled()) {
+"goto or target parameter is missing in the request.");
}
return;
}
// Construct the login URL
if (debug.messageEnabled()) {
+ loginURI);
}
} else {
cdcUri = cdcAuthURI;
}
if (debug.messageEnabled()) {
}
} else {
}
if (policyAdviceList != null) {
}
if (debug.messageEnabled()) {
+":redirectURL before dispatching is="+redirectURL);
}
} else {
// Redirect the user to the authenticated URL
//Reset the cookie value to null, to avoid continuous loop
// when a load balancer is used
if (authCookie != null) {
}
}
if (debug.messageEnabled()) {
+"Forwarding for authentication to= " + redirectURL);
}
} catch (IOException ex) {
+"in forwarding to Authentication service. IOException", ex);
+ex.getMessage());
} catch (ServletException se) {
"in forwarding to Authentication service. ServletException", se);
+se.getMessage());
} catch (IllegalStateException ie) {
+"in forwarding to Authentication service. Illegal state", ie);
+ie.getMessage());
}
}
/**
* Shows Application Error message to the user.
* @param response an HttpServletResponse object that contains the response
* the servlet sends to the client.
* @param msg Message to be displayed.
*/
throws IOException {
return;
}
try {
} catch (IOException e) {
+"message to the user " + e);
} finally {
try {
} catch (IOException ignore) {}
}
}
/**
* Returns the SSOToken of the user. If user has not authenticated
* re-directs the user to login page
*/
try {
/* SSOTokenManager.createSSOToken() throws an SSOException if the
* token is not valid, so for a invalid token manager.isValidToken()
* will never get executed for an invalid token.
*/
if (debug.messageEnabled()) {
+"either null or not valid: " + token +
"\nRedirecting for authentication");
}
}
if (debug.messageEnabled()) {
+"caught= " + e);
}
}
return (token);
}
if (debug.messageEnabled()) {
}
try{
if (debug.messageEnabled()) {
"AuthnResponse= " + authnResponse);
}
if (debug.messageEnabled()) {
"AuthnResponse showing 403 error page");
}
return;
}
if (debug.messageEnabled()) {
"ERROR: An application error has occured.");
}
return;
}
if (debug.messageEnabled()) {
+ "AuthnResponse sent successfully");
}
return;
} catch(IOException ioe){
}
}
/**
* Return <code>true</code> if the passed URI is valid compared to the valid set loaded during initialization.
*
* @param cdcUri The URI to test.
* @return <code>true</code> if the URI is considered valid, <code>false</code> otherwise.
*/
// We are only interested in the URI part up to any parameters that may be included.
if (questionMark != -1) {
}
// If there is not an exact match for the passed value then it cannot be considered valid
if (debug.messageEnabled()) {
}
return result;
}
private static void initConfig() {
if (INVALID_SET.isEmpty()) {
if (invalidStrings == null) {
} else {
if (debug.messageEnabled()) {
}
while (st.hasMoreTokens()) {
}
}
}
if (validLoginURIStrings == null) {
} else {
if (debug.messageEnabled()) {
}
while (st.hasMoreTokens()) {
}
}
}
}