In enterprises, LDAP servers are often used to store user credentials and groups and share them among applications. Oracle SOA Suite 12c introduces a new technology adapter; the LDAPAdapter which allows easy integration with LDAP servers. In this blog post I will provide a quick and easy howto on installation of an LDAP server and browser (ApacheDS and Apache Directory Studio). I will also describe the configuration required to use the LDAPAdapter and provide an example BPEL process which allows creation of new users in the ApacheDS LDAP server by means of webservice calls.
Setting up the LDAP server
Installing an LDAP server
For this example I’ll use ApacheDS as LDAP server and Apache Directory Studio as LDAP browser. First download and install Apache Directory Studio from http://directory.apache.org/studio/. Next create an LDAP server. Click the LDAP server tab in the bottom left corner and click New Server.
Select ApacheDS 2.0.0 and click finish.
Now you can start the server by selecting it and clicking the green play button.
Create a connection to the LDAP server
Next to the LDAP Servers tab, there is a Connections tab. Create a new connection. Use localhost and port 10389.
Click Next and fill in the following credentials: Bind DN or User: uid=admin,ou=system and Bind password: secret.
You can now connect to your newly created server and browse it.
Configuring Weblogic
Target the adapter
In Weblogic Server you need to configure a connection factory in the adapter configuration. First login to Weblogic console and click on the LdapAdapter.
The adapter is by default not targeted. You should specify a target if you want to use it. In my case (JDeveloper integrated Weblogic server) only one target can be selected: DefaultServer. Set the target and save.
This is required in order to access the connection factories provided by the adapter and for example browse for them in JDeveloper.
Configure the connection factory
Go to the configuration of the LdapAdapter, Outbound Connection Pools.
I decided to configure eis/ldap/master. Click on that and provide the required settings (see screenshot).
The first time when configuring a connection factory for an adapter, Weblogic asks for the name of the configuration plan to use. It’s a good practice to use a name which makes clear for which adapter the configuration is (or put it in a separate directory per adapter). For example PlanLdap.xml.
After the configuration is complete, restart the server. The LdapAdapter cannot be updated like the DbAdapter. It is more similar to the BamAdapter in behavior. The adapter is deployed upon server start. Upon deployment, a configuration change is applied.
JDeveloper
Configuring the LdapAdapter
Create an application, create an empty project with a synchronous BPEL 2.0 process. In the composite editor, drag the new LDAP adapter to the References lane to start configuring. The default password is still secret.
Using the browse button (magnifying glass after the JNDI Name field). You can select the eis/ldap/master. If you can’t, you forgot to target the adapter.
Choose ‘Add’ as the outbound operation. Use the following classes: inetOrgPerson and person. Use uid, userPassword as fields.
Now you can Next, Finish to the end of the wizard and fill in details of the BPEL process calling the LDAP Server.
Seeing it work
I’ve created a small BPEL process which calls the adapter. Since it’s relatively easy I will not provide screenshots for it. Mind the following though: the userPassword should be at least 5 characters and should not contain the username. I’ve chosen ‘Welcome01’ for this. The dn should be as can be seen in the below screenshot example. You can create it by means of concatenation. Using the Test Webservice screen from Fusion Middleware Control, we can see my service can successfully call the LDAP server.
In Apache Directory Studio you can confirm the user actually has been created.
Check to see if a user is actually created in the LdapServer! The LdapAdapter will return success even if it has failed (or the server did not return a correct failure result). For example after a successful request, I could see in the domain log file entries like:
org.opends.sdk.ConstraintViolationException: Constraint Violation: CONSTRAINT_VIOLATION: failed for MessageType : ADD_REQUEST Message ID : 6 Add Request : Entry dn[n]: uid=maartenmaarten,ou=users,ou=system objectClass: inetOrgPerson objectClass: person uid: maartenmaarten userPassword: '0x6D 0x61 0x61 0x72 0x74 0x65 0x6E 0x6D 0x61 0x61 0x72 0x74 0x65 0x6E ' sn: maartenmaarten cn: maartenmaarten : Password shouldn't contain parts of the username at org.opends.sdk.ErrorResultException.wrap(ErrorResultException.java:164) at com.sun.opends.sdk.ldap.AbstractLDAPFutureResultImpl.setResultOrError(AbstractLDAPFutureResultImpl.java:159) at com.sun.opends.sdk.ldap.LDAPClientFilter$1.addResult(LDAPClientFilter.java:93) at com.sun.opends.sdk.ldap.LDAPClientFilter$1.addResult(LDAPClientFilter.java:73)
The user was not created in this case. In a process flow you can of course also use the LdapAdapter again to search for the user you have just created to confirm it was successful.
Conclusion
In this quick howto I have used the example of adding a user by means using the new Oracle SOA Suite 12c LdapAdapter. Of course there are many situations in which this adapter will useful and the adapter is capable of much more then what I’ve just described. Read for example http://docs.oracle.com/middleware/1213/adapters/develop-soa-adapters/adptr_ldap.htm#TKADP2901. Other use cases for the adapter could be if you have users stored in different systems and want to create users in all of them by means of a single service call or if you want to use information (such as groups or e-mail addresses) available from a provided LDAP server. Using the LdapAdapter, you can provide an abstraction to certain LDAP operations by means of services and make the LDAP server part of the integration effort instead of leaving it out or having to build custom integrations for it.
Hi Marteeen,
i got below error while connecting LDAP Adapter
The invocation resulted in an error: Invoke JCA outbound service failed with application error, exception: com.bea.wli.sb.transports.jca.JCATransportException: oracle.tip.adapter.sa.api.JCABindingException: oracle.tip.adapter.sa.impl.fw.ext.org.collaxa.thirdparty.apache.wsif.WSIFException: servicebus:/LDap/Resources/llllll.wsdl [ search_ptt::search(body,body) ] – WSIF JCA Execute of operation ‘search’ failed due to: LDAP_ERROR_INVALID_FLTR.
Invalid ldap filter.
Filter “rks” or a part is invalid.
; nested exception is:
BINDING.JCA-14709
LDAP_ERROR_INVALID_FLTR.
Invalid ldap filter.
Filter “rks” or a part is invalid.
Please examine the log file to determine the problem. Refer to ldapV3 specification for correct composition of a ldapFilter String
com.bea.wli.sb.transports.jca.JCATransportException: oracle.tip.adapter.sa.api.JCABindingException: oracle.tip.adapter.sa.impl.fw.ext.org.collaxa.thirdparty.apache.wsif.WSIFException: servicebus:/LDap/Resources/llllll.wsdl [ search_ptt::search(body,body) ] – WSIF JCA Execute of operation ‘search’ failed due to: LDAP_ERROR_INVALID_FLTR.
Invalid ldap filter.
Filter “rks” or a part is invalid.
; nested exception is:
BINDING.JCA-14709
LDAP_ERROR_INVALID_FLTR.
Invalid ldap filter.
Filter “rks” or a part is invalid.
Please examine the log file to determine the problem. Refer to ldapV3 specification for correct composition of a ldapFilter String
at com.bea.wli.sb.transports.jca.binding.JCATransportOutboundOperationBindingServiceImpl.invoke(JCATransportOutboundOperationBindingServiceImpl.java:169)
at com.bea.wli.sb.transports.jca.JCATransportEndpoint.sendRequestResponse(JCATransportEndpoint.java:240)
at com.bea.wli.sb.transports.jca.JCATransportEndpoint.send(JCATransportEndpoint.java:201)
at com.bea.wli.sb.transports.jca.JCATransportProvider.sendMessageAsync(JCATransportProvider.java:622)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.bea.wli.sb.transports.Util$1.invoke(Util.java:79)
at com.sun.proxy.$Proxy171.sendMessageAsync(Unknown Source)
at com.bea.wli.sb.transports.TransportManagerImpl.sendMessageToService(TransportManagerImpl.java:509)
at com.bea.wli.sb.transports.TransportManagerImpl.sendMessageAsync(TransportManagerImpl.java:397)
at com.bea.wli.sb.service.handlerchain.handlers.TransportProviderInvoker.dispatch(TransportProviderInvoker.java:83)
at com.bea.wli.sb.service.handlerchain.handlers.AbstractHandler.dispatch(AbstractHandler.java:131)
at com.bea.wli.sb.service.handlerchain.handlers.EndpointManagementHandler.dispatch(EndpointManagementHandler.java:47)
at com.bea.wli.sb.service.handlerchain.handlers.AbstractHandler.dispatch(AbstractHandler.java:131)
at com.bea.wli.sb.service.handlerchain.handlers.UpdateOutboundStatistics.dispatch(UpdateOutboundStatistics.java:66)
at com.bea.wli.sb.service.handlerchain.handlers.LoadBalanceFailover$LoadBalanceFailoverHelper.sendMessageAsync(LoadBalanceFailover.java:408)
at com.bea.wli.sb.service.handlerchain.handlers.LoadBalanceFailover$LoadBalanceFailoverHelper.sendMessageToServiceAsync(LoadBalanceFailover.java:333)
at com.bea.wli.sb.service.handlerchain.handlers.LoadBalanceFailover$LoadBalanceFailoverHelper.sendMessageToService(LoadBalanceFailover.java:280)
at com.bea.wli.sb.service.handlerchain.handlers.LoadBalanceFailover.dispatch(LoadBalanceFailover.java:162)
at com.bea.wli.sb.service.handlerchain.handlers.AbstractHandler.dispatch(AbstractHandler.java:131)
at com.bea.wli.sb.service.handlerchain.handlers.OutboundMessageContentHandler.dispatch(OutboundMessageContentHandler.java:71)
at com.bea.wli.sb.service.handlerchain.handlers.AbstractHandler.dispatch(AbstractHandler.java:131)
at com.bea.wli.sb.service.handlerchain.handlers.CheckTxDeadlock.dispatch(CheckTxDeadlock.java:59)
at com.bea.wli.sb.service.handlerchain.handlers.AbstractHandler.dispatch(AbstractHandler.java:131)
at com.bea.wli.sb.service.handlerchain.handlers.ResultCachingHandler.dispatch(ResultCachingHandler.java:111)
at com.bea.wli.sb.service.handlerchain.handlers.AbstractHandler.dispatch(AbstractHandler.java:131)
at com.bea.wli.sb.service.handlerchain.handlers.SetSoapAction.dispatch(SetSoapAction.java:157)
at com.bea.wli.sb.service.handlerchain.handlers.AbstractHandler.dispatch(AbstractHandler.java:131)
at com.bea.wli.sb.service.handlerchain.handlers.OutboundMessagePatternHandler.dispatch(OutboundMessagePatternHandler.java:153)
at com.bea.wli.sb.service.handlerchain.handlers.AbstractHandler.dispatch(AbstractHandler.java:131)
at com.bea.wli.sb.service.handlerchain.OutboundHandlerChain.dispatch(OutboundHandlerChain.java:109)
at com.bea.wli.sb.service.dispatcher.TransportDispatcher.dispatch(TransportDispatcher.java:58)
at com.bea.wli.sb.test.services.TestClient.invoke(TestClient.java:166)
at com.bea.wli.sb.test.services.TestClient$1.run(TestClient.java:125)
at com.bea.wli.sb.test.services.TestClient$1.run(TestClient.java:122)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:363)
at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:146)
at com.bea.wli.sb.util.security.SecurityUtils.executeAs(SecurityUtils.java:102)
at com.bea.wli.sb.security.WLSSecurityContextService.executeAs(WLSSecurityContextService.java:55)
at com.bea.wli.sb.test.services.TestClient.invoke(TestClient.java:128)
at com.bea.wli.sb.test.services.service.BizProcessor.invoke(BizProcessor.java:47)
at com.bea.wli.sb.test.services.AbstractServiceProcessor.invoke(AbstractServiceProcessor.java:447)
at com.bea.wli.sb.test.TestServiceImpl.invoke(TestServiceImpl.java:183)
at com.bea.wli.sb.test.client.ejb.TestServiceEJBBean.invoke(TestServiceEJBBean.java:172)
at com.bea.wli.sb.test.client.ejb.TestService_sqr59p_EOImpl.__WL_invoke(Unknown Source)
at weblogic.ejb.container.internal.SessionRemoteMethodInvoker.invoke(SessionRemoteMethodInvoker.java:34)
at com.bea.wli.sb.test.client.ejb.TestService_sqr59p_EOImpl.invoke(Unknown Source)
at com.bea.wli.sb.test.client.ejb.TestService_sqr59p_EOImpl_WLSkel.invoke(Unknown Source)
at weblogic.rmi.internal.BasicServerRef.invoke(BasicServerRef.java:701)
at weblogic.rmi.cluster.ClusterableServerRef.invoke(ClusterableServerRef.java:231)
at weblogic.rmi.internal.BasicServerRef$1.run(BasicServerRef.java:527)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:363)
at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:146)
at weblogic.rmi.internal.BasicServerRef.handleRequest(BasicServerRef.java:523)
at weblogic.rmi.internal.wls.WLSExecuteRequest.run(WLSExecuteRequest.java:118)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:311)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:263)
Caused by: oracle.tip.adapter.sa.api.JCABindingException: oracle.tip.adapter.sa.impl.fw.ext.org.collaxa.thirdparty.apache.wsif.WSIFException: servicebus:/LDap/Resources/llllll.wsdl [ search_ptt::search(body,body) ] – WSIF JCA Execute of operation ‘search’ failed due to: LDAP_ERROR_INVALID_FLTR.
Invalid ldap filter.
Filter “rks” or a part is invalid.
; nested exception is:
BINDING.JCA-14709
LDAP_ERROR_INVALID_FLTR.
Invalid ldap filter.
Filter “rks” or a part is invalid.
Please examine the log file to determine the problem. Refer to ldapV3 specification for correct composition of a ldapFilter String
at oracle.tip.adapter.sa.impl.JCABindingReferenceImpl.request(JCABindingReferenceImpl.java:325)
at com.bea.wli.sb.transports.jca.binding.JCATransportOutboundOperationBindingServiceImpl.invoke(JCATransportOutboundOperationBindingServiceImpl.java:164)
… 58 more
Caused by: oracle.tip.adapter.sa.impl.fw.ext.org.collaxa.thirdparty.apache.wsif.WSIFException: servicebus:/LDap/Resources/llllll.wsdl [ search_ptt::search(body,body) ] – WSIF JCA Execute of operation ‘search’ failed due to: LDAP_ERROR_INVALID_FLTR.
Invalid ldap filter.
Filter “rks” or a part is invalid.
; nested exception is:
BINDING.JCA-14709
LDAP_ERROR_INVALID_FLTR.
Invalid ldap filter.
Filter “rks” or a part is invalid.
Please examine the log file to determine the problem. Refer to ldapV3 specification for correct composition of a ldapFilter String
at oracle.tip.adapter.sa.impl.fw.wsif.jca.WSIFOperation_JCA.performOperation(WSIFOperation_JCA.java:695)
at oracle.tip.adapter.sa.impl.fw.wsif.jca.WSIFOperation_JCA.executeOperation(WSIFOperation_JCA.java:383)
at oracle.tip.adapter.sa.impl.fw.wsif.jca.WSIFOperation_JCA.executeRequestResponseOperation(WSIFOperation_JCA.java:342)
at oracle.tip.adapter.sa.impl.JCABindingReferenceImpl.invokeWsifProvider(JCABindingReferenceImpl.java:422)
at oracle.tip.adapter.sa.impl.JCABindingReferenceImpl.request(JCABindingReferenceImpl.java:323)
… 59 more
Caused by: BINDING.JCA-14709
LDAP_ERROR_INVALID_FLTR.
Invalid ldap filter.
Filter “rks” or a part is invalid.
Please examine the log file to determine the problem. Refer to ldapV3 specification for correct composition of a ldapFilter String
at oracle.tip.adapter.ldap.outbound.LdapSearchInteractionBuilder.constructLdapRequestMessage(LdapSearchInteractionBuilder.java:312)
at oracle.tip.adapter.ldap.outbound.LdapInteractionFactory.getLdapRequestMessage(LdapInteractionFactory.java:164)
at oracle.tip.adapter.ldap.outbound.LdapInteraction.execute(LdapInteraction.java:208)
at oracle.tip.adapter.sa.impl.fw.wsif.jca.WSIFOperation_JCA.performOperation(WSIFOperation_JCA.java:568)
… 63 more
Caused by: org.opends.sdk.LocalizedIllegalArgumentException: The provided search filter “rks” was missing an equal sign in the suspected simple filter component between positions 0 and 3
at org.opends.sdk.Filter.valueOf0(Filter.java:1583)
at org.opends.sdk.Filter.valueOf(Filter.java:1233)
at oracle.tip.adapter.ldap.outbound.LdapSearchInteractionBuilder.constructLdapRequestMessage(LdapSearchInteractionBuilder.java:310)
… 66 more
Please help me.
Hi. As the exception says; rks is not a valid LDAP query to execute. You should specify a valid query. This is use-case specific. With kind regards.
Thanks a lot for your nice article Maartin. I’m using Jdeveloper 12.2.1. I cannot find LdapAdapter in wbelogic deployments. Should I install that using a separate library?
Hi Ali. I have not seen 12c environments where the LDAPAdapter was not available by default under deployments. Is your environment an upgraded 11g environment? Also the LDAPAdapter is by default not targeted to a specific server. To manually deploy the adapter, you can look at: https://docs.oracle.com/middleware/1213/adapters/develop-soa-adapters/GUID-8111CB1A-15C8-47C7-A800-FBDCDCE98868.htm#TKADP164. I hope this helps.
Hi Maarten,
Nice article. Is it possible to validate username and password again active directory through LDAP adapter ?? Could you please let me know if this possible.
Hi Suresh,
I have not seen a direct way of doing authentication of specific users with the LDAP Adapter. If you want authentication, I suggest you use an authentication provider as can be configured in WebLogic Server (http://docs.oracle.com/cd/E17904_01/web.1111/e13707/atn.htm#SECMG169). As a possible alternative you might be able to fetch the password from the LDAP using the adapter, see if/how it is encrypted and compare it to what you expect it to be. I haven’t tried this. You have to mind though that the password might appear in audit logs this way. You can encrypt this (http://www.soawork.com/2014/10/soa-12c-encryption-and-decryption-of-sensitive-data.html).
Hope this helps you,
With kind regards,
Maarten
Hi Maarten,
is it possible to directly connect to a subtree of the ldap directory?
In my case my user only has the permission to connect to a certain base dn.
Because there is no possibility to specify a base dn, the adapter tries to connect to the root, where my permissions are insufficient.
This is a huge problem for me because it makes the LDAPAdapter useless for this situation.
With kind regards,
Raphael