001: /*
002: * JOSSO: Java Open Single Sign-On
003: *
004: * Copyright 2004-2008, Atricore, Inc.
005: *
006: * This is free software; you can redistribute it and/or modify it
007: * under the terms of the GNU Lesser General Public License as
008: * published by the Free Software Foundation; either version 2.1 of
009: * the License, or (at your option) any later version.
010: *
011: * This software is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this software; if not, write to the Free
018: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
019: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
020: */
021:
022: package org.josso.tc50.agent.jaas;
023:
024: import org.apache.catalina.Realm;
025: import org.apache.catalina.realm.GenericPrincipal;
026: import org.apache.commons.logging.Log;
027: import org.apache.commons.logging.LogFactory;
028: import org.josso.gateway.SSONameValuePair;
029: import org.josso.gateway.identity.SSOUser;
030:
031: import javax.security.auth.Subject;
032: import java.security.Principal;
033: import java.security.acl.Group;
034: import java.util.ArrayList;
035: import java.util.Enumeration;
036: import java.util.Iterator;
037: import java.util.List;
038:
039: /**
040: * On authentication, Catalina JAAS Realm doesn't return the Principal instances as
041: * built by the Login Modules. It returns a Catalina-specific Principal called GenericPrincipal.
042: * As a consequence all the additional properties that the SSOUser instance carries are lost.
043: * With this class, we'll make Catalina beleive that our SSOUser its actually a GenericPrincipal, so that it
044: * doesn't create a new one.
045: *
046: * @author <a href="mailto:gbrigand@josso.org">Gianluca Brigandi</a>
047: * @version CVS $Id: CatalinaSSOUser.java 508 2008-02-18 13:32:29Z sgonzalez $
048: */
049:
050: public class CatalinaSSOUser extends GenericPrincipal implements
051: SSOUser {
052: private static Log logger = LogFactory
053: .getLog(CatalinaSSOUser.class);
054:
055: private static List _userClasses = new ArrayList();
056: private static List _roleClasses = new ArrayList();
057:
058: static {
059: _userClasses
060: .add("org.josso.gateway.identity.service.BaseUserImpl");
061: _roleClasses
062: .add("org.josso.gateway.identity.service.BaseRoleImpl");
063: }
064:
065: private SSOUser _ssoUser;
066:
067: /**
068: * Construct and return a java.security.Principal instance
069: * representing the authenticated user for the specified Subject. If no
070: * such Principal can be constructed, return null.
071: *
072: * The Principal constructed is *not* GenericPrincipal as in Catalina JAASRealm class,
073: * but CatalinaSSOUser which is a SSOUser.
074: * The Partner Application can access SSOUser-specific properties that are not available
075: * in GenericPrincipal.
076: * The JAASRealm superclass invokes this factory method to build the Catalina-specific
077: * Principal from the Subject filled by the configured JAASLoginModule.
078: *
079: * @param subject The Subject representing the logged in user
080: */
081: public static CatalinaSSOUser newInstance(Realm realm,
082: Subject subject) {
083: // Prepare to scan the Principals for this Subject
084: String password = null; // Will not be carried forward
085: ArrayList roles = new ArrayList();
086: SSOUser ssoUser = null;
087: String username = null;
088:
089: // Scan the Principals for this Subject
090: Iterator principals = subject.getPrincipals().iterator();
091: while (principals.hasNext()) {
092: Principal principal = (Principal) principals.next();
093: // No need to look further - that's our own stuff
094: if (principal instanceof CatalinaSSOUser) {
095: if (logger.isDebugEnabled())
096: logger.debug("Found old CatalinaSSOUser Principal "
097: + principal);
098: return (CatalinaSSOUser) principal;
099: }
100: String principalClass = principal.getClass().getName();
101: if (logger.isDebugEnabled())
102: logger.debug("Principal: " + principalClass + " "
103: + principal);
104:
105: if (_userClasses.contains(principalClass)) {
106: // Override the default - which is the original user, accepted by
107: // the friendly LoginManager
108: username = principal.getName();
109: }
110: if (_roleClasses.contains(principalClass)) {
111: roles.add(principal.getName());
112: }
113: // Same as Jboss - that's a pretty clean solution
114: if ((principal instanceof Group)
115: && "Roles".equals(principal.getName())) {
116: Group grp = (Group) principal;
117: Enumeration en = grp.members();
118: while (en.hasMoreElements()) {
119: Principal roleP = (Principal) en.nextElement();
120: roles.add(roleP.getName());
121: }
122:
123: }
124:
125: // Save the SSOUser principal so that it can be included in the
126: // CatalinaSSOUser Principal
127: if (principal instanceof SSOUser) {
128: ssoUser = (SSOUser) principal;
129: }
130: }
131:
132: if (ssoUser == null) {
133: logger
134: .error("Fatal: Subject does not contain an SSOUser Principal");
135: return null;
136: }
137:
138: // Create the resulting Principal for our authenticated user
139: if (username != null) {
140: return (new CatalinaSSOUser(ssoUser, realm, username,
141: password, roles));
142: } else {
143: return (null);
144: }
145: }
146:
147: /**
148: * Construct a new Principal, associated with the specified Realm, for the
149: * specified username and password.
150: *
151: * @param realm The Realm that owns this Principal
152: * @param name The username of the user represented by this Principal
153: * @param password Credentials used to authenticate this user
154: */
155: private CatalinaSSOUser(SSOUser ssoUser, Realm realm, String name,
156: String password) {
157:
158: this (ssoUser, realm, name, password, null);
159: }
160:
161: /**
162: * Construct a new Principal, associated with the specified Realm, for the
163: * specified username and password, with the specified role names
164: * (as Strings).
165: *
166: * @param realm The Realm that owns this principal
167: * @param name The username of the user represented by this Principal
168: * @param password Credentials used to authenticate this user
169: * @param roles List of roles (must be Strings) possessed by this user
170: */
171: private CatalinaSSOUser(SSOUser ssoUser, Realm realm, String name,
172: String password, List roles) {
173:
174: super (realm, name, password, roles);
175: _ssoUser = ssoUser;
176:
177: }
178:
179: /**
180: * @deprecated this method always return null
181: * @return always null
182: */
183: public String getSessionId() {
184: return null;
185: }
186:
187: public SSONameValuePair[] getProperties() {
188: return _ssoUser.getProperties();
189: }
190:
191: /**
192: * Return a String representation of this object, which exposes only
193: * information that should be public.
194: */
195: public String toString() {
196: StringBuffer sb = new StringBuffer("CatalinaSSOUser[");
197: sb.append(this .name);
198: sb.append("]");
199: return (sb.toString());
200: }
201:
202: }
|