View Javadoc
1   /**
2    * Copyright 2005-2016 The Kuali Foundation
3    *
4    * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php
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  package org.kuali.rice.kim.client.acegi;
17  
18  import java.io.StringReader;
19  
20  import javax.xml.parsers.DocumentBuilder;
21  import javax.xml.parsers.DocumentBuilderFactory;
22  
23  import org.acegisecurity.AuthenticationServiceException;
24  import org.acegisecurity.BadCredentialsException;
25  import org.acegisecurity.providers.cas.TicketResponse;
26  import org.acegisecurity.providers.cas.ticketvalidator.CasProxyTicketValidator;
27  import org.apache.commons.logging.Log;
28  import org.apache.commons.logging.LogFactory;
29  import org.kuali.rice.kim.sesn.DistributedSession;
30  import org.w3c.dom.Document;
31  import org.w3c.dom.Element;
32  import org.w3c.dom.NodeList;
33  import org.xml.sax.InputSource;
34  
35  import edu.yale.its.tp.cas.client.ProxyTicketValidator;
36  
37  
38  /**
39   * Uses CAS' <code>ProxyTicketValidator</code> to validate a service ticket.  
40   * Creates the distributed session.  Session principal is currently 
41   * user@method.
42   *  
43   * @author Kuali Rice Team (rice.collab@kuali.org)
44   *
45   */
46  public class KualiCasProxyTicketValidator extends CasProxyTicketValidator {
47      //~ Static fields/initializers =====================================================================================
48  
49      private static final Log logger = LogFactory.getLog(KualiCasProxyTicketValidator.class);
50  
51      private DistributedSession distributedSession;
52      //~ Instance fields ================================================================================================
53  
54  
55      /**
56       * This overridden method gets the authentication source and 
57       * Distributed Session Ticket from the response
58       * 
59       * @see org.acegisecurity.providers.cas.ticketvalidator.CasProxyTicketValidator#validateNow(edu.yale.its.tp.cas.client.ProxyTicketValidator)
60       */
61      protected TicketResponse validateNow(ProxyTicketValidator pv)
62          throws AuthenticationServiceException, BadCredentialsException {
63  		String					sAuthenticationSource = null;
64  		String                  sDST = null;
65  
66          try {
67              pv.validate();
68          } catch (Exception internalProxyTicketValidatorProblem) {
69              throw new AuthenticationServiceException(internalProxyTicketValidatorProblem.getMessage());
70          }
71  
72          if (!pv.isAuthenticationSuccesful()) {
73              throw new BadCredentialsException(pv.getErrorCode() + ": " + pv.getErrorMessage());
74          }
75          
76          logger.debug("PROXY RESPONSE: " + pv.getResponse());
77          
78          if (logger.isDebugEnabled()) {
79              logger.debug("DEBUG");
80          }
81                  
82          try {
83  			DocumentBuilderFactory	factory = DocumentBuilderFactory.newInstance();
84  			DocumentBuilder			builder = factory.newDocumentBuilder();
85  			InputSource inStream = new InputSource();
86  			inStream.setCharacterStream(new StringReader(pv.getResponse()));
87  			Document				doc     = builder.parse(inStream);
88  			Element 				head = doc.getDocumentElement();
89  			NodeList 				attrs = head.getElementsByTagName("cas:attribute");
90  			for (int i=0; i<attrs.getLength(); i++) {
91  				logger.debug(("Field name:" + ((Element)attrs.item(i)).getAttribute("name")) + "=" + ((Element)attrs.item(i)).getAttribute("value"));
92  				if ( ((Element)attrs.item(i)).getAttribute("name").equals("authenticationMethod") ) {
93  					sAuthenticationSource = ((Element)attrs.item(i)).getAttribute("value");
94  				} else if ( ((Element)attrs.item(i)).getAttribute("name").equals("DST") ) {
95  				    sDST = ((Element)attrs.item(i)).getAttribute("value");
96  				}
97  			}
98  			if (sAuthenticationSource != null && sDST != null) {
99                  String sPrincipal = pv.getUser() + "@" + sAuthenticationSource;
100 
101                 if (logger.isDebugEnabled()) {
102 			        logger.debug("Updating session: " + sDST + " " + sPrincipal);
103 			    }
104 // Touching here may be overkill since it should happen in the filter
105                 distributedSession.touchSesn(sDST);
106               //  distributedSession.addPrincipalToSesn(sDST, sPrincipal);
107 			} else {
108 			    if (logger.isDebugEnabled()) {
109                     logger.debug("Incomplete data from CAS:" + sAuthenticationSource + ":" + sDST);
110                 }
111 			}
112         } catch (Exception e) {
113         	logger.error("Error parsing CAS Result", e);
114         }
115         
116         logger.debug("Authentication Method:" + sAuthenticationSource);
117         return new KualiTicketResponse(pv.getUser(), pv.getProxyList(), pv.getPgtIou(), sDST);
118     }
119 
120 
121     /**
122      * @param distributedSession the distributedSession to set
123      */
124     public void setDistributedSession(DistributedSession distributedSession) {
125         this.distributedSession = distributedSession;
126     }
127     
128 
129 }