Class JAASRealm

  • All Implemented Interfaces:
    javax.management.MBeanRegistration, Contained, JmxEnabled, Lifecycle, Realm

    public class JAASRealm
    extends RealmBase

    Implementation of Realm that authenticates users via the Java Authentication and Authorization Service (JAAS). JAAS support requires either JDK 1.4 (which includes it as part of the standard platform) or JDK 1.3 (with the plug-in jaas.jar file).

    The value configured for the appName property is passed to the javax.security.auth.login.LoginContext constructor, to specify the application name used to select the set of relevant LoginModules required.

    The JAAS Specification describes the result of a successful login as a javax.security.auth.Subject instance, which can contain zero or more java.security.Principal objects in the return value of the Subject.getPrincipals() method. However, it provides no guidance on how to distinguish Principals that describe the individual user (and are thus appropriate to return as the value of request.getUserPrincipal() in a web application) from the Principal(s) that describe the authorized roles for this user. To maintain as much independence as possible from the underlying LoginMethod implementation executed by JAAS, the following policy is implemented by this Realm:

    • The JAAS LoginModule is assumed to return a Subject with at least one Principal instance representing the user himself or herself, and zero or more separate Principals representing the security roles authorized for this user.
    • On the Principal representing the user, the Principal name is an appropriate value to return via the Servlet API method HttpServletRequest.getRemoteUser().
    • On the Principals representing the security roles, the name is the name of the authorized security role.
    • This Realm will be configured with two lists of fully qualified Java class names of classes that implement java.security.Principal - one that identifies class(es) representing a user, and one that identifies class(es) representing a security role.
    • As this Realm iterates over the Principals returned by Subject.getPrincipals(), it will identify the first Principal that matches the "user classes" list as the Principal for this user.
    • As this Realm iterates over the Principals returned by Subject.getPrincipals(), it will accumulate the set of all Principals matching the "role classes" list as identifying the security roles for this user.
    • It is a configuration error for the JAAS login method to return a validated Subject without a Principal that matches the "user classes" list.
    • By default, the enclosing Container's name serves as the application name used to obtain the JAAS LoginContext ("Catalina" in a default installation). Tomcat must be able to find an application with this name in the JAAS configuration file. Here is a hypothetical JAAS configuration file entry for a database-oriented login module that uses a Tomcat-managed JNDI database resource:
      Catalina {
      org.foobar.auth.DatabaseLoginModule REQUIRED
          JNDI_RESOURCE=jdbc/AuthDB
        USER_TABLE=users
        USER_ID_COLUMN=id
        USER_NAME_COLUMN=name
        USER_CREDENTIAL_COLUMN=password
        ROLE_TABLE=roles
        ROLE_NAME_COLUMN=name
        PRINCIPAL_FACTORY=org.foobar.auth.impl.SimplePrincipalFactory;
      };
    • To set the JAAS configuration file location, set the CATALINA_OPTS environment variable similar to the following:
      CATALINA_OPTS="-Djava.security.auth.login.config=$CATALINA_HOME/conf/jaas.config"
    • As part of the login process, JAASRealm registers its own CallbackHandler, called (unsurprisingly) JAASCallbackHandler. This handler supplies the HTTP requests's username and credentials to the user-supplied LoginModule
    • As with other Realm implementations, digested passwords are supported if the <Realm> element in server.xml contains a digest attribute; JAASCallbackHandler will digest the password prior to passing it back to the LoginModule
    Author:
    Craig R. McClanahan, Yoav Shapira
    • Field Detail

      • appName

        protected java.lang.String appName
        The application name passed to the JAAS LoginContext, which uses it to select the set of relevant LoginModules.
      • roleClasses

        protected final java.util.List<java.lang.String> roleClasses
        The list of role class names, split out for easy processing.
      • userClasses

        protected final java.util.List<java.lang.String> userClasses
        The set of user class names, split out for easy processing.
      • useContextClassLoader

        protected boolean useContextClassLoader
        Whether to use context ClassLoader or default ClassLoader. True means use context ClassLoader, and True is the default value.
      • configFile

        protected java.lang.String configFile
        Path to find a JAAS configuration file, if not set global JVM JAAS configuration will be used.
      • jaasConfiguration

        protected volatile javax.security.auth.login.Configuration jaasConfiguration
      • jaasConfigurationLoaded

        protected volatile boolean jaasConfigurationLoaded
      • roleClassNames

        protected java.lang.String roleClassNames
        Comma-delimited list of java.security.Principal classes that represent security roles.
      • userClassNames

        protected java.lang.String userClassNames
        Comma-delimited list of java.security.Principal classes that represent individual users.
    • Constructor Detail

      • JAASRealm

        public JAASRealm()
    • Method Detail

      • getConfigFile

        public java.lang.String getConfigFile()
        Returns:
        the path of the JAAS configuration file.
      • setConfigFile

        public void setConfigFile​(java.lang.String configFile)
        Set the JAAS configuration file.
        Parameters:
        configFile - The JAAS configuration file
      • setAppName

        public void setAppName​(java.lang.String name)
        Set the JAAS LoginContext app name.
        Parameters:
        name - The application name that will be used to retrieve the set of relevant LoginModules
      • getAppName

        public java.lang.String getAppName()
        Returns:
        the application name.
      • setUseContextClassLoader

        public void setUseContextClassLoader​(boolean useContext)
        Sets whether to use the context or default ClassLoader. True means use context ClassLoader.
        Parameters:
        useContext - True means use context ClassLoader
      • isUseContextClassLoader

        public boolean isUseContextClassLoader()
        Returns whether to use the context or default ClassLoader. True means to use the context ClassLoader.
        Returns:
        The value of useContextClassLoader
      • setContainer

        public void setContainer​(Container container)
        Description copied from class: RealmBase
        Set the Container with which this Realm has been associated.
        Specified by:
        setContainer in interface Contained
        Overrides:
        setContainer in class RealmBase
        Parameters:
        container - The associated Container
      • getRoleClassNames

        public java.lang.String getRoleClassNames()
      • setRoleClassNames

        public void setRoleClassNames​(java.lang.String roleClassNames)
        Sets the list of comma-delimited classes that represent roles. The classes in the list must implement java.security.Principal. The supplied list of classes will be parsed when LifecycleBase.start() is called.
        Parameters:
        roleClassNames - The class names list
      • parseClassNames

        protected void parseClassNames​(java.lang.String classNamesString,
                                       java.util.List<java.lang.String> classNamesList)
        Parses a comma-delimited list of class names, and store the class names in the provided List. Each class must implement java.security.Principal.
        Parameters:
        classNamesString - a comma-delimited list of fully qualified class names.
        classNamesList - the list in which the class names will be stored. The list is cleared before being populated.
      • getUserClassNames

        public java.lang.String getUserClassNames()
      • setUserClassNames

        public void setUserClassNames​(java.lang.String userClassNames)
        Sets the list of comma-delimited classes that represent individual users. The classes in the list must implement java.security.Principal. The supplied list of classes will be parsed when LifecycleBase.start() is called.
        Parameters:
        userClassNames - The class names list
      • authenticate

        public java.security.Principal authenticate​(java.lang.String username,
                                                    java.lang.String credentials)
        Return the Principal associated with the specified username and credentials, if there is one; otherwise return null.
        Specified by:
        authenticate in interface Realm
        Overrides:
        authenticate in class RealmBase
        Parameters:
        username - Username of the Principal to look up
        credentials - Password or other credentials to use in authenticating this username
        Returns:
        the associated principal, or null if there is none.
      • authenticate

        public java.security.Principal authenticate​(java.lang.String username,
                                                    java.lang.String clientDigest,
                                                    java.lang.String nonce,
                                                    java.lang.String nc,
                                                    java.lang.String cnonce,
                                                    java.lang.String qop,
                                                    java.lang.String realmName,
                                                    java.lang.String md5a2)
        Return the Principal associated with the specified username and digest, if there is one; otherwise return null.
        Specified by:
        authenticate in interface Realm
        Overrides:
        authenticate in class RealmBase
        Parameters:
        username - Username of the Principal to look up
        clientDigest - Digest to use in authenticating this username
        nonce - Server generated nonce
        nc - Nonce count
        cnonce - Client generated nonce
        qop - Quality of protection applied to the message
        realmName - Realm name
        md5a2 - Second MD5 digest used to calculate the digest MD5(Method + ":" + uri)
        Returns:
        the associated principal, or null if there is none.
      • authenticate

        protected java.security.Principal authenticate​(java.lang.String username,
                                                       javax.security.auth.callback.CallbackHandler callbackHandler)
        Perform the actual JAAS authentication.
        Parameters:
        username - The user name
        callbackHandler - The callback handler
        Returns:
        the associated principal, or null if there is none.
      • getPassword

        protected java.lang.String getPassword​(java.lang.String username)
        Description copied from class: RealmBase
        Get the password for the specified user.
        Specified by:
        getPassword in class RealmBase
        Parameters:
        username - The user name
        Returns:
        the password associated with the given principal's user name. This always returns null as the JAASRealm has no way of obtaining this information.
      • getPrincipal

        protected java.security.Principal getPrincipal​(java.lang.String username)
        Description copied from class: RealmBase
        Get the principal associated with the specified user.
        Specified by:
        getPrincipal in class RealmBase
        Parameters:
        username - The user name
        Returns:
        the Principal associated with the given user name.
      • createPrincipal

        protected java.security.Principal createPrincipal​(java.lang.String username,
                                                          javax.security.auth.Subject subject,
                                                          javax.security.auth.login.LoginContext loginContext)
        Identify and return a java.security.Principal instance representing the authenticated user for the specified Subject. The Principal is constructed by scanning the list of Principals returned by the JAASLoginModule. The first Principal object that matches one of the class names supplied as a "user class" is the user Principal. This object is returned to the caller. Any remaining principal objects returned by the LoginModules are mapped to roles, but only if their respective classes match one of the "role class" classes. If a user Principal cannot be constructed, return null.
        Parameters:
        username - The associated user name
        subject - The Subject representing the logged-in user
        loginContext - Associated with the Principal so LoginContext.logout() can be called later
        Returns:
        the principal object
      • makeLegalForJAAS

        protected java.lang.String makeLegalForJAAS​(java.lang.String src)
        Ensure the given name is legal for JAAS configuration. Added for Bugzilla 30869, made protected for easy customization in case my implementation is insufficient, which I think is very likely.
        Parameters:
        src - The name to validate
        Returns:
        A string that's a valid JAAS realm name
      • getConfig

        protected javax.security.auth.login.Configuration getConfig()
        Load custom JAAS Configuration.
        Returns:
        the loaded configuration
      • isAvailable

        public boolean isAvailable()
        Description copied from interface: Realm
        Return the availability of the realm for authentication.
        Returns:
        true if the realm is able to perform authentication