blogger templates blogger widgets
This is part of a list of blog posts.
To browse the contents go to

Authentication and Authorization mechanism


What is authentication?

Authentication is the process of determining whether someone (or something) in fact is what he/she/it asserts to be.
Within ApacheDS you will likely want to authenticate clients in order to check whether they are allowed to read, add or manipulate certain data stored within the directory. The latter, i.e. whether an authenticated client is permitted to do something, is deduced during authorization.
Quite often, the process of authentication is delegated to a directory service by other software components.

Because in doing so, authentication data (e.g. username, password) and authorization data (e.g. group relationships) are stored and managed centrally in the directory, and all connected software solutions benefit from it.

Authentication in LDAP

Different versions of the LDAP support different types of authentication. The LDAP v2 defines three types of authentication: anonymous, simple (clear-text password), and Kerberos v4.
The LDAP v3 supports anonymous, simple, and SASL authentication. SASL is the Simple Authentication and Security Layer (RFC 2222). It specifies a challenge-response protocol in which data is exchanged between the client and the server for the purposes of authentication and establishment of a security layer on which to carry out subsequent communication. By using SASL, the LDAP can support any type of authentication agreed upon by the LDAP client and server.

This lesson contains descriptions of how to authenticate by using anonymous, simple, and SASL authentication.

Specifying the Authentication Mechanism

The authentication mechanism is specified by using the Context.SECURITY_AUTHENTICATION environment property. The property may have one of the following values.

sasl_mech    A space-separated list of SASL mechanism names. Use one of the SASL mechanisms listed                        (e.g., "CRAM-MD5" means to use the CRAM-MD5 SASL mechanism described in RFC 2195).
none            Use no authentication (anonymous)
simple         Use weak authentication (clear-text password)

The Default Mechanism

If the client does not specify any authentication environment properties, then the default authentication mechanism is "none". The client will then be treated as an anonymous client.

Anonymous Authentication

As just stated, the default authentication mechanism is "none" if no authentication environment properties have been set.
To explicitly set it
// Use anonymous authentication
env.put(Context.SECURITY_AUTHENTICATION, "none");

Simple Authentication

Authentication via simple bind is widely used. The method is supported by ApacheDS 2.0 for all person entries stored within any partition, if they contain a password attribute.

How does it work?

An LDAP client provides the DN of a user entry and a password to the server, the parameters of the bind operation. ApacheDS checks whether the given password is the same as the one stored in the userpassword attribute of the given entry. If not, the bind operation fails (LDAP error code 49, LDAP_INVALID_CREDENTIALS), and the user is not authenticated.

try {
 //In the main() method of the program, create an initial directory context. 
 //This is similar to creating an initial context in the previous naming example, 
 //except that you use the constructor for InitialDirContext
 Hashtable env = new Hashtable();
 env.put(Context.INITIAL_CONTEXT_FACTORY,
 "com.sun.jndi.ldap.LdapCtxFactory");
 env.put(Context.PROVIDER_URL, "ldap://localhost:10389/o=csRepository");
 env.put(Context.SECURITY_AUTHENTICATION, "simple");
 env.put(Context.SECURITY_PRINCIPAL, "cn=John Eipe, ou=employees, o=csRepository");
 env.put(Context.SECURITY_CREDENTIALS, "qwer1234");

 // Create the initial context
 DirContext ctx = new InitialDirContext(env);   
 NamingEnumeration enm = ctx.list("ou=employees");
 while (enm.hasMore()) {
  System.out.println(enm.next());
 }
 enm.close();
 ctx.close();
}catch(NamingException e){
 e.printStackTrace();
}

Note that not supplying the password or both will still authenticate you but providing a wrong username or password will throw javax.naming.AuthenticationException. Read my answer here


Using Different Authentication Information for a Context

If you want to use different authentication information for an existing context, then you can use Context.addToEnvironment() and Context.removeFromEnvironment() to update the environment properties that contain the authentication information. Subsequent invocations of methods on the context will use the new authentication information to communicate with the server.
The following example shows how the authentication information of a context is changed to "none" after the context has been created.

