The idea of the User/Role API is to abstract developers from the identity store where users and groups are kept. A developer can basically interact with any identity provider supported by Weblogic server using the same methods. The javadoc can be found here: http://download.oracle.com/docs/cd/E15523_01/apirefs.1111/e14658/toc.htm
In this post I want to alert you about two caveats:
1) User/Role API is able to query data from only one provider. If you want to query multiple identity stores, you need to go through an OVD Authenticator (or libOvd). And depending on how you get a handle to the identity store, the order in which providers are defined in Weblogic server Console as well as their CONTROL FLAGs do matter.
Shamelessly borrowing content from FMW Application Security Guide:
"OPSS initializes the identity store service with the LDAP authenticator chosen from the list of configured LDAP authenticators according to the following algorithm:
1. Consider the subset of LDAP authenticators configured. Note that, since the context is assumed to contain at least one LDAP authenticator, this subset is not empty.
2. Within that subset, consider those that have set the maximum flag. The flag ordering used to compute this subset is the following: REQUIRED > REQUISITE > SUFFICIENT > OPTIONAL. Again, this subset (of LDAPs realizing the maximum flag) is not empty.
3. Within that subset, consider the first configured in the context.The LDAP authenticator singled out in step 3 is the one chosen to initialize the identity store service."
Lack of such understanding is a big source of headache.
Weblogic server ships with DefaultAuthenticator as the out-of-box authentication provider with the CONTROL FLAG set as REQUIRED. Customers typically want to retrieve users from an enterprise-wide LDAP server, like OID or Active Directory. They go ahead and define a new authenticator and put it as the first in the providers list. But they leave DefaultAuthenticator untouched, because they still want to leverage the weblogic user as the administrator. And when some application relying on the User/Role API is executed (Oracle's BPM and BIP are examples), a problem is just about to happen, because none of the users and groups defined in the enterprise-wide identity store are found. And the solution to this is pretty simple: switch DefaultAuthenticator's CONTROL FLAG from REQUIRED to SUFFICIENT. What happens now during authentication time is that if the user is not found in the first authenticator, the lookup falls back to DefaultAuthenticator, so leveraging weblogic user is not a problem. And that will also make the User Role API querying the identity provider that you want (the first in the list).
2) Depending on how you get a handle to the identity store, provider-specific metadata (user, password, address, root search base) won't be reused and you'll be forced to define it in code again (of course you can externalize them to some properties file, but it is still a double maintenance duty).
That said, let's examine possible ways of getting a handle to the identity store.
IdentityStoreFactoryBuilder builder = new IdentityStoreFactoryBuilder(); IdentityStoreFactory oidFactory = null; Hashtable factEnv = new Hashtable(); // Creating the factory instance factEnv.put(OIDIdentityStoreFactory.ST_SECURITY_PRINCIPAL, "cn=orcladmin"); factEnv.put(OIDIdentityStoreFactory.ST_SECURITY_CREDENTIALS,"welcome1"); factEnv.put(OIDIdentityStoreFactory.ST_LDAP_URL,"ldap://ldap.us.oracle.com:3060/"); oidFactory = builder.getIdentityStoreFactory("oracle.security.idm.providers.oid.OIDIdentityStoreFactory", factEnv); Hashtable storeEnv = new Hashtable(); storeEnv.put(OIDIdentityStoreFactory.RT_SUBSCRIBER_NAME,"cn=users,dc=us,dc=oracle,dc=com"); IdentityStore oidStore = oidFactory.getIdentityStoreInstance(storeEnv); // Use oidStore to perform various operations against the provider
Look at how specific this snippet is to OID and how we're passing metadata that is already available in the provider definition itself. By doing this, you do not incur in the problem described in my bullet #1, because you're going directly against a specific identity store. You're not leveraging the definitions in Weblogic server at all.
But if you do this...
JpsContextFactory ctxFactory = JpsContextFactory.getContextFactory(); JpsContext ctx = ctxFactory.getContext(); LdapIdentityStore idstoreService = (LdapIdentityStore)ctx.getServiceInstance(IdentityStoreService.class) IdentityStore idStore = idstoreService.getIdmStore(); // Use idStore to perform various operations against the provider
You're delegating the provider lookup process to OPSS (Oracle Platform Security Services), and it will abide by those rules outlined in my bullet #1. Here, you don't have to redefine your connection metadata. You are simply reusing whatever is defined in Weblogic server and are not incurring in the problem mentioned in bullet #2. For consistency and manageability, this is a much better approach.
For the curious, the following is the necessary configuration in jps-config.xml to make this happen (see text in bold red). It is out-of-box available in any FMW install, so don't worry about it.
<serviceInstances> ... <serviceInstance name="idstore.ldap" provider="idstore.ldap.provider"> <property name="idstore.config.provider" value="oracle.security.jps.wls.internal.idstore.WlsLdapIdStoreConfigProvider"/> <property name="CONNECTION_POOL_CLASS" value="oracle.security.idm.providers.stdldap.JNDIPool"/> </serviceInstance> ... </serviceInstances> ... <jpsContexts default="default"> <jpsContext name="default"> <serviceInstanceRef ref="credstore"/> <serviceInstanceRef ref="keystore"/> <serviceInstanceRef ref="policystore.xml"/> <serviceInstanceRef ref="audit"/> <serviceInstanceRef ref="idstore.ldap"/> <serviceInstanceRef ref="trust"/> <serviceInstanceRef ref="pdp.service"/> </jpsContext> ... </jpsContexts>