Custom Post-Authentication Module in OAM and SP

This article shows how to implement a custom authentication plugin that will be invoked after Federation SSO is complete and that will:

For more information on how to design a custom Authentication Plugin, refer to the OAM Developer’s Guide, chapter 3, which describes how to develop such a module: http://docs.oracle.com/cd/E40329_01/dev.1112/e27134/authnapi.htm. Let’s focus on how to:

Federation Authentication Module

Important note: When using the Federation Test SP application, the Authentication Module is by-passed and as such, the plugins defined in such a module won’t be executed.

An OAM Authentication Module is:

The OOTB Federation Authentication Module, called FederationPlugin, is made of two plugins:

The orchestration can be seen by:

  1. Go to the OAM Administration Console: http(s)://oam-adminhost:oam-admin-port/oamconsole.
  2. Navigate to Access Manager , Authentication Modules.
  3. Open FederationScheme.
  4. Click on the Steps tab to see the plugins.
  5. Click on the Steps Orchestration tab to see the orchestration between the different plugins, and the plugin that is used to start the operation.

Description of the illustration Federation_Plugin_Screen.png

AssertionProcessing Plugin

The AssertionProcessing plugin is responsible for the validation and consumption of an incoming SSO Assertion, for the mapping of the Assertion to a local LDAP user record and returns the user’s identity as well as the content of the Assertion to OAM. The AuthenticationContext instance shared between the Authentications Plugins contains CredentialParam objects that allow the various plugins to communicate at runtime as well as the result of the authentication operation.

Authentication Context Data

Upon successful authentication, an OAM Authentication Plugin returns the following data in the AuthenticationContext:

The following CredentialParam instances contained in the Credential object of the AuthenticationContext

The following PluginResponse instances contained in the AuthenticationContext:

The name of the Identity Store where the user record is located

The Authentication Level if it was overridden during the Federation SP processing (see this article for more information: Art 27 Mapping Fed Authn Method to Authn Levels in OAM SP)

Assertion data, with each element being a standalone PluginResponse instance:

The data contained in the AuthenticationContext is used by OAM for further processing.

The Assertion data is made of the following elements:

Example

Let’s take the following example to examine the data that is returned by the AssertionProcessing plugin at the end of the flow:

The IdP partner in OAM/SP is bound to an IdP Attribute Profile with only one entry, which maps the SAML Attribute Name uid to the OAM Session Attribute Name userid In the example, the test user will be alice:

An example of the SAML 2.0 Assertion is:

<samlp:Response ..>
     <saml:Issuer ...>hLp://acme.com/idp</saml:Issuer>
     <samlp:Status>
         <samlp:StatusCode
 Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
     </samlp:Status>
     <saml:Assertion ...>
         <saml:Issuer ...>hLp://acme.com/idp</saml:Issuer>
         <dsig:Signature ...>
         ...
         </dsig:Signature>
         <saml:Subject>
 <saml:NameID ...>alice@oracle.com</saml:NameID>
             ...
         </saml:Subject>         <saml:Conditions ...>
          ...
         </saml:Conditions>         <saml:AuthnStatement ...>
         ...
         </saml:AuthnStatement>
         <saml:AttributeStatement ...>
             <saml:Attribute Name="userid" ...>
                 <saml:AttributeValue ...>alice</saml:AttributeValue>
             </saml:Attribute>
             <saml:Attribute Name="lastname" ...>
                 <saml:AttributeValue ...>Appleton</saml:AttributeValue>             </saml:Attribute>
             <saml:Attribute Name="firstname" ...>
                 <saml:AttributeValue ...>Alice</saml:AttributeValue>
             </saml:Attribute>
         </saml:AttributeStatement>
     </saml:Assertion>
 </samlp:Response>

After a successful processing of the SAML 2.0 Assertion and the mapping of the incoming SSO response to a local user record, the AssertionProcessing plugin returns to OAM the AuthenticationContext with the following data: The Subject containing:

The following CredentialParam instances contained in the Credential object of the AuthenticationContext

The following PluginResponse instances contained in the AuthenticationContext:

Custom Authentication Plugin

Overview

In this article, let’s assume that the OAM/SP deployment needs to support:

Using a Just-In-Time User Provisioning module that provides support for #1. To be able to meet the requirements for #2, a custom Authentication Plugin is needed that will:

For this example, the environment is made of:

The custom Authentication plugin is made of the following:

Those three elements is bundled in a JAR file that is then uploaded to the OAM server via the OAM Administration Console. Once uploaded and activated modify the Federation Authentication Module.

Java Class

The class implementing the custom Authentication plugin must adhere to the following:

