Module jdk.security.auth
Package com.sun.security.auth.module

# Class LdapLoginModule

java.lang.Object
com.sun.security.auth.module.LdapLoginModule

All Implemented Interfaces:
  `LoginModule`

public class LdapLoginModule extends Object implements LoginModule
This `LoginModule` performs LDAP-based authentication. A username and password is verified against the corresponding user credentials stored in an LDAP directory. This module requires the supplied `CallbackHandler` to support a `NameCallback` and a `PasswordCallback`. If authentication is successful then a new `LdapPrincipal` is created using the user's distinguished name and a new `UserPrincipal` is created using the user's username and both are associated with the current `Subject`.

This module operates in one of three modes: search-first, authentication-first or authentication-only. A mode is selected by specifying a particular set of options.

In search-first mode, the LDAP directory is searched to determine the user's distinguished name and then authentication is attempted. An (anonymous) search is performed using the supplied username in conjunction with a specified search filter. If successful then authentication is attempted using the user's distinguished name and the supplied password. To enable this mode, set the `userFilter` option and omit the `authIdentity` option. Use search-first mode when the user's distinguished name is not known in advance.

In authentication-first mode, authentication is attempted using the supplied username and password and then the LDAP directory is searched. If authentication is successful then a search is performed using the supplied username in conjunction with a specified search filter. To enable this mode, set the `authIdentity` and the `userFilter` options. Use authentication-first mode when accessing an LDAP directory that has been configured to disallow anonymous searches.

In authentication-only mode, authentication is attempted using the supplied username and password. The LDAP directory is not searched because the user's distinguished name is already known. To enable this mode, set the `authIdentity` option to a valid distinguished name and omit the `userFilter` option. Use authentication-only mode when the user's distinguished name is known in advance.

The following option is mandatory and must be specified in this module's login `Configuration`:

`userProvider=ldap_urls`
  This option identifies the LDAP directory that stores user entries. ldap_urls is a list of space-separated LDAP URLs (RFC 2255) that identifies the LDAP server to use and the position in its directory tree where user entries are located. When several LDAP URLs are specified then each is attempted, in turn, until the first successful connection is established. Spaces in the distinguished name component of the URL must be escaped using the standard mechanism of percent character ('`%`') followed by two hexadecimal digits (see `URI`). Query components must also be omitted from the URL.

  Automatic discovery of the LDAP server via DNS (RFC 2782) is supported (once DNS has been configured to support such a service). It is enabled by omitting the hostname and port number components from the LDAP URL.

This module also recognizes the following optional `Configuration` options:

`userFilter=ldap_filter`
  This option specifies the search filter to use to locate a user's entry in the LDAP directory. It is used to determine a user's distinguished name. `ldap_filter` is an LDAP filter string (RFC 2254). If it contains the special token "`{USERNAME}`" then that token will be replaced with the supplied username value before the filter is used to search the directory.
`authIdentity=auth_id`
  This option specifies the identity to use when authenticating a user to the LDAP directory. `auth_id` may be an LDAP distinguished name string (RFC 2253) or some other string name. It must contain the special token "`{USERNAME}`" which will be replaced with the supplied username value before the name is used for authentication. Note that if this option does not contain a distinguished name then the `userFilter` option must also be specified.
`authzIdentity=authz_id`
  This option specifies an authorization identity for the user. `authz_id` is any string name. If it comprises a single special token with curly braces then that token is treated as a attribute name and will be replaced with a single value of that attribute from the user's LDAP entry. If the attribute cannot be found then the option is ignored. When this option is supplied and the user has been successfully authenticated then an additional `UserPrincipal` is created using the authorization identity and it is associated with the current `Subject`.
`useSSL`
  if `false`, this module does not establish an SSL connection to the LDAP server before attempting authentication. SSL is used to protect the privacy of the user's password because it is transmitted in the clear over LDAP. By default, this module uses SSL.
`useFirstPass`
  if `true`, this module retrieves the username and password from the module's shared state, using "javax.security.auth.login.name" and "javax.security.auth.login.password" as the respective keys. The retrieved values are used for authentication. If authentication fails, no attempt for a retry is made, and the failure is reported back to the calling application.
`tryFirstPass`
  if `true`, this module retrieves the username and password from the module's shared state, using "javax.security.auth.login.name" and "javax.security.auth.login.password" as the respective keys. The retrieved values are used for authentication. If authentication fails, the module uses the `CallbackHandler` to retrieve a new username and password, and another attempt to authenticate is made. If the authentication fails, the failure is reported back to the calling application.
`storePass`
  if `true`, this module stores the username and password obtained from the `CallbackHandler` in the module's shared state, using "javax.security.auth.login.name" and "javax.security.auth.login.password" as the respective keys. This is not performed if existing values already exist for the username and password in the shared state, or if authentication fails.
`clearPass`
  if `true`, this module clears the username and password stored in the module's shared state after both phases of authentication (login and commit) have completed.
`debug`
  if `true`, debug messages are displayed on the standard output stream.

Arbitrary "JNDI properties" may also be specified in the `Configuration`. They are added to the environment and passed to the LDAP provider. Note that the following four JNDI properties are set by this module directly and are ignored if also present in the configuration:

- `java.naming.provider.url`
- `java.naming.security.principal`
- `java.naming.security.credentials`
- `java.naming.security.protocol`

