5 Identity Assertion Providers

An Identity Assertion provider is a specific form of Authentication provider that allows users or system processes to assert their identity using tokens (in other words, perimeter authentication). Identity Assertion providers enable perimeter authentication and support single sign-on. You can use an Identity Assertion provider in place of an Authentication provider if you create a LoginModule for the Identity Assertion provider, or in addition to an Authentication provider if you want to use the Authentication provider's LoginModule.

If you want to allow the Identity Assertion provider to be configured separately from the Authentication provider, write two providers. If your Identity Assertion provider and Authentication provider cannot work independently, then write one provider.

The following sections describe Identity Assertion provider concepts and functionality, and provide step-by-step instructions for developing a custom Identity Assertion provider:

Identity Assertion Concepts

Before you develop an Identity Assertion provider, you need to understand the following concepts:

Identity Assertion Providers and LoginModules

When used with a LoginModule, Identity Assertion providers support single sign-on. For example, an Identity Assertion provider can generate a token from a digital certificate, and that token can be passed around the system so that users are not asked to sign on more than once.

The LoginModule that an Identity Assertion provider uses can be:

Unlike in a simple authentication situation (described in The Authentication Process), the LoginModules that Identity Assertion providers use do not verify proof material such as usernames and passwords; they simply verify that the user exists.

The LoginModules in this configuration must:

  • Populate the Subject with required Principals, such as those of type WLSGroup.

  • Must trust that the user has submitted sufficient proof to login and not require a password or some other proof material.

You must implement the AuthenticationProviderV2.getAssertionModuleConfiguration method in your custom Authentication provider, as described in Implement the AuthenticationProviderV2 SSPI. This method is called for identity assertion, such as when an X.509 certificate is being used, and to process the run-as tag in deployment descriptors. Other single signon strategies use it as well.

Note:

For more information about LoginModules, see LoginModules.

Identity Assertion and Tokens

You develop Identity Assertion providers to support the specific types of tokens that you will be using to assert the identities of users or system processes. You can develop an Identity Assertion provider to support multiple token types, but you or an administrator configure the Identity Assertion provider so that it validates only one "active" token type. While you can have multiple Identity Assertion providers in a security realm with the ability to validate the same token type, only one Identity Assertion provider can actually perform this validation.

Note:

"Supporting" token types means that the Identity Assertion provider's runtime class (that is, the IdentityAsserter SSPI implementation) can validate the token type in its assertIdentity method. For more information, see Implement the IdentityAsserterV2 SSPI.

The following sections will help you work with new token types:

How to Create New Token Types

If you develop a custom Identity Assertion provider, you can also create new token types. A token type is simply a piece of data represented as a string. The token types you create and use are completely up to you. The token types currently defined for the WebLogic Identity Assertion provider include: AuthenticatedUser, X.509, CSI.PrincipalName, CSI.ITTAnonymous, CSI.X509CertChain, CSI.DistinguishedName, and wsse:PasswordDigest.

To create new token types, you create a new Java file and declare any new token types as variables of type String., as shown in Example 5-1. The PerimeterIdentityAsserterTokenTypes.java file defines the names of the token types Test 1, Test 2, and Test 3 as strings.

Example 5-1 PerimeterIdentityAsserterTokenTypes.java

package sample.security.providers.authentication.perimeterATN;
public class PerimeterIdentityAsserterTokenTypes
{
   public final static String TEST1_TYPE = 'Test 1";
   public final static String TEST2_TYPE = 'Test 2";
   public final static String TEST3_TYPE = 'Test 3";
}

Note:

If you are defining only one new token type, you can also do it right in the Identity Assertion provider's runtime class, as shown in Example 5-4.

How to Make New Token Types Available for Identity Assertion Provider Configurations

When you or an administrator configure a custom Identity Assertion provider (see Configure the Custom Identity Assertion Provider Using the Administration Console), the Supported Types field displays a list of the token types that the Identity Assertion provider supports. You enter one of the supported types in the Active Types field, as shown in Figure 5-1.

Figure 5-1 Configuring the Sample Identity Assertion Provider

Description of Figure 5-1 follows
Description of "Figure 5-1 Configuring the Sample Identity Assertion Provider"

The content for the Supported Types field is obtained from the SupportedTypes attribute of the MBean Definition File (MDF), which you use to generate your custom Identity Assertion provider's MBean type. An example from the sample Identity Assertion provider is shown in Example 5-2. (For more information about MDFs and MBean types, see Generate an MBean Type Using the WebLogic MBeanMaker.)

Example 5-2 SampleIdentityAsserter MDF: SupportedTypes Attribute

<MBeanType>
...
   <MBeanAttribute 
    Name = "SupportedTypes"
    Type = "java.lang.String[]"
    Writeable = "false"
    Default = "new String[] {&quot;SamplePerimeterAtnToken&quot;}"
   />
...
</MBeanType>

Similarly, the content for the Active Types field is obtained from the ActiveTypes attribute of the MBean Definition File (MDF). You or an administrator can default the ActiveTypes attribute in the MDF so that it does not have to be set manually with the WebLogic Server Administration Console. An example from the sample Identity Assertion provider is shown in Example 5-3.

Example 5-3 SampleIdentityAsserter MDF: ActiveTypes Attribute with Default

<MBeanAttribute 
 Name= "ActiveTypes"
 Type= "java.lang.String[]"
 Default = "new String[] { &quot;SamplePerimeterAtnToken&quot; }"
/>

While defaulting the ActiveTypes attribute is convenient, you should only do this if no other Identity Assertion provider will ever validate that token type. Otherwise, it would be easy to configure an invalid security realm (where more than one Identity Assertion provider attempts to validate the same token type). Best practice dictates that all MDFs for Identity Assertion providers turn off the token type by default; then an administrator can manually make the token type active by configuring the Identity Assertion provider that validates it.