The following code is an example of the custom plugin.

package postsp;
 import java.util.Hashtable;
 import java.util.Map;
 import java.util.Set;
 import javax.naming.Context;
 import javax.naming.NamingException;
 import javax.naming.directory.Attributes;
 import javax.naming.directory.BasicAttribute;
 import javax.naming.directory.BasicAttributes;
 import javax.naming.directory.DirContext;
 import javax.naming.directory.InitialDirContext;
 import javax.security.auth.Subject;
 import oracle.security.am.common.utilities.principal.OAMUserDNPrincipal;
 import oracle.security.am.common.utilities.principal.OAMUserPrincipal;
 import oracle.security.am.plugin.ExecutionStatus;
 import oracle.security.am.plugin.MonitoringData;
 import oracle.security.am.plugin.PluginAttributeContextType;
 import oracle.security.am.plugin.PluginResponse;
 import oracle.security.am.plugin.authn.AbstractAuthenticationPlugIn;
 import oracle.security.am.plugin.authn.AuthenticationContext;
 import oracle.security.am.plugin.authn.AuthenticationException;
 public class CustomAttributesUpdatePlugin extends
 AbstractAuthenticationPlugIn
 {
   public ExecutionStatus process(AuthenticationContext context)
               throws AuthenticationException {
     // user's ID and DN. Note: we are not making necessary checks for size/null to
     // keep the sample code minimal.
     Subject subject = context.getSubject();
     Set<OAMUserPrincipal> principalsUserID =
               subject.getPrincipals(OAMUserPrincipal.class);
     Set<OAMUserDNPrincipal> principalsDN =
               subject.getPrincipals(OAMUserDNPrincipal.class);
     String localUserID =
 (String)principalsUserID.iterator().next().getName();
     String localUserDN = (String)principalsDN.iterator().next().getName();
     // get the assertion data. Note: We are not making necessary checks for size/null to
     // keep the sample code minimal.
     PluginResponse partnerResponse = context.getResponse(               PluginAttributeContextType.SESSION, "fed.partner");
     String partnerName = (String)partnerResponse.getValue();     PluginResponse nameIDResponse = context.getResponse(
               PluginAttributeContextType.SESSION, "fed.nameidvalue");
     String nameID = (String)nameIDResponse.getValue();
     PluginResponse uidResponse = context.getResponse(
               PluginAttributeContextType.SESSION, "fed.aLr.uid");
     String uid = (String)uidResponse.getValue();
     PluginResponse firstnameResponse = context.getResponse(
               PluginAttributeContextType.SESSION, "fed.aLr.firstname");
     String firstname = (String)firstnameResponse.getValue();     PluginResponse lastnameResponse = context.getResponse(
               PluginAttributeContextType.SESSION, "fed.aLr.lastname");
     String lastname = (String)lastnameResponse.getValue();
     try {
       // open ldap connection
       Hashtable env = new Hashtable();
       env.put(Context.INITIAL_CONTEXT_FACTORY,
 "com.sun.jndi.ldap.LdapCtxFactory");
       env.put(Context.PROVIDER_URL, "ldap://host:port");
       env.put(Context.SECURITY_PRINCIPAL, "admin");
       env.put(Context.SECURITY_CREDENTIALS, "password");       DirContext ldapContext = new InitialDirContext(env);
       // modify user ldap record. Note: We are not making the necessary checks to
       // keep the sample code minimal.
       Attributes attributes = new BasicAttributes();
       attributes.put(new BasicAttribute("givenname", firstname));
       attributes.put(new BasicAttribute("sn", lastname));
       attributes.put(new BasicAttribute("mail", nameID));
       attributes.put(new BasicAttribute("uid", uid));
       ldapContext.modifyAttributes(localUserDN,
                          DirContext.REPLACE_ATTRIBUTE, attributes);
     }
     catch (NamingException ex) {
       throw new AuthenticationException(ex);
     }
     // return success, so that OAM can resume the flow
     return ExecutionStatus.SUCCESS;
   }
   public String getPluginName() {
     return "CustomAttributesUpdatePlugin";
   }
   public String getDescription() {
     return "Custom Attributes Update Plugin";
   }
   public Map<String, MonitoringData> getMonitoringData() {
     return null;
   }
   public boolean getMonitoringStatus() {
     return false;
   }
   public int getRevision() {
     return 10;
   }
   public void setMonitoringStatus(boolean arg0) {
   } }

Plugin Registration File

The custom Authentication plugin must be defined in a plugin XML file such as:

