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