Note:

If an Identity Assertion provider is not developed and configured to validate and accept a token type, the authentication process will fail. For more information about configuring an Identity Assertion provider, see Configure the Custom Identity Assertion Provider Using the Administration Console.

Passing Tokens for Perimeter Authentication

An Identity Assertion provider can pass tokens from Java clients to servlets for the purpose of perimeter authentication. Tokens can be passed using HTTP headers, cookies, SSL certificates, or other mechanisms. For example, a string that is base 64-encoded (which enables the sending of binary data) can be sent to a servlet through an HTTP header. The value of this string can be a username, or some other string representation of a user's identity. The Identity Assertion provider used for perimeter authentication can then take that string and extract the username.

If the token is passed through HTTP headers or cookies, the token is equal to the header or cookie name, and the resource container passes the token to the part of the WebLogic Security Framework that handles authentication. The WebLogic Security Framework then passes the token to the Identity Assertion provider, unchanged.

WebLogic Server is designed to extend the single sign-on concept all the way to the perimeter through support for identity assertion. Identity assertion allows WebLogic Server to use the authentication mechanism provided by perimeter authentication schemes such as the Security Assertion Markup Language (SAML), the Simple and Protected GSS-API Negotiation Mechanism (SPNEGO), or enhancements to protocols such as Common Secure Interoperability (CSI) v2 to achieve this functionality.

Common Secure Interoperability Version 2 (CSIv2)

WebLogic Server provides support for an Enterprise JavaBean (EJB) interoperability protocol based on Internet Inter-ORB (IIOP) (GIOP version 1.2) and the CORBA Common Secure Interoperability version 2 (CSIv2) specification. CSIv2 support in WebLogic Server:

  • Interoperates with the Java 2 Enterprise Edition (Java EE) version 1.4 reference implementation.

  • Allows WebLogic Server IIOP clients to specify a username and password in the same manner as T3 clients.

  • Supports Generic Security Services Application Programming Interface (GSSAPI) initial context tokens. For this release, only usernames and passwords and GSSUP (Generic Security Services Username Password) tokens are supported.

    Note:

    The CSIv2 implementation in WebLogic Server passed Java 2 Enterprise Edition (Java EE) Compatibility Test Suite (CTS) conformance testing.

The external interface to the CSIv2 implementation is a JAAS LoginModule that retrieves the username and password of the CORBA object. The JAAS LoginModule can be used in a WebLogic Java client or in a WebLogic Server instance that acts as a client to another Java EE application server. The JAAS LoginModule for the CSIv2 support is called UsernamePasswordLoginModule, and is located in the weblogic.security.auth.login package.

CSIv2 works in the following manner:

  1. When creating a Security Extensions to Interoperable Object Reference (IOR), WebLogic Server adds a tagged component identifying the security mechanisms that the CORBA object supports. This tagged component includes transport information, client authentication information, and identity token/authorization token information.

  2. The client evaluates the security mechanisms in the IOR and selects the mechanism that supports the options required by the server.

  3. The client uses the SAS protocol to establish a security context with WebLogic Server. The SAS protocol defines messages contained within the service context of requests and replies. A context can be stateful or stateless.

For information about using CSIv2, see "Common Secure Interoperability Version 2" in Understanding Security for Oracle WebLogic Server. For more information about JAAS LoginModules, see LoginModules.

The Identity Assertion Process

In perimeter authentication, a system outside of WebLogic Server establishes trust via tokens (as opposed to the type of authentication described in The Authentication Process, where WebLogic Server establishes trust via usernames and passwords). Identity Assertion providers are used as part of perimeter authentication process, which works as follows (see Figure 5-2):

  1. A token from outside of WebLogic Server is passed to an Identity Assertion provider that is responsible for validating tokens of that type and that is configured as "active".

  2. If the token is successfully validated, the Identity Assertion provider maps the token to a WebLogic Server username, and sends that username back to WebLogic Server, which then continues the authentication process as described in The Authentication Process. Specifically, the username is sent via a Java Authentication and Authorization Service (JAAS) CallbackHandler and passed to each configured Authentication provider's LoginModule, so that the LoginModule can populate the subject with the appropriate principals.

Figure 5-2 Perimeter Authentication

Description of Figure 5-2 follows
Description of "Figure 5-2 Perimeter Authentication"

As Figure 5-2 also shows, perimeter authentication requires the same components as the authentication process described in The Authentication Process, but also adds an Identity Assertion provider.

Do You Need to Develop a Custom Identity Assertion Provider?

The WebLogic Identity Assertion providers support certificate authentication using X509 certificates, SPNEGO tokens, SAML assertion tokens, and CORBA Common Secure Interoperability version 2 (CSIv2) identity assertion.

The LDAP X509 Identity Assertion provider receives an X509 certificate, looks up the LDAP object for the user associated with that certificate, ensures that the certificate in the LDAP object matches the presented certificate, and then retrieves the name of the user from the LDAP object for the purpose of authentication.

The Negotiate Identity Assertion provider is used for SSO with Microsoft clients that support the SPNEGO protocol. The Negotiate Identity Assertion provider decodes SPNEGO tokens to obtain Kerberos tokens, validates the Kerberos tokens, and maps Kerberos tokens to WebLogic users. The Negotiate Identity Assertion provider utilizes the Java Generic Security Service (GSS) Application Programming Interface (API) to accept the GSS security context via Kerberos. The Negotiate Identity Assertion provider is for Windows NT Integrated Login.

The SAML Identity Assertion providers handle SAML assertion tokens when WebLogic Server acts as a SAML destination site. The SAML Identity Assertion providers consume and validate SAML assertion tokens and determines if the assertion is to be trusted (using either the proof material available in the SOAP message, the client certificate, or some other configuration indicator).