<Plugin type="Authentication">
<author>uid=admin</author>
<email>admin@example</email>
<creationDate>08:00:00,2014-01-15</creationDate>
<description>Custom Attributes Update Plugin</description>
<conhguration>
</conhguration>
</Plugin>

Important Note: The XML file must have the same name as the class implementing the plugin, in this case CustomAttributesUpdatePlugin.xml

See the OAM Developer’s Guide for more information

Manifest File

Before packaging the custom Authentication plugin in a JAR file, a MANIFEST.MF must be defined such as: Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: CustomAttributesUpdatePlugin Bundle-SymbolicName: CustomAttributesUpdatePlugin Bundle-Version: 10 Bundle-Activator: postsp.CustomAttributesUpdatePlugin Import-Package: org.osgi.framework;version=”1.3.0”,oracle.security.am.plugin,oracle.security.am.plugin.authn,oracle.security.am.common.utilities.principal,javax.naming,javax.naming.directory,javax.security.auth Bundle-RequiredExecutionEnvironment: JavaSE-1.6

See the OAM Developer’s Guide for more information

Note: The manifest file must include the Import-Package property which lists all the packages that are used in the plugin

Building the Plugin

Compiling

The following JAR files from the OAM deployment need to be used for compilation:

These files are found in the following locations:

In this example, we put the CustomAttributesUpdatePlugin.java file in a src/postsp folder:

bash-4.1$ ls -l src/postsp/ total 4
-rw-r--r-- 1 root root 4377 Oct 1 09:54 CustomAttributesUpdatePlugin.java

To compile, execute the following command:

$JDK_HOME/bin/javac -cp $IAM_HOME/oam/server/lib/plugin /felix.jar:$IAM_HOME/oam/server/lib/plugin/oam-
plugin.jar:$IAM_HOME/oam/server/lib/plugin/utilities.jar src/postsp /\*.java

Packaging the Custom Plugin

We created the MANIFEST.MF in the current directory based on the content listed in the previous section, and the CustomAttributesUpdatePlugin.xml in the src directory, which contains the plugin definition listed in the previous section.

find
.
./MANIFEST.MF
./src
./src/userauthn
./src/userauthn/CustomAttributesUpdatePlugin.class
./src/userauthn/CustomAttributesUpdatePlugin.java
./src/CustomAttributesUpdatePlugin.xml

To create the CustomAttributesUpdatePlugin.jar JAR file that contains the plugin and the required files, execute the following command:

jar cfvm CustomAttributesUpdatePlugin.jar MANIFEST.MF -C src/ . added manifest adding: CustomAttributesUpdatePlugin.xml(in = 238) (out= 158)(deflated 33%) adding: postsp/(in = 0) (out= 0)(stored 0%) adding: postsp/CustomAttributesUpdatePlugin.java(in = 4377) (out= 1206)(deflated 72%) adding: postsp/CustomAttributesUpdatePlugin.class(in = 3726) (out= 1667)(deflated 55%)

This creates the CustomAttributesUpdatePlugin.jar. To view the contents of the file:

unzip -l CustomAttributesUpdatePlugin.jar Archive: CustomAttributesUpdatePlugin.jar
Length Date Time Name
0 10-01-2014 10:04 META-INF/
542 10-01-2014 10:04 META-INF/MANIFEST.MF
238 10-01-2014 09:11 CustomAttributesUpdatePlugin.xml
0 10-01-2014 09:59 postsp/
4377 10-01-2014 09:54 postsp/CustomAttributesUpdatePlugin.java
3726 10-01-2014 09:54 postsp/CustomAttributesUpdatePlugin.class
8883   6  

Important Note: The JAR file must have the same name as the class implementing the plugin, in this case CustomAttributesUpdatePlugin.jar

Deploying the Custom Authentication Plugin

Perform the following steps to deploy the custom Authentication plugin in OAM:

  1. Go to the OAM Administration Console: http(s)://oam-adminhost:oam-admin-port/oamconsole
  2. Navigate to Access Manager, Plugins
  3. Click Import Plug-In
  4. Select the plugin JAR file (CustomAttributesUpdatePlugin.jar in this example)

Description of the illustration Specifying_Plug-in_JAR_file.png

The plugin will be in an uploaded state:

Description of the illustration Plug-in_loaded_Screen.png

You need to distribute the plugin to the runtime OAM servers and activate it:

  1. Select the plugin
  2. Click Distribute Selected The Activation Status tab of the plugin shows the state of the plugin

Description of the illustration Plug-in_Screen_with_Status.png

You need to activate the plugin:

  1. Select the plugin
  2. Click Activate Selected The Activation Status tab of the plugin shows the state of the plugin

