Saturday, July 23, 2011

How to use JAAS to authenticate users on an LDAP directory

This article cover all JAAS authentication concept by describing a sample JAVA application "" to authenticate a user on an LDAP directory using JAAS.

So to authenticate your LDAP users using the SampleLDAPLogin application, the following steps are performed:
  1. The application instantiates a LoginContext.
  2. The LoginContext consults a Configuration (described in the sample_jaas_ldap.config login configuration file) to load the LdapLoginModule which is a LoginModule performing LDAP-based authentication.
  3. The application invokes the LoginContext's login method.
  4. The login method invokes the loaded LoginModule (LdapLoginModule) which attempt to authenticate the user against the corresponding user credentials stored in the openLDAP directory. The LdapLoginModule module requires the supplied CallbackHandler ( to support a NameCallback and a PasswordCallback.
  5. The LoginContext returns the authentication status to the application.
  6. 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 example consists of three files:,, sample_jaas_ldap.config

The SampleLDAPLogin Class

public class SampleLDAPLogin {
public static void main(String[] args) {
LoginContext lc = null;
try {
lc = new LoginContext("SampleLDAPConfiguration", new SampleCallbackHandler());
} catch (LoginException le) {
System.err.println("Cannot create LoginContext. " + le.getMessage());
} catch (SecurityException se) {
System.err.println("Cannot create LoginContext. " + se.getMessage());
try {
// attempt authentication
System.out.println("Authentication succeeded!");
} catch (LoginException le) {
System.err.println("Authentication failed:\n" + le.getMessage());

The code for authenticating consist of just two steps:
  • Instantiate a LoginContext with two arguments :

    lc = new LoginContext("SampleLDAPConfiguration", new SampleCallbackHandler());
  1. SampleLDAPConfiguration: The name of the entry in the JAAS login configuration file (sample_jaas_ldap.config)
  2. new SampleCallbackHandler(): A CallbackHandler instance
  • Call the LoginContext's login method: lc.login();

The SampleCallbackHandler Class

public class SampleCallbackHandler implements CallbackHandler {
public void handle(Callback[] callbacks)
throws IOException, UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof NameCallback) {
// prompt the user for a username
NameCallback nc = (NameCallback)callbacks[i];
nc.setName((new BufferedReader
(new InputStreamReader(;
} else if (callbacks[i] instanceof PasswordCallback) {
// prompt the user for sensitive information
PasswordCallback pc = (PasswordCallback)callbacks[i];
} else {
throw new UnsupportedCallbackException
(callbacks[i], "Unrecognized Callback");
// Reads user password from given input stream.
private char[] readPassword(InputStream in) throws IOException {
char[] lineBuffer;
char[] buf;
int i;
buf = lineBuffer = new char[128];
int room = buf.length;
int offset = 0;
int c;
loop: while (true) {
switch (c = {
case -1:
case '\n':
break loop;
case '\r':
int c2 =;
if ((c2 != '\n') && (c2 != -1)) {
if (!(in instanceof PushbackInputStream)) {
in = new PushbackInputStream(in);
} else
break loop;
if (--room < 0) {
buf = new char[offset + 128];
room = buf.length - offset - 1;
System.arraycopy(lineBuffer, 0, buf, 0, offset);
Arrays.fill(lineBuffer, ' ');
lineBuffer = buf;
buf[offset++] = (char) c;
if (offset == 0) {
return null;
char[] ret = new char[offset];
System.arraycopy(buf, 0, ret, 0, offset);
Arrays.fill(buf, ' ');
return ret;

In some cases a LoginModule (in our case:LdapLoginModule) must communicate with the user to obtain authentication information.

SampleCallbackHandler handles two types of Callbacks: NameCallback to prompt the user for a user name and PasswordCallback to prompt the user for a password.

The sample_jaas_ldap.config (login configuration file)

SampleLDAPConfiguration{ REQUIRED







This entry is named "SampleLDAPConfiguration" and that is the name that our sample application, SampleLDAPLogin, uses to refer to this entry. The entry specifies that the LoginModule to be used to do the user authentication is the "" and that this LdapLoginModule is required to "succeed" in order for authentication to be considered successful. The LdapLoginModule succeeds only if the name and password supplied by the user are the one it expects in the DN (Distinguished Name) openLDAP directory "ldap://ip_adress:ldap_port/ou=users,dc=blogDomain,dc=badr,dc=org"

Depending on ther user/password entred You wil get different message in your console from LdapLoginModule using the TextOutputCallback !

Saturday, July 9, 2011

How to read arabic message from ressource bundles with JSF

In this article we assume that you already have an idea about configuring ressource bundles in JSF, how to use it in your pages and also how to configure jsf pages encoding ...

This blog entry is realy independante from JSF version, and it works for both JSF1 and JSF2 ;-)

We suppose that you want to write "Arabic" like "loginBean.username.label = اسم المستخدم " in the message resource bundle (properties) file and you try to save it you will get this error:
"Save couldn't be completed Some characters cannot be mapped using "ISO-85591-1" character encoding. Either change encoding or remove the character ..." because the default mechanism loading of properties files is in "ISO-8559-1-1".

If you change the file encoding to UTF-8, you will be able to save the file but you can not print your messages correctly in JSF !!

To get it work you have to change the default mechanism loading to UTF-8 by implementing a custom ressource bundle class using UTF-8 Control

public class I18nRessourceBundle extends ResourceBundle {

protected static final String BUNDLE_EXTENSION = "properties";
protected static final String CHARSET = "UTF-8";
public static final Control UTF8_CONTROL = new UTF8Control();

public I18nRessourceBundle() {
FacesContext.getCurrentInstance().getViewRoot().getLocale(), UTF8_CONTROL));

protected Object handleGetObject(String key) {
return parent.getObject(key);

public Enumeration getKeys() {
return parent.getKeys();

public static class UTF8Control extends Control {
public ResourceBundle newBundle
(String baseName, Locale locale, String format, ClassLoader loader, boolean reload)
throws IllegalAccessException, InstantiationException, IOException
// The below code is copied from default Control#newBundle() implementation.
// Only the PropertyResourceBundle line is changed to read the file as UTF-8.

String bundleName = toBundleName(baseName, locale);
String resourceName = toResourceName(bundleName, BUNDLE_EXTENSION);
ResourceBundle bundle = null;
InputStream stream = null;
if (reload) {
URL url = loader.getResource(resourceName);
if (url != null) {
URLConnection connection = url.openConnection();
if (connection != null) {
stream = connection.getInputStream();
} else {
stream = loader.getResourceAsStream(resourceName);
if (stream != null) {
try {
bundle = new PropertyResourceBundle(new InputStreamReader(stream, CHARSET));
} finally {
return bundle;

We assume that you have a properties file Propety_File_Ressource in your ressource folder

So in JSF configuration you should use:



Insted of



Enjoy it!