Coverage Report - org.kuali.student.security.filter.ProxyTicketRetrieverFilterSTS
 
Classes in this File Line Coverage Branch Coverage Complexity
ProxyTicketRetrieverFilterSTS
0%
0/100
0%
0/28
2.818
 
 1  
 /**
 2  
  * Copyright 2010 The Kuali Foundation Licensed under the
 3  
  * Educational Community License, Version 2.0 (the "License"); you may
 4  
  * not use this file except in compliance with the License. You may
 5  
  * obtain a copy of the License at
 6  
  *
 7  
  * http://www.osedu.org/licenses/ECL-2.0
 8  
  *
 9  
  * Unless required by applicable law or agreed to in writing,
 10  
  * software distributed under the License is distributed on an "AS IS"
 11  
  * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 12  
  * or implied. See the License for the specific language governing
 13  
  * permissions and limitations under the License.
 14  
  */
 15  
 
 16  
 package org.kuali.student.security.filter;
 17  
 
 18  
 import java.io.ByteArrayInputStream;
 19  
 import java.io.IOException;
 20  
 import java.io.StringWriter;
 21  
 import java.util.List;
 22  
 
 23  
 import javax.servlet.FilterChain;
 24  
 import javax.servlet.ServletException;
 25  
 import javax.servlet.http.HttpServletRequest;
 26  
 import javax.servlet.http.HttpServletResponse;
 27  
 import javax.xml.bind.JAXBElement;
 28  
 import javax.xml.parsers.DocumentBuilder;
 29  
 import javax.xml.parsers.DocumentBuilderFactory;
 30  
 import javax.xml.transform.Transformer;
 31  
 import javax.xml.transform.TransformerFactory;
 32  
 import javax.xml.transform.dom.DOMSource;
 33  
 import javax.xml.transform.stream.StreamResult;
 34  
 
 35  
 import org.apache.xpath.XPathAPI;
 36  
 import org.jasig.cas.client.validation.Assertion;
 37  
 import org.kuali.student.security.exceptions.KSSecurityException;
 38  
 import org.kuali.student.security.trust.dto.RequestSecurityTokenResponseType;
 39  
 import org.kuali.student.security.trust.dto.RequestSecurityTokenType;
 40  
 import org.kuali.student.security.trust.dto.RequestedSecurityTokenType;
 41  
 import org.kuali.student.security.trust.service.SecurityTokenService;
 42  
 import org.kuali.student.security.trust.service.SecurityTokenServiceImpl;
 43  
 import org.kuali.student.security.util.SamlUtils;
 44  
 import org.opensaml.SAMLAssertion;
 45  
 import org.springframework.security.context.SecurityContextHolder;
 46  
 import org.springframework.security.providers.cas.CasAuthenticationToken;
 47  
 import org.springframework.security.ui.FilterChainOrder;
 48  
 import org.springframework.security.ui.SpringSecurityFilter;
 49  
 import org.w3c.dom.Document;
 50  
 import org.w3c.dom.Element;
 51  
 import org.w3c.dom.NodeList;
 52  
 
 53  0
 public class ProxyTicketRetrieverFilterSTS extends SpringSecurityFilter {
 54  
     
 55  0
     private String proxyTargetService = null;
 56  
     private SecurityTokenService stsClient;
 57  0
     private boolean useCasProxyMechanism = false;
 58  
     
 59  
     @Override
 60  
     public void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException {
 61  
 
 62  0
         CasAuthenticationToken cat = (CasAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
 63  
         
 64  0
         if(cat != null && !isSAMLInSecurityContext()){
 65  
             // This is not a SAML Assertion. It is CAS specific way to hold information about the authenticated user.
 66  
             // The information is returned from the CAS server as a response to a validation request.
 67  0
             Assertion casAssertion = null;
 68  0
             String proxyTicket = null;
 69  0
             String principal = null;
 70  
             
 71  0
             System.out.println("ProxyTicketRetrieverFilter STS : inside if");
 72  0
             casAssertion = cat.getAssertion();
 73  0
             if(casAssertion != null){
 74  0
                 System.out.println("ProxyTicketRetrieverFilter STS : casAssertion is not null");
 75  0
                 if(useCasProxyMechanism){
 76  0
                     proxyTicket = casAssertion.getPrincipal().getProxyTicketFor(proxyTargetService);
 77  
                 } else {
 78  0
                     principal = casAssertion.getPrincipal().getName();
 79  
                 }
 80  
             }
 81  
             
 82  0
             Document signedSAMLDoc = null;
 83  0
             SAMLAssertion samlAssertion = null;
 84  0
             RequestSecurityTokenResponseType rstr = null;
 85  0
             Element signedSAMLRet = null;
 86  
             
 87  
             try{
 88  0
                 System.out.println("ProxyTicketRetrieverFilter STS : Proxy Ticket Returned from CAS " + proxyTicket);
 89  0
                 if(useCasProxyMechanism){
 90  0
                     RequestSecurityTokenType rst = prepareSecurityToken(proxyTicket, proxyTargetService);
 91  0
                     rstr = stsClient.requestSecurityToken(rst);
 92  
                 } else {
 93  
                     //signedSAMLRet = samlIssuerService.getSamlPrincipal(principal);
 94  
                 }
 95  
                 
 96  0
                 String tokenTypeUri = null;
 97  0
                 List<Object> objects = rstr.getAny();
 98  
                 
 99  0
                 for(Object o : objects){
 100  
                     // if its being accessed as a SOAP service with JAXB.
 101  0
                     if(o instanceof JAXBElement){
 102  0
                         JAXBElement<?> e = (JAXBElement<?>)o;
 103  0
                         if( e.getName().getLocalPart().equalsIgnoreCase("TokenType")){
 104  0
                             tokenTypeUri = (String)e.getValue();
 105  
                         }
 106  0
                         else if(e.getName().getLocalPart().equalsIgnoreCase("RequestedSecurityToken")) {
 107  0
                             RequestedSecurityTokenType requestedToken = (RequestedSecurityTokenType)e.getValue();
 108  0
                             signedSAMLRet = (Element)requestedToken.getAny();
 109  
                         }
 110  
                     
 111  
                     // if its being accessed with a client impl, no SOAP.
 112  0
                     } else if(o instanceof Element){
 113  0
                         Element e = (Element)o;
 114  0
                         if( e.getLocalName().equalsIgnoreCase("TokenType")){
 115  0
                             tokenTypeUri = e.getTextContent();
 116  
                         }
 117  0
                         else if(e.getLocalName().equalsIgnoreCase("RequestedSecurityToken")) {
 118  0
                             signedSAMLRet = (Element)e.getFirstChild();
 119  
                         }
 120  0
                     }
 121  
                 }
 122  
                 
 123  
                 
 124  
                 // transform the saml DOM into a writer
 125  0
                 if(tokenTypeUri.equals(SecurityTokenServiceImpl.SAML_11_NS)){
 126  0
                     DOMSource domSource = new DOMSource(signedSAMLRet);
 127  0
                     StringWriter writer = new StringWriter();
 128  0
                     StreamResult result = new StreamResult(writer);
 129  
                     
 130  0
                     TransformerFactory tf = TransformerFactory.newInstance();
 131  
                     Transformer transformer;
 132  
                     
 133  0
                     transformer = tf.newTransformer();
 134  0
                     transformer.transform(domSource, result);
 135  
                     
 136  0
                     writer.flush();
 137  
                     //System.out.println(writer.toString());
 138  
                     
 139  
                     // now build a new document before unsigning.
 140  
                     // I know this is nasty but is the only way it works. 
 141  
                     // Could not get it to work by just passing the signedSAMLRet
 142  0
                     DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 143  0
                     dbf.setNamespaceAware(true);
 144  
                     
 145  0
                     DocumentBuilder db = dbf.newDocumentBuilder();
 146  0
                     ByteArrayInputStream bais = new ByteArrayInputStream(writer.toString().getBytes());
 147  
                  
 148  0
                     signedSAMLDoc = db.parse(bais);
 149  0
                     samlAssertion = SamlUtils.unsignAssertion(signedSAMLDoc);
 150  0
                 } else {
 151  0
                     throw new ServletException("Security token not supported : " + tokenTypeUri);
 152  
                 }
 153  
                 
 154  
                  
 155  0
              } catch(Exception e){
 156  0
                  throw new ServletException(e);
 157  0
              }
 158  
              
 159  
              // place saml in security context
 160  0
              cat.setDetails(samlAssertion);
 161  
         }
 162  0
         filterChain.doFilter(request, response);
 163  0
     }
 164  
     
 165  
     private boolean isSAMLInSecurityContext(){
 166  0
         CasAuthenticationToken cat = (CasAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
 167  0
         if(cat.getDetails() instanceof SAMLAssertion){
 168  0
             return true;
 169  
         }
 170  0
         return false;
 171  
     }
 172  
 
 173  
     private RequestSecurityTokenType prepareSecurityToken(String proxyTicket, String proxyTargetService) throws KSSecurityException {
 174  0
         RequestSecurityTokenType rst = new RequestSecurityTokenType();
 175  0
         rst.setContext("Optional URI specifies this request identifier");
 176  
         
 177  
         // "TokenType"
 178  0
         Element tokenType = createElement("TokenType");
 179  0
         tokenType.setTextContent("urn:oasis:names:tc:SAML:1.0:assertion");
 180  0
         rst.getAny().add(tokenType);
 181  
         
 182  
         // "RequestType"
 183  0
         Element requestType = createElement("RequestType");
 184  0
         requestType.setTextContent("/Issue");
 185  0
         rst.getAny().add(requestType);
 186  
         
 187  
         // "CasProxyTicket"
 188  0
         Element casProxyTicket = createElement("CasProxyTicket");
 189  0
         casProxyTicket.setTextContent(proxyTicket);
 190  0
         rst.getAny().add(casProxyTicket);
 191  
         
 192  
         // "CasProxyTargetService"
 193  0
         Element casProxyTargetService = createElement("CasProxyTargetService");
 194  0
         casProxyTargetService.setTextContent(proxyTargetService);
 195  0
         rst.getAny().add(casProxyTargetService);
 196  
         
 197  0
         return rst;
 198  
     }
 199  
     
 200  
     private Element createElement(String tagName) throws KSSecurityException{
 201  
         
 202  0
         Element element = null;
 203  
         try{
 204  0
             DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
 205  
     
 206  0
             DocumentBuilder db = dbf.newDocumentBuilder();
 207  0
             Document doc = db.newDocument();
 208  
     
 209  0
             element = doc.createElementNS("http://schemas.xmlsoap.org/ws/2005/02/trust", tagName);
 210  
             
 211  0
         } catch(Exception e){
 212  0
             throw new KSSecurityException(e);
 213  0
         }
 214  0
         return element;
 215  
     }
 216  
     
 217  
     @Override
 218  
     public int getOrder() {
 219  0
         return FilterChainOrder.CAS_PROCESSING_FILTER + 2;
 220  
     }
 221  
 
 222  
     public String getProxyTargetService() {
 223  0
         return proxyTargetService;
 224  
     }
 225  
 
 226  
     public void setProxyTargetService(String proxyTargetService) {
 227  0
         this.proxyTargetService = proxyTargetService;
 228  0
     }
 229  
 
 230  
     public SecurityTokenService getSecurityTokenService() {
 231  0
         return stsClient;
 232  
     }
 233  
 
 234  
     public void setSecurityTokenService(SecurityTokenService stsClient) {
 235  0
         this.stsClient = stsClient;
 236  0
     }
 237  
 
 238  
     public boolean getUseCasProxyMechanism() {
 239  0
         return useCasProxyMechanism;
 240  
     }
 241  
 
 242  
     public void setUseCasProxyMechanism(boolean useCasProxyMechanism) {
 243  0
         this.useCasProxyMechanism = useCasProxyMechanism;
 244  0
     }
 245  
 
 246  
 }