.....
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, " cn=John Eipe, ou=employees, o=csRepository");
env.put(Context.SECURITY_CREDENTIALS, "qwre1234");
// Create the initial context
DirContext ctx = new InitialDirContext(env);

// ... do something useful with ctx
// Change to using no authentication
ctx.addToEnvironment(Context.SECURITY_AUTHENTICATION, "none");
// ... do something useful with ctx


What is authorization?

After authentication of a user or an application (or more generally an LDAP client) against the directory server (or attaining anonymous access respectively), certain LDAP operations will be granted or rejected, according to configuration and certain rules. This process of granting access is called authorization.

Authorization for directory operations is not strictly standardized in the LDAP world, RFC 2829 - Authentication Methods for LDAPdescribes various scenarios and concepts, but does not enforce a concrete implementation. Thus each product comes with its own authorization feature. So does ApacheDS. A powerful authorization subsystem is provided since version 0.9.3, but disabled as a default.

Group membership

In order to accomplish their authorization functionality, software components often take advantage of LDAP groups stored within the directory. groupOfNames and groupOfUniqueNames are common object classes for groups entries; they contain the DNs of their members (users, other groups) as attribute values.

Here is something important.

Without access controls enabled all entries are accessible and alterable by all: even anonymous users.
There are however some minimal built-in rules for protecting users and groups within the server without having to turn on the ACI subsystem.


  1. Users cannot see other user entries under the 'ou=users,ou=system' entry. So placing new users there automatically protects them. Placing new users anywhere else exposes them.
  2. Groups defined using groupOfNames or groupOfUniqueNames under the 'ou=groups,ou=system' are also protected from access or alteration by anyone other than the admin user. Again this protection is not allowed anywhere else but under these entries.


But for advanced configurations we need to enable the ACI subsystem. This however shuts down access to everything by everyone except the admin user which bypasses the ACI subsystem.
More about ACI for ApacheDS here


SASL Authentication

SASL means Simple Authentication and Security Layer. It extends the Simple authentication, by allowing the LDAP server to authenticate the user by various mechanisms.

The LDAP v3 protocol uses the SASL to support pluggable authentication. This means that the LDAP client and server can be configured to negotiate and use possibly nonstandard and/or customized mechanisms for authentication, depending on the level of protection desired by the client and the server. The LDAP v2 protocol does not support the SASL.

Several SASL mechanisms are currently defined:

  • "EXTERNAL", where authentication is implicit in the context (e.g., for protocols already using IPsec or TLS)
  • "ANONYMOUS", for unauthenticated guest access
  • "PLAIN", a simple cleartext password mechanism.
  • "OTP", a one-time password mechanism. OTP obsoleted the SKEY Mechanism.
  • "SKEY", an S/KEY mechanism.
  • "CRAM-MD5", a simple challenge-response scheme based on HMAC-MD5.
  • "DIGEST-MD5", partially HTTP Digest compatible challenge-response scheme based upon MD5. DIGEST-MD5 offered a data security layer.
  • "SCRAM" (RFC 5802), modern challenge-response scheme based mechanism with channel binding support
  • "NTLM", an NT LAN Manager authentication mechanism 
  • "GSSAPI", for Kerberos V5 authentication via the GSSAPI. GSSAPI offers a data-security layer.
  • "BROWSERID-AES128", for Mozilla Persona authentication
  • "EAP-AES128", for GSS EAP authentication
  • GateKeeper (& GateKeeperPassport), a challenge-response mechanism developed by Microsoft for MSN Chat

To view the full list of SASL mechanisms check iana.org/sasl

SASL Mechanisms Supported by LDAP Servers

Most of the existing SASL mechanisms are just either useless (PLAIN, ANONYMOUS) or too weak (DIGEST-MD5 or CRAM-MD5) to be used in a secured environment.

Suggested SASL mechanisms are GSSand SCRAM.


Here is a simple program for finding out the list of SASL mechanisms that an LDAP server supports.
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
 "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:10389/o=csRepository");
