Add Artifact test case.
[java-idp.git] / tests / edu / internet2 / middleware / shibboleth / integration / IntegrationTest.java
1 /*
2  * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 package edu.internet2.middleware.shibboleth.integration;
18
19 import java.io.UnsupportedEncodingException;
20 import java.net.URLDecoder;
21 import java.util.Enumeration;
22
23 import javax.naming.directory.Attributes;
24 import javax.naming.directory.BasicAttribute;
25 import javax.servlet.http.HttpServletRequest;
26 import javax.servlet.http.HttpServletResponse;
27
28 import junit.framework.TestCase;
29
30 import org.apache.commons.codec.binary.Base64;
31 import org.apache.log4j.Level;
32 import org.opensaml.SAMLException;
33
34 import com.mockrunner.mock.web.MockHttpServletResponse;
35
36 import edu.internet2.middleware.shibboleth.idp.provider.ShibbolethV1SSOHandler;
37 import edu.internet2.middleware.shibboleth.resource.FilterUtil;
38 import edu.internet2.middleware.shibboleth.resource.FilterSupport.NewSessionData;
39 import edu.internet2.middleware.shibboleth.runner.ShibbolethRunner;
40 import edu.internet2.middleware.shibboleth.serviceprovider.AssertionConsumerServlet;
41 import edu.internet2.middleware.shibboleth.serviceprovider.ServiceProviderContext;
42 import edu.internet2.middleware.shibboleth.serviceprovider.Session;
43 import edu.internet2.middleware.shibboleth.serviceprovider.SessionManager;
44
45 /**
46  * A JUnit test case that exercises the IdP, SP, and Filter
47  * @author Howard Gilbert
48  */
49 public class IntegrationTest extends TestCase {
50     
51     ShibbolethRunner runner;
52     ShibbolethRunner.IdpTestContext idp;
53     ShibbolethRunner.AuthenticationFilterContext filter;
54     
55     
56     
57     protected void setUp() throws Exception {
58         super.setUp();
59
60         // Static call to set Log4J appenders and levels
61         ShibbolethRunner.loglevel = Level.DEBUG;
62         ShibbolethRunner.setupLogging();
63         
64         // Create the overall testing framework
65         runner = new ShibbolethRunner();
66         
67         // Initialize the Idp, create the Mockrunner
68         // objects to do SSO, AA, and Artifact calls, and
69         // configure SAML to use the MockHTTPBindingProvider
70         runner.setIdpConfigFileName("/basicIdpHome/idpconfig.xml");
71         idp = runner.getIdp();
72         
73         // Initialize the SP with the default config file.
74         runner.setSpConfigFileName("/basicSpHome/spconfig.xml");
75         runner.initializeSP();
76         
77         // Initialize the Filter and create its separate
78         // Mockrunner simulated context. 
79         filter= runner.getFilter();
80             // Note: If you are going to change the Filter init-param
81             // values, do it here before calling setUp()
82         filter.setUp();
83         
84         // Create the static collection of Attributes that are 
85         // returned by the IdP for every principal.
86         // This could be done in each test, just as long as it
87         // is done before the SSO.
88         Attributes attributes = runner.getAttributesCollection();
89         attributes.put(new BasicAttribute("eduPersonAffiliation", "member"));
90         attributes.put(new BasicAttribute("eduPersonScopedAffiliation", "member"));
91         attributes.put(new BasicAttribute("title", "clown"));
92         attributes.put(new BasicAttribute("givenName", "bozo"));
93         attributes.put(new BasicAttribute("surname", "Clown"));
94     }
95     
96     
97     public void testAttributePush() throws SAMLException {
98         
99         // Set the URL suffix that triggers SSO processing
100         idp.setRequestUrls("SSO");
101         
102         // Add the WAYF/RM parameters
103         idp.testModule.addRequestParameter("target", "https://nonsense");
104         idp.testModule.addRequestParameter("shire","https://sp.example.org/Shibboleth.sso/SAML/POST");
105         idp.testModule.addRequestParameter("providerId", "https://sp.example.org/shibboleth");
106         
107         // Add a userid, as if provided by Basic Authentication or a Filter
108         idp.request.setRemoteUser("BozoTClown");
109         
110         // Force Attribute Push
111         ShibbolethV1SSOHandler.pushAttributeDefault=true;
112         
113         // Call the IdP 
114         idp.testModule.doGet();
115         
116             /*
117              * Sanity check: The IdP normally ends by transferring control to a
118              * JSP page that generates the FORM. However, we have not set up
119              * Mockrunner to perform the transfer, because the form would just
120              * create parsing work. Rather, the following code extracts the
121              * information from the request attributes that the JSP would have
122              * used as its source.
123              */
124         String bin64assertion = (String) idp.request.getAttribute("assertion");
125         String assertion = new String(Base64.decodeBase64(bin64assertion.getBytes()));
126         String handlerURL = (String) idp.request.getAttribute("shire");
127         String targetURL = (String) idp.request.getAttribute("target");
128         
129         
130         // Build the parameter for Session creation
131         NewSessionData data = new NewSessionData();
132         FilterUtil.sessionDataFromRequest(data,idp.request);
133             // there was no real redirect, so the next two fields are not
134             // in the places that sessionDataFromRequest expects.
135             data.SAMLResponse = bin64assertion;  
136             data.target=targetURL;
137         data.applicationId="default";
138         data.handlerURL=handlerURL;
139         data.providerId="https://sp.example.org/shibboleth";
140         
141         // Create the session, extract pushed Attributes 
142         String sessionId = AssertionConsumerServlet.createSessionFromData(data);
143         
144         // Now get what was created in case you want to test it.
145         ServiceProviderContext context   = ServiceProviderContext.getInstance();
146         Session session = context.getSessionManager().findSession(sessionId, "default");
147         
148         // Pass the SessionId to the Filter, let it fetch the attributes
149         filter.testModule.addRequestParameter("ShibbolethSessionId", sessionId);
150         filter.setRequestUrls("test.txt");
151         filter.testModule.doFilter();
152         
153             /*
154              * Sanity Check: doFilter runs just the Filter itself. On 
155              * input there was a Request and Response. When done, there
156              * will be a replacement Request object created by the Filter
157              * wrapping the original request and adding features.
158              */
159         
160         // Get the Request Wrapper object created by the Filter
161         HttpServletRequest filteredRequest = 
162             (HttpServletRequest) filter.testModule.getFilteredRequest();
163         
164         // Now do something that uses Filter supplied logic
165         Enumeration headerNames = filteredRequest.getHeaderNames();
166         while (headerNames.hasMoreElements()) {
167             String name = (String) headerNames.nextElement();
168             String value = (String) filteredRequest.getHeader(name);
169             System.out.println(name+ "-"+value );
170         }
171         
172         
173     }
174     
175     public void testAttributeQuery() throws SAMLException {
176         
177         // Set the URL suffix that triggers SSO processing
178         idp.setRequestUrls("SSO");
179         
180         // Add the WAYF/RM parameters
181         idp.testModule.addRequestParameter("target", "https://nonsense");
182         idp.testModule.addRequestParameter("shire","https://sp.example.org/Shibboleth.sso/SAML/POST");
183         idp.testModule.addRequestParameter("providerId", "https://sp.example.org/shibboleth");
184         
185         // Add a userid, as if provided by Basic Authentication or a Filter
186         idp.request.setRemoteUser("BozoTClown");
187         
188         // Block Attribute Push
189         ShibbolethV1SSOHandler.pushAttributeDefault=false;
190         
191         // Call the IdP 
192         idp.testModule.doGet();
193         
194         String bin64assertion = (String) idp.request.getAttribute("assertion");
195         String assertion = new String(Base64.decodeBase64(bin64assertion.getBytes()));
196         String handlerURL = (String) idp.request.getAttribute("shire");
197         String targetURL = (String) idp.request.getAttribute("target");
198         
199         
200         // Build the parameter for Session creation
201         NewSessionData data = new NewSessionData();
202         FilterUtil.sessionDataFromRequest(data,idp.request);
203         data.SAMLResponse = bin64assertion; // test logic 
204         data.target=targetURL;
205         data.applicationId="default";
206         data.handlerURL=handlerURL;
207         data.providerId="https://sp.example.org/shibboleth";
208         
209         // Create the Session
210         // Internally an AA Query will fetch the attributes through the 
211         // MockHTTPBindingProvider
212         String sessionId = AssertionConsumerServlet.createSessionFromData(data);
213         
214         
215         // Now get what was created in case you want to test it.
216         ServiceProviderContext context   = ServiceProviderContext.getInstance();
217         Session session = context.getSessionManager().findSession(sessionId, "default");
218         StringBuffer buffer = SessionManager.dumpAttributes(session);
219         System.out.println(buffer.toString());
220         
221         // Pass the SessionId to the Filter, let it fetch the attributes
222         filter.testModule.addRequestParameter("ShibbolethSessionId", sessionId);
223         filter.setRequestUrls("test.txt"); // need any URL
224         filter.testModule.doFilter();
225         
226         // Get the Request Wrapper object created by the Filter
227         HttpServletRequest filteredRequest = (HttpServletRequest) filter.testModule.getFilteredRequest();
228         
229         // Now do something that uses Filter supplied logic
230         Enumeration headerNames = filteredRequest.getHeaderNames();
231         while (headerNames.hasMoreElements()) {
232             String name = (String) headerNames.nextElement();
233             String value = (String) filteredRequest.getHeader(name);
234             System.out.println(name+ "-"+value );
235         }
236     }
237     
238     public void testArtifact() throws SAMLException, UnsupportedEncodingException {
239         
240         // Set the URL suffix that triggers SSO processing
241         idp.setRequestUrls("SSO");
242         
243         // Add the WAYF/RM parameters
244         idp.testModule.addRequestParameter("target", "https://nonsense");
245         idp.testModule.addRequestParameter("shire","https://sp.example.org/Shibboleth.sso/SAML/Artifact");
246         idp.testModule.addRequestParameter("providerId", "https://sp.example.org/shibboleth");
247         
248         // Add a userid, as if provided by Basic Authentication or a Filter
249         idp.request.setRemoteUser("BozoTClown");
250         
251         // Attribute Push is implied by Artifact
252         ShibbolethV1SSOHandler.pushAttributeDefault=false;
253         
254         // Call the IdP 
255         idp.testModule.doGet();
256         
257         MockHttpServletResponse response = idp.response;
258         String redirectURL = response.getHeader("Location");
259         
260         String[] splits = redirectURL.split("\\&SAMLart=");
261         assertTrue(splits.length>0);
262         String[] samlArt = new String[splits.length-1];
263         for (int i=0;i<samlArt.length;i++) {
264             samlArt[i]=URLDecoder.decode(splits[i+1],"UTF-8");
265         }
266         
267         
268         
269         // Build the parameter for Session creation
270         NewSessionData data = new NewSessionData();
271         FilterUtil.sessionDataFromRequest(data,idp.request);
272         data.SAMLArt=samlArt;
273         data.target="https://nonsense";
274         data.applicationId="default";
275         data.handlerURL="https://sp.example.org/Shibboleth.sso/SAML/Artifact";
276         data.providerId="https://sp.example.org/shibboleth";
277         
278         // Create the Session
279         // Internally an AA Query will fetch the attributes through the 
280         // MockHTTPBindingProvider
281         String sessionId = AssertionConsumerServlet.createSessionFromData(data);
282         
283         
284         // Now get what was created in case you want to test it.
285         ServiceProviderContext context   = ServiceProviderContext.getInstance();
286         Session session = context.getSessionManager().findSession(sessionId, "default");
287         StringBuffer buffer = SessionManager.dumpAttributes(session);
288         System.out.println(buffer.toString());
289         
290         // Pass the SessionId to the Filter, let it fetch the attributes
291         filter.testModule.addRequestParameter("ShibbolethSessionId", sessionId);
292         filter.setRequestUrls("test.txt"); // need any URL
293         filter.testModule.doFilter();
294         
295         // Get the Request Wrapper object created by the Filter
296         HttpServletRequest filteredRequest = (HttpServletRequest) filter.testModule.getFilteredRequest();
297         
298         // Now do something that uses Filter supplied logic
299         Enumeration headerNames = filteredRequest.getHeaderNames();
300         while (headerNames.hasMoreElements()) {
301             String name = (String) headerNames.nextElement();
302             String value = (String) filteredRequest.getHeader(name);
303             System.out.println(name+ "-"+value );
304         }
305     }
306     
307 }