As we saw earlier in Example 16-1, when a Java client creates a JNDI context bound to a server configured for two-way SSL, the server authenticates the client on two levels:
If the client needs to interact with an SSL server configured for two-way SSL, the client will be requested to present its digital certificate to prove its identity. The client's certificate can perform the dual role of identifying the WebLogic principals that map to the client. After all, a client's certificate does affirm its identity. WebLogic lets you configure the server so that it can map the client's certificate to the username of a valid WebLogic user. In this way, a Java client can securely establish a JNDI context that is bound to an SSL server by supplying only its private key and digital certificate, and WebLogic will map the client's certificate to a username.
Typically, a client (e.g., the JNDI client) supplies a username and password to authenticate itself to WebLogic. At the server end, WebLogic determines the client's principals i.e., the corresponding user and the groups it belongs to and uses these to populate the client's subject. In Chapter 17, you'll learn how WebLogic's authorization framework works with these principals populated in the client's subject to evaluate whether the client is permitted to access a server-side resource. However, if an SSL-enabled client connects to a server configured for two-way SSL, and the client doesn't supply a username, the server still can use the client's certificate to determine the user and its associated groups and roles.
This mapping is executed by the configured Identity Asserter, one of the modules of the Authentication Provider, which allows you to determine the client's identity using some client-supplied token such as an X.509-compliant certificate or a CSIv2-compliant certificate. An Identity Asserter validates these tokens and maps each to a particular WebLogic user. If you haven't configured an Identity Assertion Provider that can handle these tokens, the client must authenticate itself using some alternative mechanism e.g., supplying a username/password combination in addition to its client-side certificate. Without an Identity Assertion Provider set up for the security realm, our SSL-enabled JNDI client must also supply the login credentials of a valid WebLogic user:
Environment env = new Environment( ); env.setProviderUrl("t3s://10.0.10.10:7002"); // Set the username and password env.setSecurityPrincipal("system"); env.setSecurityCredentials("12341234"); // As in Example 16-1, obtain the client's private key and certificate // ... env.setSSLClientCertificate(new InputStream[] { key, cert}); // ... context = env.getInitialContext( );
When you configure an Identity Assertion Provider for a security realm to handle certificate-based tokens, WebLogic passes the digital certificate received from the Java client to a user mapper class. As the name suggests, this class maps the client-supplied token (digital certificate) to a WebLogic username. The client should not supply the additional login credentials of a WebLogic user because that is now evaluated by the configured user mapper class.
Once again, you must use the Administration Console in order to configure an Identity Asserter. You need to navigate to the Security/Realms/myrealm/Providers/Authentication/Default Identity Asserter node from the left pane of the Administration Console to view and modify its configuration. The Active Types field lets you select the type of tokens that clients may supply in order to establish their identity. By default, the Identity Asserter supports AuthenticatedUser i.e., traditional username/password authentication. If you need to support identity assertion based on X.509 certificates required by two-way SSL, you also must add X.509 to the list on a separate line.
The Identity Asserter setup is complete once you specify the fully qualified name of the user mapper class in the User Name Mapper Class Name field. The username mapper class must be available in WebLogic's classpath. It also must implement the weblogic.security.providers.authentication.UserNameMapper interface. The UserNameMapper interface lets you execute the mapping using X.509 certificates received during an SSL handshake or through CSIv2, or on the basis of distinguished names passed via CSIv2. Example 16-2 provides a sample implementation of the UserNameMapper interface:
Example 16-2. Custom username mapper class
package com.oreilly.wlguide.ssl; import java.security.cert.X509Certificate; public class UserNameMapper implements weblogic.security.providers.authentication.UserNameMapper { /** * Maps a certificate to a username based on the certificate chain presented */ public String mapCertificateToUserName(X509Certificate[] certs, boolean ssl){ if (certs.length > 0) String subjectDN = certs[0].getSubjectDN( ).getName( )); if (subjectDN.equals("xena")) // Whatever logic you want return "system"; else return "jon"; } /* * Map an X.501 distinguised name to a username based on the * distinguished name attributes and values. */ public String mapDistinguishedNameToUserName(byte[] distinguishedName) { // Not used for X.509 certificates return null; } }
In order to map X.509 certificates to a username, you need to implement only the mapCertificateToUsername( ) method. This method accepts two parameters: an array of X509Certificate objects that represents the client's certificate chain presented to WebLogic; and a Boolean flag that is set to true if the certificates were received from an SSL handshake, or set to false otherwise. For instance, if the certificates were obtained from using CSIv2 tokens, the ssl flag would be set to false. Use this method to examine the incoming certificates and, based on the information embedded in these certificates, return the username that ought to be associated with the client. In the preceding example, we simply associate any incoming certificate whose SubjectDN field is set to xena, or to the user system, and associate all other certificates to the user jon. You could imagine other scenarios in which the username is embedded within the client's certificate, thereby allowing you to set up a one-to-one mapping between the client's certificates and WebLogic users.
There is an unfortunate consequence to using X.509 certificates as the basis for your identity assertion. A Java client whose identity is determined using client-side tokens cannot change its identity. The client's certificate is validated only once, during the SSL handshake between the client and WebLogic. If you did not configure an Identity Assertion Provider for the security realm, the client may simply establish another JNDI context and supply the new username/password combination. In this case, the client's certificate that was originally passed to the server isn't used to assert the client's identity, and the original parameters negotiated during the SSL handshake are cached for subsequent SSL connections to WebLogic.
16.4.1 Two-Way SSL Authentication for Web Applications
In Chapter 2, we learned how to apply declarative security constraints to a collection of web resources within a web application. The deployment descriptors for the web application allow you to restrict access to a URL pattern to one or more WebLogic security roles. Consequently, when a user accesses the particular resource from a web browser, she is required to authenticate herself. Typically, if you've configured BASIC or FORM authentication for the web application, the user is required to supply the login credentials of a valid WebLogic user within the security realm. WebLogic then will authenticate the user and determine whether the browser has sufficient access privileges to invoke the web resource.
This authentication mechanism can operate even when a web browser connects to an HTTPS port. However, if WebLogic is configured for two-way SSL, any browser that interacts over the HTTPS port also must present a digital certificate as proof of its identity. In this way, two-way SSL provides the avenue for client certificate-based web authentication. This means that a browser is required to present a digital certificate as proof of its identity when it attempts to access a protected web resource. WebLogic then will authenticate the browser by mapping its certificate to a valid user within the security realm. Based on this identity assertion, WebLogic can determine whether the browser is permitted to access the web resource.
In order to set up this certificate-based authentication scheme for resources in a web application, you need to execute the following tasks:
MySecurity Constraint MyWeb Resource Collection /* PUT GET
MySecurity Constraint web app only accessible to users in mysecrole mysecrole <login-config> CLIENT-CERT myrealm security role with access to web app mysecrole
Notice how we've used the login-config element to indicate the authentication mechanism supported by the web application.
mysecrole system,jon
This completes the list of changes you need to make to the web application (its deployment descriptors, really) in order to enable certificate-based web authentication.
As you can imagine, this setup is no different from configuring BASIC- or FORM-based web authentication. However, certificate-based web authentication requires additional setup on the servers to which the web application will be deployed. In fact, you need to ensure the following:
Only after all these instances are true can your web application support certificate-based web authentication for a collection of web resources.
Introduction
Web Applications
Managing the Web Server
Using JNDI and RMI
JDBC
Transactions
J2EE Connectors
JMS
JavaMail
Using EJBs
Using CMP and EJB QL
Packaging and Deployment
Managing Domains
Clustering
Performance, Monitoring, and Tuning
SSL
Security
XML
Web Services
JMX
Logging and Internationalization
SNMP