Package org.apache.catalina.realm

# Class JAASRealm

java.lang.Object
org.apache.catalina.util.LifecycleBase
org.apache.catalina.util.LifecycleMBeanBase
org.apache.catalina.realm.RealmBase
org.apache.catalina.realm.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

- ## Nested Class Summary

  ### Nested classes/interfaces inherited from class org.apache.catalina.realm.RealmBase

  `RealmBase.AllRolesMode`

  ### Nested classes/interfaces inherited from interface org.apache.catalina.Lifecycle

  `Lifecycle.SingleUse`

- ## Field Summary

  Fields
  Modifier and Type
  Field
  Description
  `protected String`
  `appName`
  The application name passed to the JAAS `LoginContext`, which uses it to select the set of relevant `LoginModule`s.
  `protected String`
  `configFile`
  Path to find a JAAS configuration file, if not set global JVM JAAS configuration will be used.
  `protected Configuration`
  `jaasConfiguration`
  `protected boolean`
  `jaasConfigurationLoaded`
  `protected final List<String>`
  `roleClasses`
  The list of role class names, split out for easy processing.
  `protected String`
  `roleClassNames`
  Comma-delimited list of `java.security.Principal` classes that represent security roles.
  `protected boolean`
  `useContextClassLoader`
  Whether to use context ClassLoader or default ClassLoader.
  `protected final List<String>`
  `userClasses`
  The set of user class names, split out for easy processing.
  `protected String`
  `userClassNames`
  Comma-delimited list of `java.security.Principal` classes that represent individual users.

  ### Fields inherited from class org.apache.catalina.realm.RealmBase

  `allRolesMode, container, containerLog, realmPath, sm, stripRealmForGss, support, USER_ATTRIBUTES_DELIMITER, USER_ATTRIBUTES_WILDCARD, userAttributes, userAttributesList, validate, x509UsernameRetriever, x509UsernameRetrieverClassName`

  ### Fields inherited from interface org.apache.catalina.Lifecycle

  `AFTER_DESTROY_EVENT, AFTER_INIT_EVENT, AFTER_START_EVENT, AFTER_STOP_EVENT, BEFORE_DESTROY_EVENT, BEFORE_INIT_EVENT, BEFORE_START_EVENT, BEFORE_STOP_EVENT, CONFIGURE_START_EVENT, CONFIGURE_STOP_EVENT, PERIODIC_EVENT, START_EVENT, STOP_EVENT`

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `JAASRealm()`

- ## Method Summary

  Modifier and Type
  Method
  Description
  `Principal`
  `authenticate(String username, String credentials)`
  Try to authenticate using the specified username and credentials.
  `Principal`
  `authenticate(String username, String clientDigest, String nonce, String nc, String cnonce, String qop, String realmName, String digestA2, String algorithm)`
  Try to authenticate with the specified username, which matches the digest calculated using the given parameters using the method described in RFC 7616.
  `protected Principal`
  `authenticate(String username, CallbackHandler callbackHandler)`
  Perform the actual JAAS authentication.
  `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`.
  `String`
  `getAppName()`
  `protected Configuration`
  `getConfig()`
  Load custom JAAS Configuration.
  `String`
  `getConfigFile()`
  `protected String`
  `getPassword(String username)`
  Get the password for the specified user.
  `protected Principal`
  `getPrincipal(String username)`
  Get the principal associated with the specified user.
  `String`
  `getRoleClassNames()`
  `String`
  `getUserClassNames()`
  `boolean`
  `isAvailable()`
  Return the availability of the realm for authentication.
  `boolean`
  `isUseContextClassLoader()`
  Returns whether to use the context or default ClassLoader.
  `protected String`
  `makeLegalForJAAS(String src)`
  Ensure the given name is legal for JAAS configuration.
  `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.
  `void`
  `setAppName(String name)`
  Set the JAAS `LoginContext` app name.
  `void`
  `setConfigFile(String configFile)`
  Set the JAAS configuration file.
  `void`
  `setContainer(Container container)`
  Set the `Container` with which this instance is associated.
  `void`
  `setRoleClassNames(String roleClassNames)`
  Sets the list of comma-delimited classes that represent roles.
  `void`
  `setUseContextClassLoader(boolean useContext)`
  Sets whether to use the context or default ClassLoader.
  `void`
  `setUserClassNames(String userClassNames)`
  Sets the list of comma-delimited classes that represent individual users.
  `protected void`
  `startInternal()`
  Prepare for the beginning of active use of the public methods of this component and implement the requirements of `LifecycleBase.startInternal()`.

  ### Methods inherited from class org.apache.catalina.realm.RealmBase

  `addPropertyChangeListener, authenticate, authenticate, authenticate, authenticate, authenticate, backgroundProcess, findSecurityConstraints, getAllRolesMode, getContainer, getCredentialHandler, getDigest, getDigest, getDomainInternal, getObjectNameKeyProperties, getPrincipal, getPrincipal, getPrincipal, getRealmPath, getRealmSuffix, getServer, getTransportGuaranteeRedirectStatus, getUserAttributes, getValidate, getX509UsernameRetrieverClassName, hasMessageDigest, hasResourcePermission, hasRole, hasRoleInternal, hasUserDataPermission, initInternal, isStripRealmForGss, main, parseUserAttributes, removePropertyChangeListener, setAllRolesMode, setCredentialHandler, setRealmPath, setStripRealmForGss, setTransportGuaranteeRedirectStatus, setUserAttributes, setValidate, setX509UsernameRetrieverClassName, stopInternal, toString`

  ### Methods inherited from class org.apache.catalina.util.LifecycleMBeanBase

  `destroyInternal, getDomain, getObjectName, postDeregister, postRegister, preDeregister, preRegister, register, setDomain, unregister, unregister`

  ### Methods inherited from class org.apache.catalina.util.LifecycleBase

  `addLifecycleListener, destroy, findLifecycleListeners, fireLifecycleEvent, getState, getStateName, getThrowOnFailure, init, removeLifecycleListener, setState, setState, setThrowOnFailure, start, stop`

  ### Methods inherited from class java.lang.Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait`

- ## Field Details

  - ### appName

    protected String appName
    The application name passed to the JAAS `LoginContext`, which uses it to select the set of relevant `LoginModule`s.

  - ### 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 `LoginModule`s

  - ### 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.

    The default implementation calls `Realm.authenticate(String, String, String, String, String, String, String, String)` for backwards compatibility which effectively forces the use of MD5 regardless of the algorithm specified in the call to this method.

    Implementations are expected to override the default implementation and take account of the algorithm parameter.

    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