Class JAASRealm

All Implemented Interfaces:
MBeanRegistration, Contained, JmxEnabled, Lifecycle, Realm

public class JAASRealm extends RealmBase

Implementation of Realm that authenticates users via the Java Authentication and Authorization Service (JAAS).

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 Details

    • appName

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

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

      protected final List<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 String configFile
      Path to find a JAAS configuration file, if not set global JVM JAAS configuration will be used.
    • jaasConfiguration

      protected volatile Configuration jaasConfiguration
    • jaasConfigurationLoaded

      protected volatile boolean jaasConfigurationLoaded
    • roleClassNames

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

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

    • JAASRealm

      public JAASRealm()
  • Method Details

    • getConfigFile

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

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

      public void setAppName(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 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 interface: Contained
      Set the Container with which this instance is associated.
      Specified by:
      setContainer in interface Contained
      Overrides:
      setContainer in class RealmBase
      Parameters:
      container - The Container instance with which this instance is to be associated, or null to disassociate this instance from any Container
    • getRoleClassNames

      public String getRoleClassNames()
    • setRoleClassNames

      public void setRoleClassNames(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(String classNamesString, List<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 String getUserClassNames()
    • setUserClassNames

      public void setUserClassNames(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 Principal authenticate(String username, String credentials)
      Description copied from interface: Realm
      Try to authenticate using the specified username and credentials.
      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 Principal authenticate(String username, String clientDigest, String nonce, String nc, String cnonce, String qop, String realmName, String digestA2, String algorithm)
      Description copied from interface: Realm
      Try to authenticate with the specified username, which matches the digest calculated using the given parameters using the method described in RFC 7616.
      Specified by:
      authenticate in interface Realm
      Overrides:
      authenticate in class RealmBase
      Parameters:
      username - Username of the Principal to look up
      clientDigest - Digest which has been submitted by the client
      nonce - Unique (or supposedly unique) token which has been used for this request
      nc - the nonce counter
      cnonce - the client chosen nonce
      qop - the "quality of protection" (nc and cnonce will only be used, if qop is not null).
      realmName - Realm name
      digestA2 - Second digest calculated as digest(Method + ":" + uri)
      algorithm - The message digest algorithm to use
      Returns:
      the associated principal, or null if there is none.
    • authenticate

      protected Principal authenticate(String username, 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 String getPassword(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 Principal getPrincipal(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 Principal createPrincipal(String username, Subject subject, 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 String makeLegalForJAAS(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
    • startInternal

      protected void startInternal() throws LifecycleException
      Description copied from class: RealmBase
      Prepare for the beginning of active use of the public methods of this component and implement the requirements of LifecycleBase.startInternal().
      Overrides:
      startInternal in class RealmBase
      Throws:
      LifecycleException - if this component detects a fatal error that prevents this component from being used
    • getConfig

      protected 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