Authentication FrameworkUpdated by: Susan Bramhall 10/3/01 IntroductionThe emerging De facto standard conceptualization of an Internet portal typically requires a mechanism that allows users to identify themselves. At the very least, this mechanism allows stored per-user preferences to be retrieved and applied. In addition, the concept of a session with a corresponding lifespan is presumed. For the purposes of a University portal, we must extend this model to embody several additional features.
These goals can be met through the combination of documents (such as this) that provide design guidelines as well as Java classes, interfaces and support packages. This support code takes the form of interface definitions that must be implemented by the developers of backend authentication entities as well as concrete code that is part of the core portal framework. In addition, examples of specific authentication implementations are provided and can be used outright or serve as a guide to those authoring new authentication mechanisms. The uPortal Version 2 Beta provides the following examples of authentication providers:
Authentication Life cycleAn authentication object begins life once a single principle associated with the object is identified and optionally verified as authentic. The object's life ends during an operation typically regarded as a "logout" (either active or passive). As such we need to either invent or utilize a pre-existing mechanism to maintain authentication state during the session. The simplest (and currently implemented) approach is to use the Servlet Session object to hold a reference to the authentication object. The advantages of this model are that a Session (HttpSession) object can be counted on to exist and has a semantic behavior that meets our minimum needs. The downside of this approach is that:
Authentication Objects and MechanismsThe proposed authentication mechanism for the portal project will require Java classes that implement the four following interfaces and proceed as follows:
The process of authentication creates three additional objects per security context that are referenced through the security context. These are:
The Principal InterfaceThis interface can be described as: Principal public interface Principal { public String getUID(); public String getGlobalUID(); public String getFullName(); protected void setUID(String uid); } The string value manipulated by get/setUID represents a "userid" or "username" that is sufficiently specific to be unique within the context of the portal. the GlobalUID referenced above is a version of the same but with enough additional information to be considered globally unique. For example, the network identifier "newman" is sufficient within the Yale portal to identify a single user. Since the authentication would be done against a Kerberos realm, the result of getGlobalUID() in this case would return newman/@NET.YALE.EDU". In an LDAP/X.500 environment the UID might be either the UID= or CN= field where the GlobalUID would be the entirely specified distinguished name (LDAP) or Subject field of an X.509 certificate. (Note that GlobalUID was incorrectly changed to an integer in the uPortal Beta and needs to be reinstated as originally intended in order to enable future cross-realm authentication.) The OpaqueCredentials InterfaceThis interface can be described as: Opaque Credentials public interface OpaqueCredentials { public void setCredentials(byte[]); public void setCredentials(String); } The intention here is provide a set of cover functions to allow the storage of some data used to verify the identity of the principal. One important aesthetic here is that the object implementing this that persists for the life of the session should not store credentials that are no longer needed after the initial login. For a simple password based authentication, the password (for instance) should not be kept after it is verified as correct. On the other hand, in the case of a Kerberos environment, the resulting decrypted ticket granting ticket might be kept in a persistent object implementing the OpaqueCredentials interface. Another concrete example might be the pass phrase used to decrypt an RSA private key. This should not be kept around but the decrypted private key might be kept around. On the other hand, if the private key is only used once to immediately establish a set of session working keys (as in Secure Sockets Layer or Internet Key Exchange) then even the private key should be destroyed after the session keys are established. The AdditionalDescriptor InterfaceThis interface has no required methods and is merely a "marker" interface (like Serializable). The purpose of this is to provide a spot to store additional information that is idiosyncratic to the authentication mechanism or came "for free" with the authentication records. One example of this are the Unix UID and GID vectors associated with a typical Unix login. Another is the collection of various attributes and characteristics typically associated with a PKIX profiled X.509v3 certificate. It is important to recognize that some of these additional attributes have a native access control use (group affiliation under Unix for instance) within their native systems. In the portal model however, these attributes may be algorithmically mapped to portal access control roles but may not be used as access control tokens themselves. The reason for this is that the ACL mechanism would then be forever tied to a particular authentication flavor. The SecurityContext InterfaceThis interface can be described as: SecurityContext public interface SecurityContext { public int getAuthType(); public String getChannelAffiliation(); public void authenticate(Principal, OpaqueCredentials); public Principal getPrincipal(); public OpaqueCredentials getOpaqueCredentials(); public AdditionalDescriptor getAdditionalDescriptor(); public boolean isAuthenticated(); public SecurityContext getSubContext(String); public Enumeration getSubContexts(); protected void addSubContext(String); } This is the main interface that drives the authentication mechanism and allows channels to add security contexts that must be resolved at authenticate time. Some of the aesthetics of this interface require further discussion. The integer value returned by getAuthType() should be a globally unique authentication flavor. One possibility is to use the SASL names for authentication. It is important, for instance that if we agree that: public static final int PASSWORD_AUTH = 0x44; The concept of PASSWORD_AUTH is clearly documented and no one else uses either the number or the name for a different flavor of password-based authentication. The concept of channel affiliation allows credentials to be stored that will be used by channel-specific authentication. (See single sign on below). If there are no additional authentication descriptors or no stored opaque credentials, the value returned from these methods is allowed to be null and the caller must check for this before continuing. Single Sign onThe promise of single sign on has been an illusive goal for some time now. In the context of the portal environment, a purist would claim that we should either take advantage of a pre-existent single sign on model that all applications have subscribed to or suffer if it is absent. A more flexible approach presented here is to "dummy up" the single sign on by acquiring all credentials needed at portal session startup. Each channel can register a security requirement but the credentials must all be resolved at one time. For example, in a simple world we might have two security domains that each require a pass-word and by convention both use the same password. In that case, one is chosen as the authentication system for the portal session and any channels that use it get it "for free". Channels that use the other security domain request that the same password be used to acquire these credentials at the same time. The credentials might be something like a Kerberos TGT or they might be a Connection handle to an Oracle database account accessed with a password. As mentioned above, all effort to avoid storing the actual password should be made. Java Virtual Machine and SecurityOne topic that must at least be mentioned is the risk of using a JVM to store sensitive security-related information. A single JVM today has no concept of trusted paths, system-level security descriptors or anything like system virtual memory protection. Because of this, all threads executing in a single JVM should play nice together since they will likely be able to access each others' data. The Servlet environment has the ability to separate Servlet (or JSP) based applications into. Separate ServletContexts to avoid namespace overlap but this shouldn't be regarded as a security perimeter per se. At the very least, the Servlet/JSP runtime that vends the portal and its channels should be configured to run in a dedicated JVM until such time that the technology allows JVMs to support strong security internally. |