The default WebLogic Identity Assertion provider validates the token type, then maps X509 digital certificates and X501 distinguished names to WebLogic usernames. It also specifies a list of trusted client principals to use for CSIv2 identity assertion. The wildcard character (*) can be used to specify that all principals are trusted. If a client is not listed as a trusted client principal, the CSIv2 identity assertion fails and the invoke is rejected.

Note:

To use the WebLogic Identity Assertion provider for X.501 and X.509 certificates, you have the option of using the default user name mapper that is supplied with the WebLogic Server product (weblogic.security.providers.authentication.DefaultUserNameMapperImpl) or providing you own implementation of the weblogic.security.providers.authentication.UserNameMapper interface.

This interface maps a X.509 certificate to a WebLogic Server user name according to whatever scheme is appropriate for your needs. You can also use this interface to map from an X.501 distinguished name to a user name. You specify your implementation of this interface when you use the Administration Console to configure an Identity Assertion provider.

The WebLogic Identity Assertion providers support the following token types:

  • AU_TYPE, for a WebLogic AuthenticatedUser used as a token.

  • X509_TYPE, for an X509 client certificate used as a token.

  • CSI_PRINCIPAL_TYPE, for a CSIv2 principal name identity used as a token.

  • CSI_ANONYMOUS_TYPE, for a CSIv2 anonymous identity used as a token.

  • CSI_X509_CERTCHAIN_TYPE, for a CSIv2 X509 certificate chain identity used as a token.

  • CSI_DISTINGUISHED_NAME_TYPE, for a CSIv2 distinguished name identity used as a token.

  • AUTHORIZATION_NEGOTIATE, for a SPNEGO internal token used as a token.

  • SAML_ASSERTION_B64_TYPE, for a Base64 encoded SAML.assertion used as a token.

  • SAML_ASSERTION_DOM_TYPE, for a SAML DOM element used as a token.

  • SAML_ASSERTION_TYPE, for a SAML string XML form used as a token.

  • SAML2_ASSERTION_DOM_TYPE, for a SAML2 DOM element used as a token.

  • SAML2_ASSERTION_TYPE, for a SAML2 string XML form used as a token.

  • SAML_SSO_CREDENTIAL_TYPE, for a SAML string consisting of the TARGET parameter concatenated with the assertion itself and used as a token.

  • WSSE_PASSWORD_DIGEST_TYPE, for a username token with a password type of password digest used as a token.

  • WWW_AUTHENTICATE_NEGOTIATE, for a SPNEGO internal token used as a token.

If you want to perform additional identity assertion tasks or create new token types, then you need to develop a custom Identity Assertion provider.

How to Develop a Custom Identity Assertion Provider

If the WebLogic Identity Assertion provider does not meet your needs, you can develop a custom Identity Assertion provider by following these steps:

  1. Create Runtime Classes Using the Appropriate SSPIs

  2. Generate an MBean Type Using the WebLogic MBeanMaker

  3. Configure the Custom Identity Assertion Provider Using the Administration Console

  4. Consider whether you need to implement Challenge Identity Assertion, as described in Challenge Identity Assertion.

Create Runtime Classes Using the Appropriate SSPIs

Before you start creating runtime classes, you should first:

When you understand this information and have made your design decisions, create the runtime classes for your custom Identity Assertion provider by following these steps:

For an example of how to create a runtime class for a custom Identity Assertion provider, see Example: Creating the Runtime Class for the Sample Identity Assertion Provider.

Implement the AuthenticationProviderV2 SSPI

Note:

The AuthenticationProvider SSPI is deprecated in this release of WebLogic Server. Use the AuthenticationProviderV2 SSPI instead.