DirContext ctx = new InitialDirContext(env);
// Read supportedSASLMechanisms from root DSE
Attributes attrs = ctx.getAttributes("ldap://localhost:10389", new String[]{"supportedSASLMechanisms"});
System.out.println(attrs);

Output:
{supportedsaslmechanisms=supportedSASLMechanisms: NTLM, DIGEST-MD5, GSS-SPNEGO, GSSAPI, SIMPLE, CRAM-MD5}

Specifying the Authentication Mechanism

To use a particular SASL mechanism, you specify its Internet Assigned Numbers Authority (IANA)-registered mechanism name in the Context.SECURITY_AUTHENTICATION environment property. You can also specify a list of mechanisms for the LDAP provider to try. This is done by specifying an ordered list of space-separated mechanism names. The LDAP provider will use the first mechanism for which it finds an implementation.

Here's an example that asks the LDAP provider to try to get the implementation for the DIGEST-MD5 mechanism and if that's not available, use the one for GSSAPI.
env.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5 GSSAPI");
You might get this list of authentication mechanisms from the user of your application. Or you might get it by asking the LDAP server, via a call similar to that shown previously.

The LDAP service provider that comes with JDK 1.7 has built-in support for the Plain, External, Digest-MD5, CRAM-MD5 and GSSAPI (Kerberos v5) SASL mechanisms.


Using Policies to Filter the Selection of Authentication Mechanisms

The previous example that showed how to select an authentication mechanism can be refined by specifying policies that restrict the selection of authentication mechanisms. This can be used by an application or system to specify general characteristics of the acceptable authentication mechanisms without explicitly naming them, and allows the list of explicit mechanism names to be supplied orthogonally.

Here is a list of environment properties used to filter the selection of authentication mechanisms. Each property's value is either "true" or "false". If a property is absent, then the resulting mechanism need not have that characteristic (that is, the value is effectively "false").


  1. javax.security.sasl.policy.forward
    Specifies that the selected SASL mechanism must support forward secrecy between sessions. This means that breaking into one session will not automatically provide information for breaking into future sessions.
  2. javax.security.sasl.policy.credentials
    Specifies that the selected SASL mechanism must require client credentials.
  3. javax.security.sasl.policy.noplaintext
    Specifies that the selected SASL mechanism must not be susceptible to simple plain passive attacks.
  4. javax.security.sasl.policy.noactive
    Specifies that the selected SASL mechanism must not be susceptible to active (non-dictionary) attacks. The mechanism might require mutual authentication as a way to prevent active attacks.
  5. javax.security.sasl.policy.nodictionary
    Specifies that the selected SASL mechanism must not be susceptible to passive dictionary attacks.
  6. javax.security.sasl.policy.noanonymous
    Specifies that the selected SASL mechanism must not accept anonymous logins.

Here is a table that shows the characteristics of the various SASL mechanisms as described by the policy properties. The numbers in the table headings identify the policy properties. A check mark indicates that the mechanism exhibits that characteristic.

Here is a modification of the previous example.
env.put("javax.security.sasl.policy.noactive", "true");
env.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5 GSSAPI");
By adding the policy environment property, the DIGEST-MD5 mechanism will not be selected even if its implementation is available because the "javax.security.sasl.policy.noactive" property prohibits it from being selected.

Mechanism/Policy 1 2 3 4 5 6
EXTERNAL
GSSAPI (Kerberos v5)
DIGEST-MD5
CRAM-MD5
PLAIN
ANONYMOUS

Here is a modification of the previous example.

env.put("javax.security.sasl.policy.noactive", "true");
env.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5 GSSAPI");
By adding the policy environment property, the DIGEST-MD5 mechanism will not be selected even if its implementation is available because the "javax.security.sasl.policy.noactive" property prohibits it from being selected.

Specifying the "Bind" Distinguished Name

SASL authentication consists of the client and the server exchanging SASL messages embedded inside LDAP "bind" requests and responses. The "bind" request contains a name field, which is the DN of the directory object that the client wishes to authenticate as. For SASL authentication, the authentication identity, which might not even be a DN, is typically embedded within the credentials that are exchanged with the server. The name field is therefore left unset for SASL authentication.

