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 DirContextProcessorOur 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.javaReally 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.