Description of the illustration Plug-in_Screen_with_Status_Activated.png

Creating the Authentication Module

Create a new Federation Authentication Module, based on the existing FederationPlugin Authentication Module, which differs from the existing one:

Perform the following steps to create a new Authentication Module:

  1. Go to the OAM Administration Console: http(s)://oam-adminhost: oam-admin-port/oamconsole
  2. Navigate to Access Manager, Authentication Modules
  3. Click Create Authentication Module
  4. Select Create Custom Authentication Module
  5. Enter a Name (CustomFedModule for example)

Description of the illustration Creating_Authentication_Module.png

Perform the following steps to add steps to the new Authentication Module:

  1. Click on the Steps tab
  2. Click Add to add the FedAuthnRequestPlugin step:
  3. Click OK
  4. Description of the illustration Add_Authentication_Module.png

  5. Click Add to add the AssertionProcessing step:
  6. Click OK
  7. Description of the illustration Add_Assertion_Processing_Screen.png

  8. Click Add to add the AttributesUpdate step:
  9. Click OK

Description of the illustration Attributes_Update_Screen.png

The Steps tab shows:

Description of the illustration Steps_Screen.png

Perform the following steps to define the steps orchestration for the new Authentication Module:

  1. Click on the Steps Orchestration tab Select FedAuthnRequestPlugin as the Initial Step For FedAuthnRequestPlugin:
  2. Select success for On Success
  3. Select AssertionProcessing for On Failure Select failure for On Error
  4. Click Apply

Description of the illustration Define_Orchestration_Screen.png

Authentication Scheme

Before being able to protect resources with an Authentication Policy that uses the new Authentication Module, a new Authentication Scheme needs to be created, referencing that new custom module. This is required, since the Authentication Policy is bound to an Authentication Scheme, not an Authentication Module. To create a new Authentication Scheme for that custom module, perform the following steps:

  1. Go to the OAM Administration Console: http(s)://oam-adminhost:oam-admin-port/oamconsole
  2. Navigate to Access Manager , Authentication Schemes
  3. Click Create Authentication Scheme
  4. Enter a name (for example CustomFedScheme) and a description Set the Authentication Level to an acceptable value (2 in this example)
  5. Select FORM as the Challenge Method
  6. Set the Challenge Redirect URL (in this example, we set it to /oam/server/)
  7. Select the newly created custom Authentication Module (CustomFedModule in the example)
  8. Set the Challenge URL (/pages/servererror.jsp in this example)
  9. Set the Context Type (customWar for example)
  10. Set the Context Value (/oam here, since we don’t use any pages)
  11. Enter the following for the Challenge Parameters at least:
  12. Click Apply

Description of the illustration Authentication_Schemes_Screen.png

Test

Protect a resource with an Authentication Policy using the newly created Authentication Scheme. This invokes the custom Authentication Module. Prior to the Federation SSO, the LDAP user record for alice at OAM/SP is:

dn: cn=alice,ou=users,dc=us,dc=oracle,dc=com
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: top
givenName: al
title: manager
uid: alice
cn: alice
sn: APPLETON
userPassword:: e1NTSEE1MTJ9TXp0R2d0Si9GT1NzYUxvRXJqZW0rM1Q2eU5QMW9ZZmZ2Y3FkVWpaS1o1OFNGMy95ZDBueUxUbnllRi83SFRtS2JmOTJ0anY4TFd6di9UanliOGw4WFNQV1BxSnF3N mail: alice@oracle.com

After authentication, the IdP sends the following information for user alice in the SAML 2.0 Assertion:

After Federation SSO, the CustomAttributesUpdatePlugin has to update alice’s LDAP record so that sn, givenname, uid and mail are set to the values from the SAML Assertion. The LDAP user record for alice after the Federation SSO operation at OAM/SP is now:

dn: cn=alice,ou=users,dc=us,dc=oracle,dc=com
objectClass: person
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: top
givenName: Alice
title: manager
uid: alice
cn: alice
sn: Appleton
userPassword:: e1NTSEE1MTJ9TXp0R2d0Si9GT1NzYUxvRXJqZW0rM1Q2eU5QMW9ZZmZ2Y3FkVWpaS1o1OFNGMy95ZDBueUxUbnllRi83SFRtS2JmOTJ0anY4TFd6di9UanliOGw4WFNQV1BxSnF3N
mail: alice@oracle.com

More Learning Resources

Explore other labs on docs.oracle.com/learn or access more free learning content on the Oracle Learning YouTube channel. Additionally, visit education.oracle.com/learning-explorer to become an Oracle Learning Explorer.

For product documentation, visit Oracle Help Center.