Skip to content

Commit

Permalink
implemented LDAP authentication with configurable settings
Browse files Browse the repository at this point in the history
  • Loading branch information
timander committed Aug 17, 2009
1 parent 8f40aa0 commit ca841f6
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 16 deletions.
6 changes: 5 additions & 1 deletion README
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ To use:

1. Add the ldap-authentation-${version}.jar to the lib folder of your FitNesse server

2. Add the following line to your plugins.properties
2. Add the following line to the plugins.properties of the FitNesse server
Authenticator=fitnesse.authentication.LDAPAuthenticator
ldap.server.url=ldap://ldap.example.com:389
ldap.search.base=ou=People,dc=example,dc=com
ldap.username.attribute=AccountName

3. Start the FitNesse server with
java -cp "lib/ldap-authentation-${version}.jar:fitnesse.jar" fitnesseMain.FitNesseMain [optional args]
(NOTE Windows users should use ; for the classpath seperator)

31 changes: 22 additions & 9 deletions src/main/java/fitnesse/authentication/LDAPAuthenticator.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package fitnesse.authentication;

import com.sun.jndi.ldap.LdapCtxFactory;
import javax.naming.AuthenticationException;
import javax.naming.Context;
import javax.naming.NamingException;
Expand All @@ -19,22 +20,26 @@ public LDAPAuthenticator(Properties properties) {
this.properties = properties;
}

@SuppressWarnings({"UseOfObsoleteCollectionType", "unchecked", "RawUseOfParameterizedType"})
@SuppressWarnings({"UseOfObsoleteCollectionType", "unchecked", "RawUseOfParameterizedType", "CallToPrintStackTrace"})
@Override
public boolean isAuthenticated(String username, String password) throws Exception {
if (username == null || password == null) {
return false;
}

Hashtable authEnv = new Hashtable(11);
String base = "ou=People,dc=example,dc=com";
String dn = "uid=" + username + "," + base;
String ldapURL = "ldap://ldap.example.com:389";
String searchBase = getProperty("ldap.search.base");
String ldapURL = getProperty("ldap.server.url") + "/" + searchBase;
String usernameAttribute = getProperty("ldap.username.attribute");
String principal = usernameAttribute + "=" + username + "," + searchBase + "?" + usernameAttribute + "?sub?(objectClass=*)";

System.out.println("LDAPAuthenticator.isAuthenticated");
System.out.println("principal = " + principal);

authEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
Hashtable authEnv = new Hashtable(11);
authEnv.put(Context.INITIAL_CONTEXT_FACTORY, LdapCtxFactory.class.getName());
authEnv.put(Context.PROVIDER_URL, ldapURL);
authEnv.put(Context.SECURITY_AUTHENTICATION, "simple");
authEnv.put(Context.SECURITY_PRINCIPAL, dn);
authEnv.put(Context.SECURITY_PRINCIPAL, principal);
authEnv.put(Context.SECURITY_CREDENTIALS, password);

try {
Expand All @@ -43,15 +48,23 @@ public boolean isAuthenticated(String username, String password) throws Exceptio
}
catch (AuthenticationException ae) {
ae.printStackTrace();
//throw new RuntimeException("Authentication failed!", ae);
}
catch (NamingException ne) {
//throw new RuntimeException("Something went wrong!", ne);
ne.printStackTrace();
}

return false;
}

private String getProperty(String key) {
if (properties.getProperty(key) == null) {
System.out.println("Property not found [" + key + "] in plugins.properties");
return "";
}
else {
return properties.getProperty(key);
}
}

}

59 changes: 53 additions & 6 deletions src/test/java/fitnesse/authentication/LDAPAuthenticatorTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,52 +4,99 @@
import org.mockito.Matchers;
import static org.mockito.Mockito.*;
import javax.naming.AuthenticationException;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import java.util.Hashtable;
import java.util.Properties;


