001: /* Copyright 2006 The JA-SIG Collaborative. All rights reserved.
002: * See license distributed with this file and
003: * available online at http://www.uportal.org/license.html
004: */
005:
006: package org.jasig.portal.security.provider.cas;
007:
008: import java.io.IOException;
009:
010: import org.jasig.portal.security.PortalSecurityException;
011: import org.jasig.portal.security.provider.ChainingSecurityContext;
012:
013: import edu.yale.its.tp.cas.client.CASReceipt;
014: import edu.yale.its.tp.cas.client.filter.StaticCasReceiptCacherFilter;
015: import edu.yale.its.tp.cas.proxy.ProxyTicketReceptor;
016:
017: /**
018: * CAS security context backed by the StaticCasReceiptCacherFilter.
019: * This security context implements the approach of fronting uPortal login
020: * with the CAS Java Servlet filters (specifically CASValidateFilter and
021: * StaticCasReceiptCacherFilter), allowing the filters to do the "heavy lifting" of
022: * performing the authentication and then just reading and using the
023: * results here in the security context.
024: *
025: * This approach dodges having to configure a constant service URL for
026: * portal login and thereby affords flexibility for supporting parameters
027: * on login for specifying the fname of a channel to jump to on authentication,
028: * e.g.
029: *
030: * Relies on the CASValidationFilter already having done any necessary ticket validation,
031: * and the StaticCasReceiptCacherFilter having cached the receipt, keyed by the ticket.
032: * Based on Susan Bramhall's YaleSecurityContext. Based on edu.yale.its.tp.portal.security.YaleCasFilteredContext
033: * as distributed in the Yale CAS uPortal security provider module version 3.0.0.
034: */
035: public class CasFilteredSecurityContext extends ChainingSecurityContext
036: implements ICasSecurityContext {
037:
038: private static final long serialVersionUID = 1L;
039:
040: /**
041: * Receipt stored here upon authenticate() invocation.
042: */
043: private CASReceipt receipt;
044:
045: CasFilteredSecurityContext() {
046: super ();
047: }
048:
049: public int getAuthType() {
050: return ICasSecurityContext.CAS_AUTHTYPE;
051: }
052:
053: /*
054: * Authentication entry-point Opaque credentials are set to value of ticket
055: * supplied by CAS. This method checks to see if the StaticCasReceiptCacherFilter
056: * has previously cached a receipt representing the prior validation of this ticket.
057: */
058: public synchronized void authenticate()
059: throws PortalSecurityException {
060: if (log.isTraceEnabled()) {
061: log.trace("entering authenticate()");
062: }
063: String serviceTicket = new String(
064: this .myOpaqueCredentials.credentialstring);
065:
066: this .isauth = false;
067: this .receipt = StaticCasReceiptCacherFilter
068: .receiptForTicket(serviceTicket);
069:
070: if (this .receipt != null) {
071: this .myPrincipal.setUID(this .receipt.getUserName());
072: this .isauth = true;
073: log.debug("CASContext authenticated ["
074: + this .myPrincipal.getUID() + "] using receipt ["
075: + this .receipt + "]");
076: }
077:
078: this .myAdditionalDescriptor = null; //no additional descriptor from CAS
079: super .authenticate();
080: if (log.isTraceEnabled()) {
081: log.trace("returning from authenticate()");
082: }
083: return;
084: }
085:
086: public String getCasServiceToken(String target)
087: throws CasProxyTicketAcquisitionException {
088: if (log.isTraceEnabled()) {
089: log.trace("entering getCasServiceToken(" + target
090: + "), previously cached receipt=[" + this .receipt
091: + "]");
092: }
093: if (this .receipt == null) {
094: if (log.isDebugEnabled()) {
095: log
096: .debug("Returning null CAS Service Token because cached receipt is NULL.");
097: }
098: return null;
099: }
100: if (this .receipt.getPgtIou() == null) {
101: if (log.isDebugEnabled()) {
102: log
103: .debug("Returning null CAS Service Token because cached receipt does not include a PGTIOU.");
104: }
105: return null;
106: }
107: String proxyTicket;
108: try {
109: proxyTicket = ProxyTicketReceptor.getProxyTicket(
110: this .receipt.getPgtIou(), target);
111: } catch (IOException e) {
112: log
113: .error(
114: "Error contacting CAS server for proxy ticket",
115: e);
116: throw new CasProxyTicketAcquisitionException(target,
117: this .receipt, e);
118: }
119: if (proxyTicket == null) {
120: log
121: .error("Failed to obtain proxy ticket using receipt ["
122: + this .receipt
123: + "], has the Proxy Granting Ticket referenced by the pgtIou expired?");
124: throw new CasProxyTicketAcquisitionException(target,
125: this .receipt);
126: }
127: if (log.isTraceEnabled()) {
128: log
129: .trace("returning from getCasServiceToken(), returning proxy ticket ["
130: + proxyTicket + "]");
131: }
132: return proxyTicket;
133: }
134:
135: public String toString() {
136: StringBuffer sb = new StringBuffer();
137: sb.append(this .getClass().getName());
138: sb.append(" receipt:");
139: sb.append(this.receipt);
140: return sb.toString();
141: }
142: }
|