2 * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package edu.internet2.middleware.shibboleth.integration;
19 import java.io.FileNotFoundException;
20 import java.io.IOException;
21 import java.security.KeyStoreException;
22 import java.security.NoSuchAlgorithmException;
23 import java.security.cert.CertificateException;
24 import java.util.Date;
25 import java.util.Enumeration;
26 import java.util.Iterator;
29 import javax.naming.directory.Attributes;
30 import javax.naming.directory.BasicAttribute;
31 import javax.servlet.http.HttpServletRequest;
33 import junit.framework.TestCase;
35 import org.apache.commons.codec.binary.Base64;
36 import org.apache.log4j.Level;
37 import org.opensaml.SAMLException;
38 import org.opensaml.SAMLResponse;
40 import edu.internet2.middleware.shibboleth.idp.provider.ShibbolethV1SSOHandler;
41 import edu.internet2.middleware.shibboleth.resource.AuthenticationFilter;
42 import edu.internet2.middleware.shibboleth.resource.FilterUtil;
43 import edu.internet2.middleware.shibboleth.resource.FilterSupport.NewSessionData;
44 import edu.internet2.middleware.shibboleth.runner.MadSignertest;
45 import edu.internet2.middleware.shibboleth.runner.ShibbolethRunner;
46 import edu.internet2.middleware.shibboleth.runner.MadSignertest.MockIdp;
47 import edu.internet2.middleware.shibboleth.runner.ShibbolethRunner.IdpTestContext;
48 import edu.internet2.middleware.shibboleth.serviceprovider.AssertionConsumerServlet;
49 import edu.internet2.middleware.shibboleth.serviceprovider.ServiceProviderConfig;
50 import edu.internet2.middleware.shibboleth.serviceprovider.ServiceProviderContext;
51 import edu.internet2.middleware.shibboleth.serviceprovider.Session;
54 * A JUnit test case that exercises the IdP, SP, and Filter
55 * @author Howard Gilbert
57 public class FileAssertionTest extends TestCase {
59 // Create some constants, both as parameters and to test responses
60 private static final String GIVENNAME = "Bozo";
61 public static final String SURNAME = "Clown";
62 private static final String TITLE = "clown";
63 public static final String AFFILIATION = "member";
64 public static final String SP_ENTITY = "https://sp.example.org/shibboleth";
65 public static final String POST_SHIRE = "https://sp.example.org/shibboleth-sp/Shibboleth.sso/SAML/POST";
66 public static final String ARTIFACT_SHIRE = "https://sp.example.org/shibboleth-sp/Shibboleth.sso/SAML/Artifact";
67 public static final String TARGET = "https://nonsense";
68 public static final String NETID = "BozoTClown";
69 public static final String APPLICATIONID = "default";
71 ShibbolethRunner runner;
72 ShibbolethRunner.SPTestContext consumer;
73 ShibbolethRunner.AuthenticationFilterContext filter;
74 private NewSessionData newSessionData = new NewSessionData();
75 ServiceProviderContext context;
76 ServiceProviderConfig config;
82 * <p>There is no IdP or SSO in this test. The IdP function
83 * is performed from assertion files.</p>
85 protected void setUp() throws Exception {
88 // Static call to set Log4J appenders and levels
89 ShibbolethRunner.loglevel = Level.DEBUG;
90 ShibbolethRunner.setupLogging();
92 // Create the overall testing framework
93 runner = new ShibbolethRunner();
96 // Initialize the SP with the default config file.
97 runner.setSpConfigFileName("/basicSpHome/spconfig.xml");
99 // Use one of two forms to initialize the SP
100 // Only calling AssertionConsumerServlet.createSessionFromData
101 //runner.initializeSP();
102 // Using either MockRunner or direct call to SP
103 consumer = ShibbolethRunner.consumer = runner.new SPTestContext();
105 context=ServiceProviderContext.getInstance();
106 config = context.getServiceProviderConfig();
108 // Initialize the Filter and create its separate
109 // Mockrunner simulated context.
110 filter= runner.getFilter();
111 // Note: If you are going to change the Filter init-param
112 // values, do it here before calling setUp()
115 newSessionData.applicationId=APPLICATIONID;
116 newSessionData.providerId=SP_ENTITY;
121 * Test the Post Profile, Attribute Push from an XML Assertion file.
123 * <p>Read an AttributePush assertion in from a file, resign it.
124 * Call AssertionConsumerServlet directly, then Run Filter</p>
126 public void testFileAttributePush() throws Exception {
128 // Setup a signer with the Example.org keystore
129 MadSignertest signer = new MadSignertest("src/conf/idp-example.jks","exampleorg");
131 // Read in and resign a test SAML Response file.
132 SAMLResponse samlresponse =
133 signer.signResponseFile("data/AttributePushAssertion.xml",
136 // Now feed the SAMLResponse into the AssertionConsumer
137 String bin64assertion = new String(samlresponse.toBase64());
138 newSessionData.SAMLResponse = bin64assertion;
140 // End of the Assertion-File part of the test, the rest is
141 // the same as with a real SSO.
143 newSessionData.target=TARGET;
144 newSessionData.handlerURL=POST_SHIRE;
146 // Create the session, extract pushed Attributes
147 String sessionId = AssertionConsumerServlet.createSessionFromData(newSessionData);
149 // Now get what was created in case you want to test it.
150 Session session = context.getSessionManager().findSession(sessionId, APPLICATIONID);
151 checkSession(session);
153 // Pass the SessionId to the Filter, let it fetch the attributes
154 filter.resetRequest("test.txt");
155 filter.testModule.addRequestParameter(AuthenticationFilter.SESSIONPARM, sessionId);
156 filter.request.setMethod("GET");
157 filter.testModule.doFilter();
163 * Verify correct operation of Filter and wrapped Request object,
164 * including attributes and headers.
166 private void checkFilter() {
167 // Get the Request Wrapper object created by the Filter
168 HttpServletRequest filteredRequest =
169 (HttpServletRequest) filter.testModule.getFilteredRequest();
171 assertEquals(NETID,filteredRequest.getRemoteUser());
172 assertEquals(NETID,filteredRequest.getHeader("REMOTE_USER"));
173 assertEquals(SURNAME,filteredRequest.getHeader("Shib-Person-surname"));
174 assertEquals(GIVENNAME,filteredRequest.getHeader("Shib-InetOrgPerson-givenName"));
175 assertEquals(TITLE,filteredRequest.getHeader("Shib-OrgPerson-title"));
177 Map attributes = (Map) filteredRequest.getAttribute(AuthenticationFilter.SHIB_ATTRIBUTES_PREFIX);
178 Iterator iterator = attributes.entrySet().iterator();
179 while (iterator.hasNext()) {
180 Map.Entry entry = (Map.Entry) iterator.next();
181 String key = (String) entry.getKey();
182 String value = (String) entry.getValue();
183 System.out.println(key+" : "+value);
187 Enumeration headerNames = filteredRequest.getHeaderNames();
188 while (headerNames.hasMoreElements()) {
189 String name = (String) headerNames.nextElement();
190 String value = (String) filteredRequest.getHeader(name);
191 System.out.println(name+ " : "+value );
196 * Add Session object checking here.
198 private void checkSession(Session session) {
199 assertNotNull(session);
200 assertEquals(APPLICATIONID,session.getApplicationId());
204 * Test Attribute Push using a Mock Idp
206 public void testMockIdp() throws SAMLException, KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException {
209 // Setup a signer with the Example.org keystore
210 MadSignertest signer = new MadSignertest("src/conf/idp-example.jks","exampleorg");
212 // Now create a MockIdp from it
213 MockIdp mockIdp = signer.new MockIdp();
215 // Tell the MockIdP how to respond to an SSO
216 mockIdp.ssoResponseFile = "data/AttributePushAssertion.xml";
218 // Create an IdpTestContext using this MockIdp
219 IdpTestContext idp = runner.new IdpTestContext(mockIdp);
221 // Set the URL suffix that triggers SSO processing
222 idp.resetRequest("SSO");
224 // Add the WAYF/RM parameters
225 idp.testModule.addRequestParameter("target", TARGET);
226 idp.testModule.addRequestParameter("shire",POST_SHIRE);
227 idp.testModule.addRequestParameter("providerId", SP_ENTITY);
229 // Add a userid, as if provided by Basic Authentication or a Filter
230 idp.request.setRemoteUser(NETID);
232 // Force Attribute Push
233 ShibbolethV1SSOHandler.pushAttributeDefault=true;
236 idp.testModule.doGet();
238 String bin64assertion = (String) idp.request.getAttribute("assertion");
239 String assertion = new String(Base64.decodeBase64(bin64assertion.getBytes()));
240 String handlerURL = (String) idp.request.getAttribute("shire");
241 String targetURL = (String) idp.request.getAttribute("target");
243 // Create the session directly without MockRunner
244 FilterUtil.sessionDataFromRequest(newSessionData,idp.request);
245 // there was no real redirect, so the next two fields are not
246 // in the places that sessionDataFromRequest expects.
247 newSessionData.SAMLResponse = bin64assertion;
248 newSessionData.target=targetURL;
249 newSessionData.handlerURL=handlerURL;
251 // Create the session, extract pushed Attributes
252 String sessionId = AssertionConsumerServlet.createSessionFromData(newSessionData);
254 // Now get what was created in case you want to test it.
255 Session session = context.getSessionManager().findSession(sessionId, APPLICATIONID);
256 checkSession(session);
258 // Pass the SessionId to the Filter, let it fetch the attributes
259 filter.resetRequest("test.txt");
260 filter.testModule.addRequestParameter(AuthenticationFilter.SESSIONPARM, sessionId);
261 filter.request.setMethod("GET");
262 filter.testModule.doFilter();