Three sample `Configuration`s are shown below. The first one activates search-first mode. It identifies the LDAP server and specifies that users' entries be located by their `uid` and `objectClass` attributes. It also specifies that an identity based on the user's `employeeNumber` attribute should be created. The second one activates authentication-first mode. It requests that the LDAP server be located dynamically, that authentication be performed using the supplied username directly but without the protection of SSL and that users' entries be located by one of three naming attributes and their `objectClass` attribute. The third one activates authentication-only mode. It identifies alternative LDAP servers, it specifies the distinguished name to use for authentication and a fixed identity to use for authorization. No directory search is performed.

         ExampleApplication {
             com.sun.security.auth.module.LdapLoginModule REQUIRED
                  userProvider="ldap://ldap-svr/ou=people,dc=example,dc=com"
                  userFilter="(&(uid={USERNAME})(objectClass=inetOrgPerson))"
                  authzIdentity="{EMPLOYEENUMBER}"
                  debug=true;
         };

         ExampleApplication {
             com.sun.security.auth.module.LdapLoginModule REQUIRED
                 userProvider="ldap:///cn=users,dc=example,dc=com"
                 authIdentity="{USERNAME}"
                 userFilter="(&(|(samAccountName={USERNAME})(userPrincipalName={USERNAME})(cn={USERNAME}))(objectClass=user))"
                 useSSL=false
                 debug=true;
         };

         ExampleApplication {
             com.sun.security.auth.module.LdapLoginModule REQUIRED
                 userProvider="ldap://ldap-svr1 ldap://ldap-svr2"
                 authIdentity="cn={USERNAME},ou=people,dc=example,dc=com"
                 authzIdentity="staff"
                 debug=true;
         };

Note:
  When a `SecurityManager` is active then an application that creates a `LoginContext` and uses a `LoginModule` must be granted certain permissions.

  If the application creates a login context using an installed `Configuration` then the application must be granted the `AuthPermission` to create login contexts. For example, the following security policy allows an application in the user's current directory to instantiate any login context:

           grant codebase "file:${user.dir}/" {
               permission javax.security.auth.AuthPermission "createLoginContext.*";
           };

  Alternatively, if the application creates a login context using a caller-specified `Configuration` then the application must be granted the permissions required by the `LoginModule`. This module requires the following two permissions:
  - The `SocketPermission` to connect to an LDAP server.
  - The `AuthPermission` to modify the set of `Principal`s associated with a `Subject`.

  For example, the following security policy grants an application in the user's current directory all the permissions required by this module:

           grant codebase "file:${user.dir}/" {
               permission java.net.SocketPermission "*:389", "connect";
               permission java.net.SocketPermission "*:636", "connect";
               permission javax.security.auth.AuthPermission "modifyPrincipals";
           };

Since:
  1.6

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `LdapLoginModule()`
  Creates an `LdapLoginModule`.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `boolean`
  `abort()`
  Abort user authentication.
  `boolean`
  `commit()`
  Complete user authentication.
  `void`
  `initialize(Subject subject, CallbackHandler callbackHandler, Map<String,?> sharedState, Map<String,?> options)`
  Initialize this `LoginModule`.
  `boolean`
  `login()`
  Begin user authentication.
  `boolean`
  `logout()`
  Logout a user.

  ### Methods declared in class java.lang.Object

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

- ## Constructor Details

  - ### LdapLoginModule

    public LdapLoginModule()
    Creates an `LdapLoginModule`.

- ## Method Details

  - ### initialize

    public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String,?> sharedState, Map<String,?> options)
    Initialize this `LoginModule`.
    Specified by:
      `initialize` in interface `LoginModule`
    Parameters:
      `subject` - the `Subject` to be authenticated.
      `callbackHandler` - a `CallbackHandler` to acquire the username and password.
      `sharedState` - shared `LoginModule` state.
      `options` - options specified in the login `Configuration` for this particular `LoginModule`.

  - ### login

    public boolean login() throws LoginException
    Begin user authentication.

    Acquire the user's credentials and verify them against the specified LDAP directory.

    Specified by:
      `login` in interface `LoginModule`
    Returns:
      true always, since this `LoginModule` should not be ignored.
    Throws:
      `FailedLoginException` - if the authentication fails.
      `LoginException` - if this `LoginModule` is unable to perform the authentication.

  - ### commit

    public boolean commit() throws LoginException
    Complete user authentication.

    This method is called if the LoginContext's overall authentication succeeded (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules succeeded).

    If this LoginModule's own authentication attempt succeeded (checked by retrieving the private state saved by the `login` method), then this method associates an `LdapPrincipal` and one or more `UserPrincipal`s with the `Subject` located in the `LoginModule`. If this LoginModule's own authentication attempted failed, then this method removes any state that was originally saved.

    Specified by:
      `commit` in interface `LoginModule`
    Returns:
      true if this LoginModule's own login and commit attempts succeeded, or false otherwise.
    Throws:
      `LoginException` - if the commit fails

  - ### abort

    public boolean abort() throws LoginException
    Abort user authentication.

    This method is called if the overall authentication failed. (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules did not succeed).

    If this LoginModule's own authentication attempt succeeded (checked by retrieving the private state saved by the `login` and `commit` methods), then this method cleans up any state that was originally saved.

    Specified by:
      `abort` in interface `LoginModule`
    Returns:
      false if this LoginModule's own login and/or commit attempts failed, and true otherwise.
    Throws:
      `LoginException` - if the abort fails.

  - ### logout

    public boolean logout() throws LoginException
    Logout a user.

    This method removes the Principals that were added by the `commit` method.

    Specified by:
      `logout` in interface `LoginModule`
    Returns:
      true in all cases since this `LoginModule` should not be ignored.
    Throws:
      `LoginException` - if the logout fails.