/*
* JBoss, Home of Professional Open Source.
* Copyright 2006, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.test.web.security;
import java.net.HttpURLConnection;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.apache.commons.httpclient.Cookie;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpState;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.jboss.test.JBossTestCase;
import org.jboss.test.JBossTestSetup;
/**
* <p>
* JBAS-4804: Generic Header Based Authentication. This test case addresses the scenarios in which the
* <code>GenericHeaderAuthenticator</code> is configured in the <code>WEB-INF/context.xml</code> file of
* the web application. The <code>HttpHeaderForSSOAuth</code> and <code>SessionCookieForSSOAuth</code>
* properties are defined as attributes of the <code>GenericHeaderAuthenticator</code>, requiring no
* further configuration of the application server.
* </p>
* <p>
* The web application's <code>contex.xml</code> file should look like the following:
* <pre>
* <Context>
* <Valve className="org.jboss.web.tomcat.security.GenericHeaderAuthenticator"
* httpHeaderForSSOAuth="sm_ssoid,ct-remote-user,HTTP_OBLIX_UID"
* sessionCookieForSSOAuth="SMSESSION,CTSESSION,ObSSOCookie"/>
* </Context>
* </pre>
* </p>
*
* @author <a href="mailto:sguilhen@redhat.com">Stefan Guilhen</a>
* @since Oct 18, 2007
*/
public class GenericHeaderAuthUnitTestCase extends JBossTestCase
{
private String testAppBaseURL;
private String securedServletPath;
private HttpClient httpClient;
/**
* <p>
* Creates an instance of <code>GenericHeaderAuthUnitTestCase</code> with the specified name.
* </p>
*
* @param name the name of the test case.
*/
public GenericHeaderAuthUnitTestCase(String name)
{
super(name);
// this.testAppBaseURL = "http://" + super.getServerHost() + ":" + Integer.getInteger("web.port", 8080)
// + "/generic-header-auth/";
this.securedServletPath = "restricted/SecuredServlet";
this.httpClient = new HttpClient();
}
protected void setUp() throws Exception
{
super.setUp();
this.testAppBaseURL = "http://" + super.getServerHost() + ":" + Integer.getInteger("web.port", 8080)
+ "/generic-header-auth/";
}
/**
* <p>
* Check that, in the absence of headers, regular form authentication takes place.
* </p>
*
* @throws Exception if an error occurs when running the test.
*/
public void testRegularFormAuth() throws Exception
{
GetMethod getMethod = new GetMethod(this.testAppBaseURL + this.securedServletPath);
// execute a plain request to the SecureServlet
try
{
int responseCode = this.httpClient.executeMethod(getMethod);
String body = getMethod.getResponseBodyAsString();
// check the response code and assert the redirection to the login page
assertTrue("Unexpected response code received: " + responseCode, responseCode == HttpURLConnection.HTTP_OK);
assertTrue("Failed to redirect the request to the login page", body.indexOf("j_security_check") > 0);
}
finally
{
getMethod.releaseConnection();
}
HttpState state = this.httpClient.getState();
// fill in the login form and submit it
PostMethod postMethod = new PostMethod(this.testAppBaseURL + "j_security_check");
postMethod.addRequestHeader("Referer", this.testAppBaseURL + "restricted/login.html");
postMethod.addParameter("j_username", "jduke");
postMethod.addParameter("j_password", "theduke");
Header location = null;
try
{
int responseCode = this.httpClient.executeMethod(postMethod.getHostConfiguration(), postMethod, state);
log.debug("responseCode=" + responseCode + ", response=" + postMethod.getStatusText());
// check the response code received and the presence of a location header in the response
assertTrue("Unexpected response code received: " + responseCode,
responseCode == HttpURLConnection.HTTP_MOVED_TEMP);
location = postMethod.getResponseHeader("Location");
assertNotNull("Location header not found in response", location);
}
finally
{
postMethod.releaseConnection();
}
// follow the redirect as defined by the location header
String indexURI = location.getValue();
getMethod = new GetMethod(indexURI);
try
{
int responseCode = this.httpClient.executeMethod(getMethod.getHostConfiguration(), getMethod, state);
log.debug("responseCode=" + responseCode + ", response=" + getMethod.getStatusText());
// check the reponse code received
assertTrue("Unexpected response code received: " + responseCode, responseCode == HttpURLConnection.HTTP_OK);
String body = getMethod.getResponseBodyAsString();
// assert the redirection of to the SecureServlet
assertTrue("Redirect to SecureServlet has failed", body.indexOf("SecureServlet") > 0);
}
finally
{
getMethod.releaseConnection();
}
}
/**
* <p>
* Test usecases where the userid is sent via header and the session key is used as the password. To simplify
* testing, we pass a password as part of the session key. In reality, there needs to be a login module that can
* take the username and session key and validate.
* </p>
*
* @throws Exception if an error occurs when running the test.
*/
public void testGenericHeaderBaseAuth() throws Exception
{
String serverHost = super.getServerHost();
// Siteminder usecase
this
.performHeaderAuth("sm_ssoid", new Cookie(serverHost, "SMSESSION", "theduke", "/", null, false),
"SiteMinder");
// Cleartrust usecase
this.performHeaderAuth("ct-remote-user", new Cookie(serverHost, "CTSESSION", "theduke", "/", null, false),
"Cleartrust");
// Oblix usecase
this.performHeaderAuth("HTTP_OBLIX_UID", new Cookie(serverHost, "ObSSOCookie", "theduke", "/", null, false),
"Oblix");
}
/**
* <p>
* Invoke the <code>SecureServlet</code> setting the specified <code>headerId</code> and <code>cookie</code> objects
* in the request.
* </p>
*
* @param headerId a <code>String</code> representing the name of the request header that holds the user id.
* @param cookie a <code>Cookie</code> object containing the user's password.
* @param usecase a <code>String</code> representing the name of the use case being tested.
* @throws Exception if an error occurs when authenticating the user.
*/
private void performHeaderAuth(String headerId, Cookie cookie, String usecase) throws Exception
{
GetMethod method = new GetMethod(this.testAppBaseURL + this.securedServletPath);
// add the headerId and cookie objects to the request
method.addRequestHeader(headerId, "jduke");
this.httpClient.getState().addCookie(cookie);
// execute the request
try
{
int responseCode = this.httpClient.executeMethod(method);
// check the response code received
log.debug("Response from " + usecase + " case:" + method.getStatusText());
assertTrue("Unexpected response code received: " + responseCode, responseCode == HttpURLConnection.HTTP_OK);
// check that access to the secure servlet has been granted
String body = method.getResponseBodyAsString();
assertTrue("Access to SecureServlet has not been granted", body.indexOf("SecureServlet") > 0);
}
finally
{
// release the connection
method.releaseConnection();
}
}
public static Test suite() throws Exception
{
TestSuite suite = new TestSuite();
suite.addTest(new TestSuite(GenericHeaderAuthUnitTestCase.class));
// create an initializer for the test suite
Test wrapper = new JBossTestSetup(suite)
{
/**
* <p>
* Deploy the ear file containing the Servlets used by the tests.
* </p>
*
* @throws Exception if an error occurs when deploying the ear.
*/
protected void setUp() throws Exception
{
super.setUp();
super.deploy("generic-header-auth.ear");
// make sure the security cache is clear
super.flushAuthCache();
}
/**
* <p>
* Undeploy the ear file containing the Servlets used by the tests.
* </p>
*
* @throws Exception if an error occurs when undeploying the ear.
*/
protected void tearDown() throws Exception
{
super.undeploy("generic-header-auth.ear");
super.tearDown();
}
};
return wrapper;
}
}