@SuppressWarnings({"UseOfObsoleteCollectionType", "RawUseOfParameterizedType", "ThrowableInstanceNeverThrown"})
public class LDAPAuthenticatorTest extends TestCase {

private LDAPAuthenticator authenticator;

@Override
protected void setUp() throws Exception {
super.setUp();
Properties properties = new Properties();
properties.setProperty("ldap.search.base", "ou=People,dc=example,dc=com");
properties.setProperty("ldap.server.url", "ldap://ldap.example.com:389");
properties.setProperty("ldap.username.attribute", "AccountName");
authenticator = new LDAPAuthenticator(properties);
}

public void testNullUsername() throws Exception {
LDAPAuthenticator authenticator = new LDAPAuthenticator(null);
assertFalse(authenticator.isAuthenticated(null, "password"));
}

public void testNullPassword() throws Exception {
LDAPAuthenticator authenticator = new LDAPAuthenticator(null);
assertFalse(authenticator.isAuthenticated("username", null));
}

public void testNullUsernameAndPassword() throws Exception {
LDAPAuthenticator authenticator = new LDAPAuthenticator(null);
assertFalse(authenticator.isAuthenticated(null, null));
}

public void testNullProperties() throws Exception {
assertFalse(authenticator.isAuthenticated("username", "password"));
}

@SuppressWarnings({"UseOfPropertiesAsHashtable"})
public void testMissingProperties() throws Exception {
Properties propertiesWithMissingKeys = new Properties();
propertiesWithMissingKeys.setProperty("ldap.search.base", "search base");
assertNull(propertiesWithMissingKeys.get("ldap.server.url"));
authenticator.properties = propertiesWithMissingKeys;
assertFalse(authenticator.isAuthenticated("username", "password"));
}

@SuppressWarnings({"JNDIResourceOpenedButNotSafelyClosed"})
public void testAuthenticated() throws Exception {
LDAPAuthenticator authenticator = new LDAPAuthenticator(null);
InitialDirContextFactory mockFactory = mock(InitialDirContextFactory.class);
when(mockFactory.create(Matchers.isA(Hashtable.class))).thenReturn(new InitialDirContext());
authenticator.initialDirContextFactory = mockFactory;
assertTrue(authenticator.isAuthenticated("username", "password"));
}

public void testAuthenticationFailed_NamingException() throws Exception {
LDAPAuthenticator authenticator = new LDAPAuthenticator(null);
InitialDirContextFactory mockFactory = mock(InitialDirContextFactory.class);
when(mockFactory.create(Matchers.isA(Hashtable.class))).thenThrow(new NamingException());
assertFalse(authenticator.isAuthenticated("username", "password"));
}

public void testAuthenticationFailed_AuthenticationException() throws Exception {
LDAPAuthenticator authenticator = new LDAPAuthenticator(null);
InitialDirContextFactory mockFactory = mock(InitialDirContextFactory.class);
when(mockFactory.create(Matchers.isA(Hashtable.class))).thenThrow(new AuthenticationException());
authenticator.initialDirContextFactory = mockFactory;
assertFalse(authenticator.isAuthenticated("username", "password"));
}

public void testSecurityContextPrincipal() throws Exception {
CollaboratingFactory collaboratingFactory = new CollaboratingFactory();
authenticator.initialDirContextFactory = collaboratingFactory;
authenticator.isAuthenticated("username", "password");
assertEquals("AccountName=username,ou=People,dc=example,dc=com?AccountName?sub?(objectClass=*)", collaboratingFactory.get(Context.SECURITY_PRINCIPAL));
assertEquals("ldap://ldap.example.com:389/ou=People,dc=example,dc=com", collaboratingFactory.get(Context.PROVIDER_URL));
assertEquals("simple", collaboratingFactory.get(Context.SECURITY_AUTHENTICATION));
assertEquals("password", collaboratingFactory.get(Context.SECURITY_CREDENTIALS));
assertEquals("com.sun.jndi.ldap.LdapCtxFactory", collaboratingFactory.get(Context.INITIAL_CONTEXT_FACTORY));
}

private static class CollaboratingFactory extends InitialDirContextFactory {

public String get(String key) {
return (String) hashtable.get(key);
}

public Hashtable hashtable;

@SuppressWarnings({"AssignmentToCollectionOrArrayFieldFromParameter"})
@Override
public DirContext create(Hashtable env) throws NamingException {
hashtable = env;
return super.create(env);
}
}
}

0 comments on commit ca841f6

Please sign in to comment.