/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at
* trunk/opends/resource/legal-notices/OpenDS.LICENSE
* or https://OpenDS.dev.java.net/OpenDS.LICENSE.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at
* trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
* add the following below this CDDL HEADER, with the fields enclosed
* by brackets "[]" replaced with your own identifying information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Copyright 2013 ForgeRock AS
*/
package org.opends.server.protocols.http;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
import static org.opends.server.protocols.http.CollectClientConnectionsFilter.*;
import java.io.IOException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.forgerock.json.resource.ResourceException;
import org.opends.server.DirectoryServerTestCase;
import org.opends.server.util.Base64;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
@SuppressWarnings("javadoc")
public class CollectClientConnectionsFilterTest extends DirectoryServerTestCase
{
private static final String USERNAME = "Aladdin";
private static final String PASSWORD = "open sesame";
private static final String BASE64_USERPASS = Base64
.encode((USERNAME + ":" + PASSWORD).getBytes());
private HTTPAuthenticationConfig authConfig = new HTTPAuthenticationConfig();
private CollectClientConnectionsFilter filter =
new CollectClientConnectionsFilter(null, authConfig);
@DataProvider(name = "Invalid HTTP basic auth strings")
public Object[][] getInvalidHttpBasicAuthStrings()
{
return new Object[][] { { null }, { "bla" },
{ "basic " + Base64.encode("la:bli:blu".getBytes()) } };
}
@Test(dataProvider = "Invalid HTTP basic auth strings")
public void parseUsernamePasswordFromInvalidAuthZHeader(String authZHeader)
throws Exception
{
assertThat(filter.parseUsernamePassword(authZHeader)).isNull();
}
@DataProvider(name = "Valid HTTP basic auth strings")
public Object[][] getValidHttpBasicAuthStrings()
{
return new Object[][] { { "basic " + BASE64_USERPASS },
{ "Basic " + BASE64_USERPASS } };
}
@Test(dataProvider = "Valid HTTP basic auth strings")
public void parseUsernamePasswordFromValidAuthZHeader(String authZHeader)
throws Exception
{
assertThat(filter.parseUsernamePassword(authZHeader)).containsExactly(
USERNAME, PASSWORD);
}
@Test
public void sendUnauthorizedResponseWithHttpBasicAuthWillChallengeUserAgent()
throws Exception
{
authConfig.setBasicAuthenticationSupported(true);
ServletOutputStream oStream = mock(ServletOutputStream.class);
HttpServletResponse response = mock(HttpServletResponse.class);
when(response.getOutputStream()).thenReturn(oStream);
sendUnauthorizedResponseWithHTTPBasicAuthChallenge(response);
verify(response).setStatus(HttpServletResponse.SC_UNAUTHORIZED);
verify(response).setHeader("WWW-Authenticate",
"Basic realm=\"org.forgerock.opendj\"");
verifyUnauthorizedOutputMessage(response, oStream);
}
@Test
public void sendUnauthorizedResponseWithoutHttpBasicAuthWillNotChallengeUserAgent()
throws Exception
{
authConfig.setBasicAuthenticationSupported(true);
HttpServletResponse response = mock(HttpServletResponse.class);
ServletOutputStream oStream = mock(ServletOutputStream.class);
when(response.getOutputStream()).thenReturn(oStream);
sendUnauthorizedResponseWithHTTPBasicAuthChallenge(response);
verify(response).setStatus(HttpServletResponse.SC_UNAUTHORIZED);
verifyUnauthorizedOutputMessage(response, oStream);
}
private void sendUnauthorizedResponseWithHTTPBasicAuthChallenge(
HttpServletResponse response)
{
filter.sendErrorReponse(response, true, ResourceException.getException(
HttpServletResponse.SC_UNAUTHORIZED, "Invalid Credentials"));
}
private void verifyUnauthorizedOutputMessage(HttpServletResponse response,
ServletOutputStream oStream) throws IOException
{
verify(response).getOutputStream();
verify(oStream).println(
"{\n" + " \"code\": 401,\n"
+ " \"message\": \"Invalid Credentials\",\n"
+ " \"reason\": \"Unauthorized\"\n" + "}");
}
@Test
public void extractUsernamePasswordHttpBasicAuthWillAcceptUserAgent()
throws Exception
{
authConfig.setBasicAuthenticationSupported(true);
HttpServletRequest request = mock(HttpServletRequest.class);
when(request.getHeader(HTTP_BASIC_AUTH_HEADER)).thenReturn(
"Basic " + BASE64_USERPASS);
assertThat(filter.extractUsernamePassword(request)).containsExactly(
USERNAME, PASSWORD);
}
@Test
public void extractUsernamePasswordCustomHeaders() throws Exception
{
final String customHeaderUsername = "X-OpenIDM-Username";
final String customHeaderPassword = "X-OpenIDM-Password";
authConfig.setCustomHeadersAuthenticationSupported(true);
authConfig.setCustomHeaderUsername(customHeaderUsername);
authConfig.setCustomHeaderPassword(customHeaderPassword);
HttpServletRequest request = mock(HttpServletRequest.class);
when(request.getHeader(customHeaderUsername)).thenReturn(USERNAME);
when(request.getHeader(customHeaderPassword)).thenReturn(PASSWORD);
assertThat(filter.extractUsernamePassword(request)).containsExactly(
USERNAME, PASSWORD);
}
}