Specifying Input for the Authentication Mechanism

Some mechanisms, such as External, require no additional input--the mechanism name alone is sufficient for the authentication to proceed.
Most other mechanisms require some additional input. Depending on the mechanism, the type of input might vary. Following are some common inputs required by mechanisms.
Authentication id: The identity of the entity performing the authentication.
Authorization id : The identity of the entity for which access control checks should be made if the authentication succeeds.
Authentication credentials: For example, a password or a key.

The authentication and authorization ids might differ if the program (such as a proxy server) is authenticating on behalf of another entity. The authentication id is specified by using the Context.SECURITY_PRINCIPAL environment property. It is of type java.lang.String.
The password/key of the authentication id is specified by using the Context.SECURITY_CREDENTIALS environment property. It is of type java.lang.String, char array (char[]), or byte array (byte[]). If the password is a byte array, then it is transformed into a char array by using an UTF-8 encoding.
If the "java.naming.security.sasl.authorizationId" property has been set, then its value is used as the authorization ID. Its value must be of type java.lang.String. By default, the empty string is used as the authorization ID, which directs the server to derive an authorization ID from the client's authentication credentials.

Specifying the Quality of Protection

In additional to authentication, some SASL mechanisms support integrity and privacy protection of the communication channel after successful authentication. With integrity protection, subsequent LDAP requests and responses are protected against tampering. With privacy protection, subsequent LDAP requests and responses are encrypted and therefore protected against unintended monitoring. Privacy protection automatically entails integrity protection. These different types of protection are referred to as the quality of protection (qop). It is negotiated between the client and server during the authentication phase of the SASL exchange. If the client and server cannot negotiate a common qop, then the SASL authentication fails.

You use the "javax.security.sasl.qop" environment property to specify the client's preferred qop. The value of this property is a comma-separated list of qop values, the order of which specifies the preference order. There are three possible qop values, as listed in the following table.

Token Description

auth

Authentication only

auth-int

Authentication with integrity protection

auth-conf

Authentication with integrity and privacy protection

If you do not specify this property, it defaults to "auth".

Specifying the Encryption Strength for Privacy Protection

Some SASL mechanisms support the use of different privacy protection strengths--that is, different ciphers and key lengths used for encryption. The protection strength determines how easily the encryption code can be cracked. The Java SASL API broadly categorizes privacy protection strengths into low, medium, and high. The mapping of these categories into specific ciphers and key lengths are SASL mechanism-specific. The ciphers, key lengths or other means of strength specification are negotiated between the client and server during the authentication phase of the SASL exchange. If the client and server cannot negotiate a common strength, then the SASL authentication fails.

You use the "javax.security.sasl.strength" environment property to specify the client's preferred privacy protection strength. The value of this property is a comma-separated list of strength values, the order of which specifies the preference order. The three possible strength values are "low", "medium", and "high". If you do not specify this property, then it defaults to "high,medium,low". This property is ignored by SASL mechanisms that do not support privacy protection.

Specifying the Maximum Receive Buffer Size

If a client is using a SASL mechanism that supports integrity or privacy protection, then it must negotiate with the server their respective receive buffer sizes.
You use the "javax.security.sasl.maxbuffer" environment property to specify the client's maximum receive buffer size. The value of this property is the string representation of an integer that specifies the maximum size of the receive buffer in bytes. If you do not specify this property, it defaults to a SASL mechanism-specific size. This property is ignored by SASL mechanisms that do not support integrity or privacy protection.

Specifying Mutual Authentication

When you think of authentication, you typically think of the process by which you verify your identity to the LDAP server. For some applications, it is equally important that the LDAP server's identity be verified. The process by which both parties participating in the exchange authenticate each other is referred to as mutual authentication.
You use the "javax.security.sasl.server.authentication" environment property to indicate that you want mutual authentication. The value of this property is either "true" or "false".

Digest-MD5 Authentication

