001/** 002 * Copyright 2005-2015 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 */ 016package org.kuali.rice.kim.client.acegi; 017 018import java.io.StringReader; 019 020import javax.xml.parsers.DocumentBuilder; 021import javax.xml.parsers.DocumentBuilderFactory; 022 023import org.acegisecurity.AuthenticationServiceException; 024import org.acegisecurity.BadCredentialsException; 025import org.acegisecurity.providers.cas.TicketResponse; 026import org.acegisecurity.providers.cas.ticketvalidator.CasProxyTicketValidator; 027import org.apache.commons.logging.Log; 028import org.apache.commons.logging.LogFactory; 029import org.kuali.rice.kim.sesn.DistributedSession; 030import org.w3c.dom.Document; 031import org.w3c.dom.Element; 032import org.w3c.dom.NodeList; 033import org.xml.sax.InputSource; 034 035import 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 */ 046public 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}