Oracle® Fusion Middleware Security Guide 11g Release 1 (11.1.1) Part Number E10043-04 |
|
|
View PDF |
This chapter applies only to JavaSE applications. For authentication for JavaEE applications, it provides links to other Oracle WebLogic documentation.
This chapter is divided in the following sections:
Prior to using this information, it is strongly recommended to be familiar with the context in which these APIs are used. For details, see Section 14.3.2, "Authentication with OPSS APIs."
The following documents are a good source of information for developing authentication in JavaEE applications:
For general information about authentication in the Oracle WebLogic Server, see section Authentication in chapter 3 in Oracle Fusion Middleware Understanding Security for Oracle WebLogic Server.
Oracle Fusion Middleware Programming Security for Oracle WebLogic Server
Chapter 3, Securing Web Applications
Chapter 4, Using JAAS Authentication in Java Clients
Chapter 5, Using SSL Authentication in Java Clients
Oracle Fusion Middleware Developing Security Providers for Oracle WebLogic Server
Chapter 4, Authentication Providers
Chapter 5, Identity Assertion Providers
Chapter 13, Servlet Authentication Filters
Custom modules in JavaEE applications required to be wrapped in an authenticator provider. For details, see section How to Develop a Custom Authentication Provider in Oracle Fusion Middleware Developing Security Providers for Oracle WebLogic Server.
For login modules used in JavaEE applications, see the following documentation:
Section Login Modules in chapter 4 in Oracle Fusion Middleware Developing Security Providers for Oracle WebLogic Server.
Section JAAS Authentication Development Environment in Chapter 4 in Oracle Fusion Middleware Programming Security for Oracle WebLogic Server
For links to all OPSS API javadocs, see Section H.1, "OPSS API References."
This section is divided into the following sections:
Authentication is the mechanism by which callers prove that they are acting on behalf of specific users or system. Using data, such as name/password combinations, authentication answers the question Who are you? The identity store is the abstract concept that refers to the storage where identity data is kept, and authentication providers are ways to access an identity store.
The way an application obtains information from an OPSS security store (identity, policy, or credential store) and manages its contents is using the OPSS APIs, as illustrated in the following graphic:
A JavaSE application can use an LDAP-based identity store configured in the file jps-config-jse.xml
with the elements <serviceProvider>
, <serviceInstance>
, and <jpsContext>
, as illustrated in the following snippet:
<serviceProviders> <serviceProvider type="IDENTITY_STORE" name="idstore.ldap.provider" class="oracle.security.jps.internal.idstore.ldap.LdapIdentityStoreProvider"> <description>Prototype LDAP-based ID store</description> </serviceProvider> </serviceProviders> <serviceInstances> <serviceInstance name="idstore.ldap" provider="idstore.ldap.provider"> <property name="idstore.type" value="OID"/> <property name="security.principal.alias" value="MyCredentialMapName"/> <property name="security.principal.key" value="MyCredentialMapKey"/> <property name="ldap.url" value="${LDAP_URI}"/> <property name="max.search.filter.length" value="500"/> <extendedProperty> <name>user.search.bases</name> <values> <value>cn=users,dc=us,dc=oracle,dc=com</value> </values> </extendedProperty> <extendedProperty> <name>group.search.bases</name> <values> <value>cn=groups,dc=us,dc=oracle,dc=com</value> </values> </extendedProperty> </serviceInstance> </serviceInstances> <jpsContexts default="ldap_idstore"> <jpsContext name="ldap_idstore"> <serviceInstanceRef ref="idstore.ldap"/> </jpsContext> </jpsContexts>
Note the following points:
The name of the <serviceInstance>
(idstore.ldap
in the example above) can have any value, but it must match the instance referenced in element <serviceInstanceRef>
.
The name of the <serviceProvider>
(idstore.ldap.provider
in the example above) can have any value, but it must match the provider in element <serviceInstance>
.
To add properties to a provider instance with a prescribed script, see Appendix E, "Configuring OPSS Service Provider Instances with a WLST Script."
A login module is a component that authenticates users and populates a subject with principals. This process occurs in two distinct phases: during the first phase, the login module attempts to authenticate a user requesting, as necessary, a name and a password or some other credential data; only if this phase succeeds, the second phase is invoked. During the second phase, the login module assigns relevant principals to a subject, which is eventually used to perform some privileged action.
A JavaSE application can use a stack of login modules to authenticate its users; each module in the stack performs its own computations independently from the others in the stack. These and other services are specified in the file jps-config-jse.xml
.
OPSS APIs includes the interface oracle.security.jps.service.login.LoginService
which allows a JavaSE application to invoke not just all login modules in a stack, but a subset of them in a prescribed order.
The name of the jps context (defined in the configuration file jps-config-jse.xml)
passed to the method LoginContext
in the LoginService
interface (which is) determines the stack of login modules that an application uses.
The standard JAAS API LoginContext
can also be user to invoke the login modules defined in the default context.
The sequence in which a jps context lists the login modules in a stack is significant, since the authentication algorithm takes this order into account in addition to other data, such as the flag that identifies the module security level (required, sufficient, requisite, or optional).
Out-of-the-box, the identity store service is file-based, its contents being provisioned the file system-jazn-data.xml
, but it can be reconfigured to be an LDAP-based identity store.
OPSS supports the Identity Store login module in JavaSE applications, which can be used for authentication or identity assertion.
Identity Store Login Module
The class associated with this login module is the following:
oracle.security.jps.internal.jaas.module.idstore.IdStoreLoginModule
An instance of this module is configured in the file jps-config-jse.xml
as illustrated in the following fragment:
<serviceInstance name="idstore.loginmodule" provider="jaas.login.provider"> <description>Identity Store Login Module</description> <property name="loginModuleClassName" value="oracle.security.jps.internal.jaas.module.idstore.IdStoreLoginModule"/> <property name="jaas.login.controlFlag" value="REQUIRED"/> </serviceInstance>
Properties specific to this login module include the following:
remove.anonymous.role (defaults to true) add.application.role (defaults to true)
This section illustrates the use of the Identity Store login module for basic username and password authentication.
Invoke IdStoreLoginModule
The following code fragment illustrates how to set a callback handler and a context:
import javax.security.auth.Subject; import javax.security.auth.login.LoginContext; Subject sub = new Subject(); CallbackHandler cbh = new YourCallbackHandler(); LoginContext context = new LoginContext(appName, subject, cbh); context.login();
The callback handler must be able to handle NameCallback
and PasswordCallback
.
Configure jps-config-jse.xml
The following jps-config-jse.xml
fragment illustrates the configuration of the context appName
:
<jpsContext name="appName"> <serviceInstanceRef ref="jaaslm.idstore1"/> </jpsContext> <serviceProvider type="JAAS_LM" name="jaaslm.idstore" class="oracle.security.jps.internal.jaas.module.idstore.IdStoreLoginModule"> <description>Identity Store-based LoginModule </description> </serviceProvider> <serviceInstance name="jaaslm.idstore1" provider="jaaslm.idstore"> <property name="jaas.login.controlFlag" value="REQUIRED"/> <property name="debug" value="true"/> <property name="addAllRoles" value="true"/> </serviceInstance>
Write the Callback Handler
The following code snippet illustrates a callback handler able to handle name and password callback:
import javax.security.auth.callback.*; import java.io.IOException; public class SampleCallbackHandler implements CallbackHandler { //For name/password callbacks private String name = null;private char[] password = null; public SampleCallbackHandler(String name, char[] pwd) { if (name == null || name.length() == 0 ) throw new IllegalArgumentException("Invalid name "); else this.name = name; if (pwd == null || pwd.length == 0) throw new IllegalArgumentException("Invalid password "); else this.password = pwd; } public String getName() { return name; } public char[] getPassword() { return password; } public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { if (callbacks != null && callbacks.length > 0) { for (Callback c : callbacks) { if (c instanceof NameCallback) { ((NameCallback) c).setName(name); } else if (c instanceof PasswordCallback) { ((PasswordCallback) c).setPassword(password); } else { throw new UnsupportedCallbackException(c); } } } } }
To use the Identity Store login module for assertion, a developer must:
Provide an IdentityAssertion permission with execute action, so the permission oracle.security.jps.JpsPermission
can execute the login module for assertion.
Implement a callback handler that extends the class oracle.security.jps.callback.IdentityCallback
.
The above two requirements are illustrated in the following code and configuration samples.
Provisioning the JpsPermission
The following configuration sample illustrates a grant allowing the code MyApp
the required JpsPermission
to execute the assertion login module:
<grant> <grantee> <codesource> <url>file:${domain.home}/servers/MyApp/-</url> </codesource> </grantee> <permissions> <permission> <class>oracle.security.jps.JpsPermission</class> <name>IdentityAssertion</name> <actions>execute</actions> </permission> </permissions> </grant>
The following configuration sample illustrates a grant allowing the principal jdoe
the required JpsPermission
to execute the assertion login module:
<grant> <grantee> <principals> <principal> <class>weblogic.security.principal.WLSUserImpl</class> <name>jdoe</name> </principal> </principals> </grantee> <permissions> <permission> <class>oracle.security.jps.JpsPermission</class> <name>IdentityAssertion</name> <actions>execute</actions> </permission> </permissions> </grant>
Implementing the CallbackHandler
The following code fragment illustrates the implementation of a handler and the method handle, and how to instantiate it:
import oracle.security.jps.callback.IdentityCallback; import javax.security.auth.Subject; import javax.security.auth.login.LoginContext; class MyAssertionCallbackHandler extends CallbackHandler { private String name = null; public MyAssertionCallbackHandler(String name) { this.name = name; } public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (Callback callback : callbacks) { if (callback instanceof IdentityCallback) { IdentityCallback idcb = (IdentityCallback) callback; idcb.setIdentity(name); } else { //throw exception } } } } CallbackHandler cbh = new MyAssertionCallbackHandler("name"); Subject sub = new Subject(); // The first parameter must be the name of the jpsContext in which the // IdStore Login Module is referrenced LoginContext context = new LoginContext("myContext", sub, cbh); context.login(); Subject s = context.getSubject(); ...
To invoke a login module programmatically in JavaSE applications, use the method getLoginContex
t of the interface oracle.security.jps.service.login.LoginService
.
Similar to the method LoginContext
in the standard JAAS API, getLoginContext
returns an instance of a LoginContext object that can be used to authenticate a user, but, more generally, it also allows the use of any number of login modules in any order. Authentication is then performed on just those login modules and in the order they were passed.
The following code fragment illustrates user authentication against a subset of login modules in a prescribed order using getLoginContext
:
import oracle.security.jps.service.ServiceLocator; import oracle.security.jps.service.JpsServiceLocator; import oracle.security.jps.service.login.LoginService; //Obtain the login service ServiceLocator locator = JpsServiceLocator.getServiceLocator(); LoginService loginService = locator.lookup(LoginService.class); //Create the handler for given name and password CallbackHandler cbh = new MyCallbackHandler("name", "password".toCharArray()); //Invoke login modules selectively in a given order selectiveModules = new Sting[]{"lmName1", "lmName2", "lmName3"}; LoginContext ctx = loginService.getLoginContext(new Subject(), cbh, selectiveModules); ctx.login(); Subject s = ctx.getSubject();
selectiveModules
is an array of (login module) names, and the authentication uses precisely those login modules named in the array in the order listed in the array. Each name in the array must be the name of a service instance listed in the default context of the file jps-config-jse.xml
.
The following fragment illustrates the configuration of a stack of two login modules:
<serviceProvider type="LOGIN" name="jaas.login.provider" class="oracle.security.jps.internal.login.jaas.JaasLoginServiceProvider"> <description>Common definition for any login module instances</description> </serviceProvider> <serviceInstance name="auth.loginmodule" provider="jaas.login.provider"> <description>User Authentication Login Module</description> <property name="loginModuleClassName" value="oracle.security.jps.internal.jaas.module.authentication.JpsUserAuthenticationLoginModule"/> <property name="jaas.login.controlFlag" value="REQUIRED"/> </serviceInstance> <serviceInstance name="custom.loginmodule" provider="jaas.login.provider"> <description>My Custom Login Module</description> <property name="loginModuleClassName" value="my.custom.MyLoginModuleClass"/> <property name="jaas.login.controlFlag" value="REQUIRED"/> </serviceInstance> <jpsContexts default="aJpsContext"> <jpsContext name="aJpsContext"> <serviceInstanceRef ref="auth.loginmodule"/> <serviceInstanceRef ref="custom.loginmodule"/> </jpsContext> </jpsContexts>