001 /**
002 * Copyright 2005-2014 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.rice.kim.client.acegi;
017
018 import java.io.StringReader;
019
020 import javax.xml.parsers.DocumentBuilder;
021 import javax.xml.parsers.DocumentBuilderFactory;
022
023 import org.acegisecurity.AuthenticationServiceException;
024 import org.acegisecurity.BadCredentialsException;
025 import org.acegisecurity.providers.cas.TicketResponse;
026 import org.acegisecurity.providers.cas.ticketvalidator.CasProxyTicketValidator;
027 import org.apache.commons.logging.Log;
028 import org.apache.commons.logging.LogFactory;
029 import org.kuali.rice.kim.sesn.DistributedSession;
030 import org.w3c.dom.Document;
031 import org.w3c.dom.Element;
032 import org.w3c.dom.NodeList;
033 import org.xml.sax.InputSource;
034
035 import edu.yale.its.tp.cas.client.ProxyTicketValidator;
036
037
038 /**
039 * Uses CAS' <code>ProxyTicketValidator</code> to validate a service ticket.
040 * Creates the distributed session. Session principal is currently
041 * user@method.
042 *
043 * @author Kuali Rice Team (rice.collab@kuali.org)
044 *
045 */
046 public class KualiCasProxyTicketValidator extends CasProxyTicketValidator {
047 //~ Static fields/initializers =====================================================================================
048
049 private static final Log logger = LogFactory.getLog(KualiCasProxyTicketValidator.class);
050
051 private DistributedSession distributedSession;
052 //~ Instance fields ================================================================================================
053
054
055 /**
056 * This overridden method gets the authentication source and
057 * Distributed Session Ticket from the response
058 *
059 * @see org.acegisecurity.providers.cas.ticketvalidator.CasProxyTicketValidator#validateNow(edu.yale.its.tp.cas.client.ProxyTicketValidator)
060 */
061 protected TicketResponse validateNow(ProxyTicketValidator pv)
062 throws AuthenticationServiceException, BadCredentialsException {
063 String sAuthenticationSource = null;
064 String sDST = null;
065
066 try {
067 pv.validate();
068 } catch (Exception internalProxyTicketValidatorProblem) {
069 throw new AuthenticationServiceException(internalProxyTicketValidatorProblem.getMessage());
070 }
071
072 if (!pv.isAuthenticationSuccesful()) {
073 throw new BadCredentialsException(pv.getErrorCode() + ": " + pv.getErrorMessage());
074 }
075
076 logger.debug("PROXY RESPONSE: " + pv.getResponse());
077
078 if (logger.isDebugEnabled()) {
079 logger.debug("DEBUG");
080 }
081
082 try {
083 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
084 DocumentBuilder builder = factory.newDocumentBuilder();
085 InputSource inStream = new InputSource();
086 inStream.setCharacterStream(new StringReader(pv.getResponse()));
087 Document doc = builder.parse(inStream);
088 Element head = doc.getDocumentElement();
089 NodeList attrs = head.getElementsByTagName("cas:attribute");
090 for (int i=0; i<attrs.getLength(); i++) {
091 logger.debug(("Field name:" + ((Element)attrs.item(i)).getAttribute("name")) + "=" + ((Element)attrs.item(i)).getAttribute("value"));
092 if ( ((Element)attrs.item(i)).getAttribute("name").equals("authenticationMethod") ) {
093 sAuthenticationSource = ((Element)attrs.item(i)).getAttribute("value");
094 } else if ( ((Element)attrs.item(i)).getAttribute("name").equals("DST") ) {
095 sDST = ((Element)attrs.item(i)).getAttribute("value");
096 }
097 }
098 if (sAuthenticationSource != null && sDST != null) {
099 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 }