Make Spring LDAP handle Proxy-Auth extended control

The RFC 4370 defines an extended LDAP control to enable a proxy authorisation, so that a user can be able to execute operation with the right of an other user.

Be careful, this controle DOES NOT deal with authentication, it is on the application realm.

Spring LDAP is an API that handle all the burden of JNDI to deals with the real concern of LDAP management.

We all are waiting for a real LDAP extension for the Java API (hope reborns, but meantime, Spring-LDAP is a really good choice. And of course, it complies well with other Spring components.

Creating an LDAP control in Spring LDAP

The first task is to create an extended control for Spring LDAP. This is done by extending AbstractRequestControlDirContextProcessor, as explain in Spring LDAP : Implementing a Request Control DirContextProcessor

Our implementation is really simple, we just have to specify the OID of our control ("2.16.840.1.113730.3.4.18"), and override the createRequestControl() method :

private static final String LDAP_PROXY_AUTHZ_CONTROL_OID = "2.16.840.1.113730.3.4.18";
@Override
public Control createRequestControl() {
  return new BasicControl(LDAP_PROXY_AUTHZ_CONTROL_OID, true, ("dn: " + dn).getBytes());
}

Full code of ProxyAuthz.java

Using Proxy Auth control by default in an LdapContextSource

Second task is to let a ContextSource use our control by default. The idea is that we use a pool of connection initiated with an unique user devolves for that task, and that when we need a connection for an authenticated user, we take a connection from the pool and just “proxy-fied” it for all request. So, we extend LdapContextSource to pass the control to each request:

@Override
public DirContext getReadOnlyContext() {
  DirContext ctx = super.getReadOnlyContext();
  addProxyAutzControl(ctx);
  return ctx;
}

@Override public DirContext getReadWriteContext() { DirContext ctx = super.getReadWriteContext(); addProxyAutzControl(ctx); return ctx; }

private void addProxyAutzControl(DirContext ctx) { if(proxyEnabled && null != this.proxyDn) { ProxyAuthz proxyControle = new ProxyAuthz(this.proxyDn); try { proxyControle.preProcess(ctx); } catch (NamingException e) { if (ctx != null) { try { ctx.close(); } catch (Exception ex) { } } throw getExceptionTranslator().translate(e); } } }

Full code of ProxyAuthzContextSource.java

Really simple :)

The Spring application context is exactly the same as for a normal LdapContextSource. And when you want to use the proxy control, just set proxyEnabled to true, and proxyDn to the DN to use as proxied user.