It is based on the HTTP Digest Authentication. In Digest-MD5, the LDAP server sends data that includes various authentication options that it is willing to support plus a special token to the LDAP client. The client responds by sending an encrypted response that indicates the authentication options that it has selected. The response is encrypted in such a way that proves that the client knows its password. The LDAP server then decrypts and verifies the client's response.

Changing the security authentication alone will not suffice.

env.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5");
env.put(Context.SECURITY_PRINCIPAL, "cn=John Eipe, ou=employees, o=csRepository");
env.put(Context.SECURITY_CREDENTIALS, "qwer1234");

You will be welcomed by
INVALID_CREDENTIALS: DIGEST-MD5: digest response format violation. Mismatched URI: ldap/localhost; expecting: ldap/ldap.example.com]

Change the password to use MD5.


If you are using Kerberos server then you need to add realm.

A realm defines the namespace from which the authentication entity (the value of the Context.SECURITY_PRINCIPAL property) is selected. A server might have multiple realms.
In Digest-MD5 authentication, you must authenticate to a specific realm. You may use the following authentication environment property to specify the realm.
env.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5");
env.put(Context.SECURITY_PRINCIPAL, "cn=John Eipe, ou=employees, o=csRepository");
env.put(Context.SECURITY_CREDENTIALS, "qwer1234");
env.put("java.naming.security.sasl.realm", "example.com");
example.com is the default realm created in ApacheDS.



Specifying Quality of protection (QOP)

The Digest-MD5 SASL mechanism also supports the establishment of a negotiated security layer after successful authentication. The security layer can perform integrity and privacy protection. The security layer is specified by the quality of protection (qop), which is negotiated with the server during authentication. You specify the qops that your application can tolerate, listing the most desirable qop first.
env.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5");
env.put(Context.SECURITY_PRINCIPAL, "cn=John Eipe, ou=employees, o=csRepository");
env.put(Context.SECURITY_CREDENTIALS, "qwer1234");
env.put("java.naming.security.sasl.realm", "example.com");

// Request integrity protection
env.put("javax.security.sasl.qop", "auth-int");

Digest-MD5 supports five different ciphers for privacy protection. The cipher selected is negotiated between the client and server during authentication. These five ciphers are mapped to the "high", "medium", and "low" settings defined for the"javax.security.sasl.strength" environment property. Here is a table that lists the ciphers, their mappings and descriptions.

Cipher QOP Mapping Description
RC4 (40 bit) low
The RC4 cipher with 40 bit key.
RC4 (56 bit) medium
The RC4 cipher with 56 bit key.
RC4 (128 bit) high
The RC4 cipher with 128 bit key.
DES medium
The Data Encryption Standard (DES) cipher in cipher
block chaining (CBC) mode with a 56 bit key.
Triple DES high
The "triple DES" cipher in CBC mode with EDE with the same key
for each E stage (aka "two keys mode") for a total key length
of 112 bits.

Links and references used:
GSS: http://docs.oracle.com/javase/jndi/tutorial/ldap/security/gssapi.html
SASL: https://directory.apache.org/apacheds/advanced-ug/4.1.2-sasl-authn.html
SASL Guide: http://docs.oracle.com/javase/7/docs/technotes/guides/security/sasl/sasl-refguide.html
SSL vs SASL: http://stackoverflow.com/questions/11347304/security-authentication-ssl-vs-sasl

http://www.zytrax.com/books/ldap/
http://docs.oracle.com/javase/tutorial/jndi/ldap/authentication.html
http://docs.oracle.com/javase/tutorial/jndi/ldap/jndi.html
http://publib.boulder.ibm.com/tividd/td/IBMDS/guide322/en_US/HTML/Guide.html
https://today.java.net/pub/a/today/2006/04/18/ldaptemplate-java-ldap-made-simple.html
http://www.javaworld.com/article/2076073/java-web-development/ldap-and-jndi--together-forever.html?page=3
http://svn.apache.org/repos/asf/directory/apacheds/trunk/core-integ/src/test/java/org/apache/directory/server/core/jndi/
http://directory.apache.org/apacheds/basic-ug/2.3-introducing-schema.html

1 comment:

  1. This comment has been removed by a blog administrator.

    ReplyDelete