To implement the AuthenticationProviderV2 SSPI, provide implementations for the methods described in Understand the Purpose of the "Provider" SSPIs and the following methods:

  • getLoginModuleConfiguration

    public AppConfigurationEntry getLoginModuleConfiguration()
    

    The getLoginModuleConfiguration method obtains information about the Authentication provider's associated LoginModule, which is returned as an AppConfigurationEntry. The AppConfigurationEntry is a Java Authentication and Authorization Service (JAAS) class that contains the classname of the LoginModule; the LoginModule's control flag (which was passed in via the Authentication provider's associated MBean); and a configuration options map for the LoginModule (which allows other configuration information to be passed into the LoginModule).

    For more information about the AppConfigurationEntry class (located in the javax.security.auth.login package) and the control flag options for LoginModules, see the Java SE 6.0 API Specification for the AppConfigurationEntry class (http://download.oracle.com/javase/6/docs/api/javax/security/auth/login/AppConfigurationEntry.html) and the Configuration class (http://download.oracle.com/javase/6/docs/api/javax/security/auth/login/Configuration.html). For more information about LoginModules, see LoginModules. For more information about security providers and MBeans, see Understand Why You Need an MBean Type.

  • getAssertionModuleConfiguration

    public AppConfigurationEntry
    getAssertionModuleConfiguration()
    

    The getAssertionModuleConfiguration method obtains information about an Identity Assertion provider's associated LoginModule, which is returned as an AppConfigurationEntry. The AppConfigurationEntry is a JAAS class that contains the classname of the LoginModule; the LoginModule's control flag (which was passed in via the Identity Assertion provider's associated MBean); and a configuration options map for the LoginModule (which allows other configuration information to be passed into the LoginModule).

    The LoginModules in this configuration must populate the Subject with required Principals, such as those of type WLSGroup, and must trust that the user has submitted sufficient proof to login and not require a password or some other proof material.

    Note:

    The assertIdentity() method of an Identity Assertion provider is called every time identity assertion occurs, but the LoginModules may not be called if the Subject is cached. The -Dweblogic.security.identityAssertionTTL flag can be used to affect this behavior (for example, to modify the default TTL of 5 minutes or to disable the cache by setting the flag to -1).

    It is the responsibility of the Identity Assertion provider to ensure not just that the token is valid, but also that the user is still valid (for example, the user has not been deleted).

  • getPrincipalValidator

    public PrincipalValidator getPrincipalValidator()
    

    The getPrincipalValidator method obtains a reference to the Principal Validation provider's runtime class (that is, the PrincipalValidator SSPI implementation). For more information, see Chapter 6, "Principal Validation Providers."

  • getIdentityAsserter

    public IdentityAsserterV2 getIdentityAsserter()
    

    The getIdentityAsserter method obtains a reference to the Identity Assertion provider's runtime class (that is, the IdentityAsserterV2 SSPI implementation). For more information, see Implement the IdentityAsserterV2 SSPI.

    Note:

    When the LoginModule used for the Identity Assertion provider is the same as that used for an existing Authentication provider, implementations for the methods in the AuthenticationProviderV2 SSPI (excluding the getIdentityAsserter method) for Identity Assertion providers can just return null. An example of this is shown in Example 5-4.

For more information about the AuthenticationProvider SSPI and the methods described above, see the WebLogic Server API Reference Javadoc.

Implement the IdentityAsserterV2 SSPI

Note:

The IdentityAsserterV2 SSPI includes additional token types and a handler parameter to the assertIdentity method that can optionally be used to obtain additional information when asserting the identity. Although the IdentityAsserter SSPI is still supported, you should consider using the IdentityAsserterV2 SSPI instead.

To implement the IdentityAsserterV2 SSPI, provide implementations for the following method:

  • assertIdentity

    public CallbackHandler assertIdentity(String type, Object token, ContextHandler handler) throws IdentityAssertionException;
    

    The assertIdentity method asserts an identity based on the token identity information that is supplied. In other words, the purpose of this method is to validate any tokens that are not currently trusted against trusted client principals. The type parameter represents the token type to be used for the identity assertion. Note that identity assertion types are case insensitive. The token parameter contains the actual identity information. The handler parameter is a ContextHandler object that can optionally be used to obtain additional information that may be used in asserting the identity. The CallbackHandler returned from the assertIdentity method is passed to all configured Authentication providers' LoginModules to perform principal mapping, and should contain the asserted username. If the CallbackHandler is null, this signifies that the anonymous user should be used.

    A CallbackHandler is a highly-flexible JAAS standard that allows a variable number of arguments to be passed as complex objects to a method. For more information about CallbackHandlers, see the Java SE 6.0 API Specification for the CallbackHandler interface (http://download.oracle.com/javase/6/docs/api/javax/security/auth/callback/CallbackHandler.html).

    Notes:

    The assertIdentity() method of an Identity Assertion provider is called every time identity assertion occurs, but the LoginModules may not be called if the Subject is cached. The -Dweblogic.security.identityAssertionTTL flag can be used to affect this behavior (for example, to modify the default TTL of 5 minutes or to disable the cache by setting the flag to -1).

    It is the responsibility of the Identity Assertion provider to ensure not just that the token is valid, but also that the user is still valid (for example, the user has not been deleted).

For more information about the IdentityAsserterV2 SSPI and the method described above, see the WebLogic Server API Reference Javadoc.

Example: Creating the Runtime Class for the Sample Identity Assertion Provider

Example 5-4 shows the SampleIdentityAsserterProviderImpl.java class, which is the runtime class for the sample Identity Assertion provider. This runtime class includes implementations for:

Example 5-4 SampleIdentityAsserterProviderImpl.java

package examples.security.providers.identityassertion.simple;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.AppConfigurationEntry;
import weblogic.management.security.ProviderMBean;
import weblogic.security.service.ContextHandler;
import weblogic.security.spi.AuthenticationProviderV2;
import weblogic.security.spi.IdentityAsserterV2;
import weblogic.security.spi.IdentityAssertionException;
import weblogic.security.spi.PrincipalValidator;
import weblogic.security.spi.SecurityServices;
public final class SimpleSampleIdentityAsserterProviderImpl implements AuthenticationProviderV2,
IdentityAsserterV2
{
   final static private String TOKEN_TYPE   = "SamplePerimeterAtnToken";
   final static private String TOKEN_PREFIX = "username=";
   private String description; 
   public void initialize(ProviderMBean mbean, SecurityServices services)
   {
      System.out.println("SimpleSampleIdentityAsserterProviderImpl.initialize");
      SimpleSampleIdentityAsserterMBean myMBean = (SimpleSampleIdentityAsserterMBean)mbean;
      description = myMBean.getDescription() + "\n" + myMBean.getVersion();
   }
   public String getDescription()
   {
      return description;
   }
   public void shutdown()
   {
      System.out.println("SimpleSampleIdentityAsserterProviderImpl.shutdown");
   }
   public IdentityAsserterV2 getIdentityAsserter()
   {
      return this;
   }
   public CallbackHandler assertIdentity(String type, Object token, ContextHandler context) throws 
   IdentityAssertionException
   {
      System.out.println("SimpleSampleIdentityAsserterProviderImpl.assertIdentity");
      System.out.println("\tType\t\t= "  + type);
      System.out.println("\tToken\t\t= " + token);
      if (!(TOKEN_TYPE.equals(type))) {
         String error = "SimpleSampleIdentityAsserter received unknown token type \"" 
            + type + "\"." + " Expected " + TOKEN_TYPE;
         System.out.println("\tError: " + error);
         throw new IdentityAssertionException(error);
      }
      if (!(token instanceof byte[])) {
         String error = "SimpleSampleIdentityAsserter received unknown token class \"" 
            + token.getClass() + "\"." + " Expected a byte[].";
         System.out.println("\tError: " + error);
         throw new IdentityAssertionException(error);
      }
      byte[] tokenBytes = (byte[])token;
      if (tokenBytes == null || tokenBytes.length < 1) {
         String error = "SimpleSampleIdentityAsserter received empty token byte array";
         System.out.println("\tError: " + error);
         throw new IdentityAssertionException(error);
      }
      String tokenStr = new String(tokenBytes);
      if (!(tokenStr.startsWith(TOKEN_PREFIX))) {
         String error = "SimpleSampleIdentityAsserter received unknown token string \"" 
            + type + "\"." + " Expected " + TOKEN_PREFIX + "username";
         System.out.println("\tError: " + error);
         throw new IdentityAssertionException(error);
      }
      String userName = tokenStr.substring(TOKEN_PREFIX.length());
      System.out.println("\tuserName\t= " + userName);
      return new SimpleSampleCallbackHandlerImpl(userName);
   }
   public AppConfigurationEntry getLoginModuleConfiguration()
   {
      return null;
   }
   public AppConfigurationEntry getAssertionModuleConfiguration()
   {
      return null;
   }
   public PrincipalValidator getPrincipalValidator()
   {
      return null;
   }
}

Example 5-5 shows the sample CallbackHandler implementation that is used along with the SampleIdentityAsserterProviderImpl.java runtime class. This CallbackHandler implementation is used to send the username back to an Authentication provider's LoginModule.

Example 5-5 SampleCallbackHandlerImpl.java

package examples.security.providers.identityassertion.simple;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
/*package*/ class SimpleSimpleSampleCallbackHandler implements CallbackHandler
{
   private String userName;
   /*package*/ SimpleSampleCallbackHandlerImpl(String user)
   {
      userName = user;
   }
   public void handle(Callback[] callbacks) throws UnsupportedCallbackException
   {
      for (int i = 0; i < callbacks.length; i++) {
            Callback callback = callbacks[i];
            if (!(callback instanceof NameCallback)) {
               throw new UnsupportedCallbackException(callback, "Unrecognized 
                  Callback");
            }
            NameCallback nameCallback = (NameCallback)callback;
            nameCallback.setName(userName);
      }
   }
}

Generate an MBean Type Using the WebLogic MBeanMaker

Before you start generating an MBean type for your custom security provider, you should first:

When you understand this information and have made your design decisions, create the MBean type for your custom Identity Assertion provider by following these steps:

  1. Create an MBean Definition File (MDF)

  2. Use the WebLogic MBeanMaker to Generate the MBean Type

  3. Use the WebLogic MBeanMaker to Create the MBean JAR File (MJF)

  4. Install the MBean Type Into the WebLogic Server Environment

    Note:

    Several sample security providers (available at https://codesamples.samplecode.oracle.com/servlets/tracking?id=S224 on the Oracle Technology Network Web site) illustrate how to perform these steps.

    All instructions provided in this section assume that you are working in a Windows environment.

Create an MBean Definition File (MDF)

To create an MBean Definition File (MDF), follow these steps:

  1. Copy the MDF for the sample Identity Assertion provider to a text file.

    Note:

    The MDF for the sample Identity Assertion provider is called SampleIdentityAsserter.xml.
  2. Modify the content of the <MBeanType> and <MBeanAttribute> elements in your MDF so that they are appropriate for your custom Identity Assertion provider. For example, consider the following fragment to set the Base64DecodingRequired attribute to false:

    <MBeanAttribute
      Name         = "Base64DecodingRequired"
      Type         = "boolean"
      Writeable    = "false"
      Default      = "false"
      Description  = "See MyIdentityAsserter-doc.xml."
    />
    
  3. Add any custom attributes and operations (that is, additional <MBeanAttribute> and <MBeanOperation> elements) to your MDF.

  4. Save the file.

    Note:

    A complete reference of MDF element syntax is available in Appendix A, "MBean Definition File (MDF) Element Syntax."

Use the WebLogic MBeanMaker to Generate the MBean Type

Once you create your MDF, you are ready to run it through the WebLogic MBeanMaker. The WebLogic MBeanMaker is currently a command-line utility that takes as its input an MDF, and outputs some intermediate Java files, including an MBean interface, an MBean implementation, and an associated MBean information file. Together, these intermediate files form the MBean type for your custom security provider.

The instructions for generating an MBean type differ based on the design of your custom Identity Assertion provider. Follow the instructions that are appropriate to your situation:

No Optional SSPI MBeans and No Custom Operations

If the MDF for your custom Identity Assertion provider does not implement any optional SSPI MBeans and does not include any custom operations, follow these steps:

  1. Create a new DOS shell.

  2. Type the following command:

    java -DMDF=xmlfile -Dfiles=filesdir -DcreateStubs=true weblogic.management.commo.WebLogicMBeanMaker
    

    where the -DMDF flag indicates that the WebLogic MBeanMaker should translate the MDF into code, xmlFile is the MDF (the XML MBean Description File) and filesdir is the location where the WebLogic MBeanMaker will place the intermediate files for the MBean type.

    Whenever xmlfile is provided, a new set of output files is generated.

    Each time you use the -DcreateStubs=true flag, it overwrites any existing MBean implementation file.

    Note:

    As of version 9.0 of WebLogic Server, you can also provide a directory that contains multiple MDF's by using the -DMDFDIR <MDF directory name> option. In prior versions of WebLogic Server, the WebLogic MBeanMaker processed only one MDF at a time. Therefore, you had to repeat this process if you had multiple MDFs (in other words, multiple Identity Assertion providers).
  3. Proceed to Use the WebLogic MBeanMaker to Create the MBean JAR File (MJF).

Optional SSPI MBeans or Custom Operations

If the MDF for your custom Identity Assertion provider does implement some optional SSPI MBeans or does include custom operations, consider the following:

Are you creating an MBean type for the first time? If so, follow these steps:

  1. Create a new DOS shell.

  2. Type the following command:

    java -DMDF=xmlfile -Dfiles=filesdir -DcreateStubs=true weblogic.management.commo.WebLogicMBeanMaker
    

    where the -DMDF flag indicates that the WebLogic MBeanMaker should translate the MDF into code, xmlFile is the MDF (the XML MBean Description File) and filesdir is the location where the WebLogic MBeanMaker will place the intermediate files for the MBean type.

    Whenever xmlfile is provided, a new set of output files is generated.

    Each time you use the -DcreateStubs=true flag, it overwrites any existing MBean implementation file.

    Note:

    As of version 9.0 of WebLogic Server, you can also provide a directory that contains multiple MDF's by using the -DMDFDIR <MDF directory name> option. In prior versions of WebLogic Server, the WebLogic MBeanMaker processed only one MDF at a time. Therefore, you had to repeat this process if you had multiple MDFs (in other words, multiple Identity Assertion providers).
  3. If you implemented optional SSPI MBeans in your MDF, follow these steps:

    1. Locate the MBean implementation file.

      The MBean implementation file generated by the WebLogic MBeanMaker is named MBeanNameImpl.java. For example, for the MDF named SampleIdentityAsserter, the MBean implementation file to be edited is named SampleIdentityAsserterImpl.java.

    2. For each optional SSPI MBean that you implemented in your MDF, implement each method. Be sure to also provide implementations for any methods that the optional SSPI MBean inherits.

  4. If you included any custom operations in your MDF, implement the methods using the method stubs.

  5. Save the file.

  6. Proceed to Use the WebLogic MBeanMaker to Create the MBean JAR File (MJF).

Are you updating an existing MBean type? If so, follow these steps:

  1. Copy your existing MBean implementation file to a temporary directory so that your current method implementations are not overwritten by the WebLogic MBeanMaker.

  2. Create a new DOS shell.

  3. Type the following command:

    java -DMDF=xmlfile -Dfiles=filesdir -DcreateStubs=true weblogic.management.commo.WebLogicMBeanMaker
    

    where the -DMDF flag indicates that the WebLogic MBeanMaker should translate the MDF into code, xmlFile is the MDF (the XML MBean Description File) and filesdir is the location where the WebLogic MBeanMaker will place the intermediate files for the MBean type.

    Whenever xmlfile is provided, a new set of output files is generated.

    Each time you use the -DcreateStubs=true flag, it overwrites any existing MBean implementation file.

    Note:

    As of version 9.0 of WebLogic Server, you can also provide a directory that contains multiple MDF's by using the -DMDFDIR <MDF directory name> option. In prior versions of WebLogic Server, the WebLogic MBeanMaker processed only one MDF at a time. Therefore, you had to repeat this process if you had multiple MDFs (in other words, multiple Identity Assertion providers).
  4. If you implemented optional SSPI MBeans in your MDF, follow these steps:

    1. Locate and open the MBean implementation file.

      The MBean implementation file generated by the WebLogic MBeanMaker is named MBeanNameImpl.java. For example, for the MDF named SampleIdentityAsserter, the MBean implementation file to be edited is named SampleIdentityAsserterImpl.java.

    2. Open your existing MBean implementation file (which you saved to a temporary directory in step 1).

    3. Synchronize the existing MBean implementation file with the MBean implementation file generated by the WebLogic MBeanMaker.

      Accomplishing this task may include, but is not limited to: copying the method implementations from your existing MBean implementation file into the newly-generated MBean implementation file (or, alternatively, adding the new methods from the newly-generated MBean implementation file to your existing MBean implementation file), and verifying that any changes to method signatures are reflected in the version of the MBean implementation file that you are going to use (for methods that exist in both MBean implementation files).

    4. If you modified the MDF to implement optional SSPI MBeans that were not in the original MDF, implement each method. Be sure to also provide implementations for any methods that the optional SSPI MBean inherits.

  5. If you modified the MDF to include any custom operations that were not in the original MDF, implement the methods using the method stubs.

  6. Save the version of the MBean implementation file that is complete (that is, has all methods implemented).

  7. Copy this MBean implementation file into the directory where the WebLogic MBeanMaker placed the intermediate files for the MBean type. You specified this as filesdir in step 3. (You will be overriding the MBean implementation file generated by the WebLogic MBeanMaker as a result of step 3.)

  8. Proceed to Use the WebLogic MBeanMaker to Create the MBean JAR File (MJF).

About the Generated MBean Interface File

The MBean interface file is the client-side API to the MBean that your runtime class or your MBean implementation will use to obtain configuration data. It is typically used in the initialize method as described in Understand the Purpose of the "Provider" SSPIs.

Because the WebLogic MBeanMaker generates MBean types from the MDF you created, the generated MBean interface file will have the name of the MDF, plus the text "MBean" appended to it. For example, the result of running the SampleIdentityAsserter MDF through the WebLogic MBeanMaker will yield an MBean interface file called SampleIdentityAsserterMBean.java.

Use the WebLogic MBeanMaker to Create the MBean JAR File (MJF)

Once your have run your MDF through the WebLogic MBeanMaker to generate your intermediate files, and you have edited the MBean implementation file to supply implementations for the appropriate methods within it, you need to package the MBean files and the runtime classes for the custom Identity Assertion provider into an MBean JAR File (MJF). The WebLogic MBeanMaker also automates this process.

To create an MJF for your custom Identity Assertion provider, follow these steps:

  1. Create a new DOS shell.

  2. Type the following command:

    java -DMJF=jarfile -Dfiles=filesdir weblogic.management.commo.WebLogicMBeanMaker
    

    where the -DMJF flag indicates that the WebLogic MBeanMaker should build a JAR file containing the new MBean types, jarfile is the name for the MJF and filesdir is the location where the WebLogic MBeanMaker looks for the files to JAR into the MJF.

    Compilation occurs at this point, so errors are possible. If jarfile is provided, and no errors occur, an MJF is created with the specified name.

    Note:

    When you create a JAR file for a custom security provider, a set of XML binding classes and a schema are also generated. You can choose a namespace to associate with that schema. Doing so avoids the possibility that your custom classes will conflict with those provided by Oracle. The default for the namespace is vendor. You can change this default by passing the -targetNameSpace argument to the WebLogicMBeanMaker or the associated WLMBeanMaker ant task.

    If you want to update an existing MJF, simply delete the MJF and regenerate it. The WebLogic MBeanMaker also has a -DIncludeSource option, which controls whether source files are included into the resulting MJF. Source files include both the generated source and the MDF itself. The default is false. This option is ignored when -DMJF is not used.

The resulting MJF can be installed into your WebLogic Server environment, or distributed to your customers for installation into their WebLogic Server environments.

Install the MBean Type Into the WebLogic Server Environment

To install an MBean type into the WebLogic Server environment, copy the MJF into the WL_HOME\server\lib\mbeantypes directory, where WL_HOME is the top-level installation directory for WebLogic Server. This "deploys" your custom Identity Assertion provider—that is, it makes the custom Identity Assertion provider manageable from the WebLogic Server Administration Console.

Note:

WL_HOME\server\lib\mbeantypes is the default directory for installing MBean types. (Beginning with 9.0, security providers can be loaded from ...\domaindir\lib\mbeantypes as well.) However, if you want WebLogic Server to look for MBean types in additional directories, use the -Dweblogic.alternateTypesDirectory=<dir> command-line flag when starting your server, where <dir> is a comma-separated list of directory names. When you use this flag, WebLogic Server will always load MBean types from WL_HOME\server\lib\mbeantypes first, then will look in the additional directories and load all valid archives present in those directories (regardless of their extension). For example, if -Dweblogic.alternateTypesDirectory = dirX,dirY, WebLogic Server will first load MBean types from WL_HOME\server\lib\mbeantypes, then any valid archives present in dirX and dirY. If you instruct WebLogic Server to look in additional directories for MBean types and are using the Java Security Manager, you must also update the weblogic.policy file to grant appropriate permissions for the MBean type (and thus, the custom security provider). For more information, see "Using Java Security to Protect WebLogic Resources" in Programming Security for Oracle WebLogic Server.

You can create instances of the MBean type by configuring your custom Identity Assertion provider (see Configure the Custom Identity Assertion Provider Using the Administration Console), and then use those MBean instances from a GUI, from other Java code, or from APIs. For example, you can use the WebLogic Server Administration Console to get and set attributes and invoke operations, or you can develop other Java objects that instantiate MBeans and automatically respond to information that the MBeans supply. We recommend that you back up these MBean instances.

Configure the Custom Identity Assertion Provider Using the Administration Console

Configuring a custom Identity Assertion provider means that you are adding the custom Identity Assertion provider to your security realm, where it can be accessed by applications requiring identity assertion services.

Configuring custom security providers is an administrative task, but it is a task that may also be performed by developers of custom security providers.

Note:

The steps for configuring a custom Identity Assertion provider using the WebLogic Server Administration Console are described under "Configuring WebLogic Security Providers" in Securing Oracle WebLogic Server.

Challenge Identity Assertion

The Challenge Identity Asserter interface supports challenge response schemes in which multiple challenges, responses messages, and state are required. The Challenge Identity Asserter interface allows Identity Assertion providers to support authentication protocols such as Microsoft's Windows NT Challenge/Response (NTLM), Simple and Protected GSS-API Negotiation Mechanism (SPNEGO), and other challenge/response authentication mechanisms.

Challenge/Response Limitations in the Java Servlet API 2.3 Environment

The WebLogic Security Framework allows you to provide a custom Authentication and Identity Assertion provider. However, due to the nature of the Java Servlet API 2.3 specification, the interaction between the Authentication provider and the client or other servers is architecturally limited during the authentication process. This restricts authentication mechanisms to those that are compatible with the authentication mechanisms the Servlet container offers: basic, form, and certificate.

Servlet authentication filters, which are described in Chapter 13, "Servlet Authentication Filters" have fewer architecturally-dependence limitations; that is, they are not dependent on the authentication mechanisms offered by the servlet container. By allowing filters to be invoked prior to the container beginning the authentication process, a security realm can implement a wider scope of authentication mechanisms. For example, a servlet authentication filter could redirect the user to a SAML provider site for authentication.

Servlet authentication filters provide a convenient way to implement a challenge/response protocol in your environment. Filters allow your Challenge Identity Assertion interface to loop through your challenge/response mechanism as often as needed to complete the challenge.

Filters and The Role of the weblogic.security.services.Authentication Class

Servlet authentication filters allow you to implement a challenge/response protocol without being limited to the authentication mechanisms compatible with the Servlet container. However, because servlet authentication filters operate outside of the authentication environment provided by the Security Framework, they cannot depend on the Security Framework to determine provider context, and require an API to drive the multiple-challenge Identity Assertion process.

The weblogic.security.services.Authentication class has been extended to allow multiple challenge/response identity assertion from a servlet authentication filter. The methods and interface provide a wrapper for the ChallengeIdentityAsserterV2 and ProviderChallengeContext interfaces so that you can invoke them from a servlet authentication filter.

There is no other documented way to perform a multiple challenge/response dialog from a servlet authentication filter within the context of the Security Framework. Your servlet authentication filter cannot directly invoke the ChallengeIdentityAsserterV2 and ProviderChallengeContext interfaces.

Therefore, you need to implement the ChallengeIdentityAsserterV2 and ProviderChallengeContext interfaces, and then use the weblogic.security.services.Authentication methods and AppChallengeContext interface to invoke them from a servlet authentication filter.

Implement the ChallengeIdentityAsserterV2 Interface

The ChallengeIdentityAsserterV2 interface extends the IdentityAsserterV2 SSPI. You must implement the ChallengeIdentityAsserterV2 interface in addition to the IdentityAsserterV2 SSPI.

Provide an implementation for all of the IdentityAsserterV2 methods, and the following methods:

  • assertChallengeIdentity

    ProviderChallengeContext assertChallengeIdentity(String tokenType, Object token, ContextHandler handler)
    

    Use the supplied client token to establish client identity, possibly with multiple challenges. This method returns your implementation of the ProviderChallengeContext interface. The ProviderChallengeContext interface provides a means to query the state of the challenges.

  • continueChallengeIdentity

    void continueChallengeIdentity(ProviderChallengeContext context, String tokenType, Object token, 
    ContextHandler handler) 
    

    Use the supplied provider context and client token to continue establishing client identity.

  • getChallengeToken

    Object getChallengeToken(String type, ContextHandler handler) 
    

    This method returns the Identity Assertion provider's challenge token.

Implement the ProviderChallengeContext Interface

The ProviderChallengeContext interface provides a means to query the state of the challenges. It allows the assertChallengeIdentity and continueChallengeIdentity methods of the ChallengeIdentityAsserterV2 interface to return either the callback handler or a new challenge to which the client must respond.

To implement the ProviderChallengeContext interface, provide implementations for the following methods:

  • getCallbackHandler

    CallbackHandler getCallbackHandler() 
    

    This method returns the callback handler for the challenge identity assertion. Call this method only when the hasChallengeIdentityCompleted method returns true.

  • getChallengeToken

    Object getChallengeToken() 
    

    This method returns the challenge token for the challenge identity assertion. Call this method only when the hasChallengeIdentityCompleted method returns false.

  • hasChallengeIdentityCompleted

    boolean hasChallengeIdentityCompleted 
    

    This method returns whether the challenge identity assertion has completed. It returns true if the challenge identity assertion has completed, false if not. If true, the caller should use the getCallbackHandler method. If false, then the caller should use the getChallengeToken method.

Invoke the weblogic.security.services Challenge Identity Methods

Have your servlet authentication filter invoke the following weblogic.security.services.Authentication methods instead of calling the ChallengeIdentityAsserterV2 SSPI directly:

  • assertChallengeIdentity

    AppChallengeContext assertChallengeIdentity(String tokenType, Object token, AppContext appContext) 
    

    Use the supplied client token to establish client identity, possibly with multiple challenges. This method returns the context of the challenge identity assertion. This result may contain either the authenticated subject or an additional challenge to which the client must respond. The AppChallengeContext interface provides a means to query the state of the challenges.

  • continueChallengeIdentity

    void continueChallengeIdentity(AppChallengeContext context, String tokenType,
     Object token, AppContext appContext) 
    

    Use the supplied provider context and client token to continue establishing client identity.

  • getChallengeToken

    Object getChallengeToken 
    

    This method returns the initial challenge token for the challenge identity assertion.

Invoke the weblogic.security.services AppChallengeContext Methods

Have your servlet authentication filter invoke the following AppChallengeContext methods instead of invoking the ProviderChallengeContext interface directly:

  • getAuthenticatedSubject

    Subject getAuthenticatedSubject() 
    

    Returns the authenticated subject for the challenge identity assertion. Call this method only when the hasChallengeIdentityCompleted method returns true.

  • getChallengeToken

    Object getChallengeToken() 
    

    This method returns the challenge token for the challenge identity assertion. Call this method only when the hasChallengeIdentityCompleted method returns false.

  • hasChallengeIdentityCompleted

    boolean hasChallengeIdentityCompleted() 
    

    This method returns whether the challenge identity assertion has completed. It returns true if the challenge identity assertion has completed, false if not. If true, the caller should use the getCallbackHandler method. If false, then the caller should use the getChallengeToken method.

Implementing Challenge Identity Assertion from a Filter

In the following code flow, assume that the servlet authentication filter, which is described in Chapter 13, "Servlet Authentication Filters" handles the HTTP level interactions (Authorization and WWW-Authenticate) and is also responsible for calling the weblogic.security.services.Authentication methods and interfaces to drive the Challenge Identity Assertion process.

  1. Browser sends a request

  2. Filter sees requests and no Authorization header, so it calls the weblogic.security.services.Authentication getChallengeToken method to get an initial token and sends a 401 response with a WWW-Authenticate negotiate header back

  3. Browser sees 401 with WWW-Authenticate and responds with a new request and a Authorization Negotiate token.

    1. Filter sees this and calls the weblogic.security.services.Authentication assertChallengeIdentity method. assertChallengeIdentity takes the token as input, processes it according to whatever rules it needs to follow for the assertion process it is following (for example, if NTLM, then do whatever NTLM requires to process the token), and determine if that succeeded or not. assertChallengeIdentity returns your implementation of the AppChallengeContext interface.

    2. Filter calls appChallengeContext hasChallengeCompleted method. Use the AppChallengeContext hasChallengeIdentityCompleted method to see if the challenge has completed. For example, it can determine if the callback handler is not null, meaning that it contains a username, and return true. In this use it returns false, so it must issue another challenge to the client. The filter then calls AppChallengeContext getChallengeToken to get the token to challenge back with.

    3. Filter likely stores the AppChallengeContext somewhere such as a session attribute.

    4. Filter sends a 401 response with an WWW-Authenticate negotiate and the new token.

  4. Browser sees the new challenge and responds again with an Authorization header.

    1. Filter sees this and calls the weblogic.security.services.Authentication continueChallengeIdentity method.

    2. Filter calls the AppChallengeContext hasChallengeCompleted method. If it returns false another challenge is in order, so call the AppChallengeContext getChallengeToken method to get the token to challenge back with, and so forth. If it returned true, then the challenge has completed and the filter would then call AppChallengeContext getAuthenticatedSubject method and perform a runAs(subject, request).