blob: 2c6a06e53f4bb8dced4cc86bcf6c400390c0a1ff [file] [log] [blame]
// Copyright 2014 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.enterprise.adaptor.sharepoint;
import static org.junit.Assert.assertEquals;
import com.google.enterprise.adaptor.sharepoint.FormsAuthenticationHandlerTest.MockScheduledExecutor;
import com.google.enterprise.adaptor.sharepoint.SamlAuthenticationHandler.HttpPostClient;
import com.google.enterprise.adaptor.sharepoint.SamlAuthenticationHandler.PostResponseInfo;
import java.io.IOException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
public class AdfsHandshakeManagerTest {
@Rule
public ExpectedException thrown = ExpectedException.none();
private static class UnsupportedHttpPostClient implements HttpPostClient {
@Override
public SamlAuthenticationHandler.PostResponseInfo issuePostRequest(
URL url, Map<String, String> connectionProperties, String requestBody)
throws IOException {
throw new UnsupportedOperationException();
}
}
private static class MockHttpPostClient implements HttpPostClient {
private Map<URL, PostResponseInfo> responseMap;
private Map<URL, String> receivedRequestBodyMap;
public MockHttpPostClient() {
responseMap = new HashMap<URL, PostResponseInfo>();
receivedRequestBodyMap = new HashMap<URL, String>();
}
@Override
public SamlAuthenticationHandler.PostResponseInfo issuePostRequest(
URL url, Map<String, String> connectionProperties, String requestBody)
throws IOException {
if (!responseMap.containsKey(url)) {
throw new UnsupportedOperationException(
"Unexpected Http Post for URL " + url);
}
// log incoming request body
receivedRequestBodyMap.put(url, requestBody);
return responseMap.get(url);
}
}
@Test
public void testConstructor() {
new AdfsHandshakeManager.Builder(
"http://endpoint", "username", "password", "https://sts", "realm")
.build();
}
@Test
public void testNullUsername() {
thrown.expect(NullPointerException.class);
new AdfsHandshakeManager.Builder(
"http://endpoint", null, "password", "https://sts", "realm").build();
}
@Test
public void testNullPassword() {
thrown.expect(NullPointerException.class);
new AdfsHandshakeManager.Builder(
"http://endpoint", "username", null, "https://sts", "realm").build();
}
@Test
public void testNullEndpoint() {
thrown.expect(NullPointerException.class);
new AdfsHandshakeManager.Builder(
null, "username", "password","https://sts", "realm").build();
}
@Test
public void testNullSts() {
thrown.expect(NullPointerException.class);
new AdfsHandshakeManager.Builder(
"http://endpoint", "username", "password", null, "realm").build();
}
@Test
public void testNullRealm() {
thrown.expect(NullPointerException.class);
new AdfsHandshakeManager.Builder(
"http://endpoint", "username", "password", "http://sts", null).build();
}
@Test
public void testRequestToken() throws IOException{
MockHttpPostClient postClient = new MockHttpPostClient();
AdfsHandshakeManager manager = new AdfsHandshakeManager.Builder(
"https://sharepoint.intranet.com", "username@domain", "pass]]>word&123",
"https://sts.dmain.com/adfs/services/trust/2005/usernamemixed",
"urn:realm:sharepoint", postClient).build();
URL tokenRequest = new URL(
"https://sts.dmain.com/adfs/services/trust/2005/usernamemixed");
String tokenResponse = "<s:Envelope "
+ "xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\">"
+ "<s:Header>Some header</s:Header>"
+ "<t:RequestSecurityTokenResponse "
+ "xmlns:t=\"http://schemas.xmlsoap.org/ws/2005/02/trust\">"
+ "This is requested token"
+ "</t:RequestSecurityTokenResponse>"
+ "</s:Envelope>";
postClient.responseMap.put(tokenRequest,
new PostResponseInfo(tokenResponse, null));
assertEquals("<t:RequestSecurityTokenResponse "
+ "xmlns:t=\"http://schemas.xmlsoap.org/ws/2005/02/trust\">"
+ "This is requested token"
+ "</t:RequestSecurityTokenResponse>", manager.requestToken());
String expectedRequestBody
= "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
+ "<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" "
+ "xmlns:a=\"http://www.w3.org/2005/08/addressing\" "
+ "xmlns:u=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-"
+ "wssecurity-utility-1.0.xsd\"><s:Header><a:Action "
+ "s:mustUnderstand=\"1\">"
+ "http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</a:Action>"
+ "<a:ReplyTo><a:Address>http://www.w3.org/2005/08/addressing/anonymous"
+ "</a:Address></a:ReplyTo><a:To s:mustUnderstand=\"1\"><![CDATA["
+ "https://sts.dmain.com/adfs/services/trust/2005/usernamemixed]]>"
+ "</a:To><o:Security s:mustUnderstand=\"1\" "
+ "xmlns:o=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-"
+ "wssecurity-secext-1.0.xsd\"><o:UsernameToken>"
+ "<o:Username><![CDATA[username@domain]]></o:Username>"
+ "<o:Password><![CDATA[pass]]]]><![CDATA[>word&123]]>"
+ "</o:Password></o:UsernameToken></o:Security></s:Header>"
+ "<s:Body><t:RequestSecurityToken "
+ "xmlns:t=\"http://schemas.xmlsoap.org/ws/2005/02/trust\">"
+ "<wsp:AppliesTo "
+ "xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2004/09/policy\">"
+ "<a:EndpointReference><a:Address>"
+ "<![CDATA[urn:realm:sharepoint]]></a:Address>"
+ "</a:EndpointReference></wsp:AppliesTo><t:KeyType>"
+ "http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey"
+ "</t:KeyType><t:RequestType>"
+ "http://schemas.xmlsoap.org/ws/2005/02/trust/Issue"
+ "</t:RequestType><t:TokenType>urn:oasis:names:tc:SAML:1.0:assertion"
+ "</t:TokenType></t:RequestSecurityToken></s:Body></s:Envelope>";
assertEquals(expectedRequestBody,
postClient.receivedRequestBodyMap.get(tokenRequest));
}
@Test
public void testNullRequestToken() throws IOException{
MockHttpPostClient postClient = new MockHttpPostClient();
AdfsHandshakeManager manager = new AdfsHandshakeManager.Builder(
"https://sharepoint.intranet.com", "username@domain", "password&123",
"https://sts.dmain.com/adfs/services/trust/2005/usernamemixed",
"urn:realm:sharepoint", postClient).build();
URL tokenRequest = new URL(
"https://sts.dmain.com/adfs/services/trust/2005/usernamemixed");
postClient.responseMap.put(tokenRequest,
new PostResponseInfo("<data>some invalid content</data>", null));
thrown.expect(IOException.class);
String token = manager.requestToken();
}
@Test
public void testGetAuthenticationCookie() throws IOException{
MockHttpPostClient postClient = new MockHttpPostClient();
AdfsHandshakeManager manager = new AdfsHandshakeManager.Builder(
"https://sharepoint.intranet.com", "username@domain", "password&123",
"https://sts.dmain.com/adfs/services/trust/2005/usernamemixed",
"urn:realm:sharepoint", postClient).build();
URL submitToken = new URL("https://sharepoint.intranet.com/_trust");
Map<String, List<String>> responseHeaders
= new HashMap<String, List<String>>();
responseHeaders.put("some-header", Arrays.asList("some value"));
responseHeaders.put("Set-Cookie", Arrays.asList("FedAuth=AutheCookie"));
postClient.responseMap.put(submitToken,
new PostResponseInfo("submit token response", responseHeaders));
String cookie = manager.getAuthenticationCookie(
"<t:RequestSecurityTokenResponse "
+ "xmlns:t=\"http://schemas.xmlsoap.org/ws/2005/02/trust\">"
+ "This is requested token"
+ "</t:RequestSecurityTokenResponse>");
assertEquals("FedAuth=AutheCookie;", cookie);
String expectedSubmitTokenRequest = "wa=wsignin1.0&wctx="
+ URLEncoder.encode("https://sharepoint.intranet.com/_layouts/"
+ "Authenticate.aspx","UTF-8")
+ "&wresult=" + URLEncoder.encode("<t:RequestSecurityTokenResponse "
+ "xmlns:t=\"http://schemas.xmlsoap.org/ws/2005/02/trust\">"
+ "This is requested token"
+ "</t:RequestSecurityTokenResponse>", "UTF-8");
assertEquals(expectedSubmitTokenRequest,
postClient.receivedRequestBodyMap.get(submitToken));
}
@Test
public void testAuthenticateInSamlHandlerWithADFS() throws IOException{
MockHttpPostClient postClient = new MockHttpPostClient();
String username = "username@domain";
String password = "password&123";
AdfsHandshakeManager manager = new AdfsHandshakeManager.Builder(
"https://sharepoint.intranet.com", username, password,
"https://sts.dmain.com/adfs/services/trust/2005/usernamemixed",
"urn:realm:sharepoint", postClient).build();
URL tokenRequest = new URL(
"https://sts.dmain.com/adfs/services/trust/2005/usernamemixed");
String tokenResponse = "<s:Envelope "
+ "xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\">"
+ "<s:Header>Some header</s:Header>"
+ "<t:RequestSecurityTokenResponse "
+ "xmlns:t=\"http://schemas.xmlsoap.org/ws/2005/02/trust\">"
+ "This is requested token"
+ "</t:RequestSecurityTokenResponse>"
+ "</s:Envelope>";
postClient.responseMap.put(tokenRequest,
new PostResponseInfo(tokenResponse, null));
URL submitToken = new URL("https://sharepoint.intranet.com/_trust");
Map<String, List<String>> responseHeaders
= new HashMap<String, List<String>>();
responseHeaders.put("some-header", Arrays.asList("some value"));
responseHeaders.put("Set-Cookie", Arrays.asList("FedAuth=AutheCookie"));
postClient.responseMap.put(submitToken,
new PostResponseInfo(null, responseHeaders));
SamlAuthenticationHandler authenticationHandler
= new SamlAuthenticationHandler.Builder(username, password,
new MockScheduledExecutor(), manager).build();
AuthenticationResult result = authenticationHandler.authenticate();
assertEquals("FedAuth=AutheCookie;", result.getCookie());
assertEquals("NO_ERROR", result.getErrorCode());
assertEquals(600, result.getCookieTimeOut());
}
@Test
public void testEscapeCdata() {
AdfsHandshakeManager manager = new AdfsHandshakeManager.Builder(
"http://endpoint", "username", "password", "https://sts", "realm")
.build();
assertEquals("<![CDATA[This is simple]]>",
manager.escapeCdata("This is simple"));
assertEquals(
"<![CDATA[This is simple]]]]><![CDATA[>with additional text]]>",
manager.escapeCdata("This is simple]]>with additional text"));
assertEquals(
"<![CDATA[This is > & simple]]]]><![CDATA[>]]>",
manager.escapeCdata("This is > & simple]]>"));
assertEquals(
"<![CDATA[]]]]><![CDATA[>]]>",
manager.escapeCdata("]]>"));
assertEquals("<![CDATA[<![CDATA[This is simple]]]]><![CDATA[>]]>",
manager.escapeCdata("<![CDATA[This is simple]]>"));
assertEquals("<![CDATA[This is simple]]]]>"
+ "<![CDATA[>with multiple]]]]><![CDATA[>]]>",
manager.escapeCdata("This is simple]]>with multiple]]>"));
}
}