Extending OpenAM

OpenAM services solve a wide range of access and federation management problems out of the box. Yet, OpenAM also exposes APIs and SPIs that enable you extend OpenAM services when built-in functionality does not fit your deployment.

This part of the guide covers OpenAM mechanisms for plugging in additional functionality not available out of the box.

Creating a Post Authentication Plugin

Post authentication plugins (PAP) let you include custom processing at the end of the authentication process, immediately before the subject is authenticated. Common uses of post authentication plugins include setting cookies and session variables. Post authentication plugins are often used in conjunction with policy agents. The post authentication plugin sets custom session properties, and then the policy agent injects the custom properties into the request header to the protected application.

Two issues should be considered when writing a post authentication plugin for an OpenAM deployment that uses stateless sessions:

Cookie size

You can set an unlimited number of session properties in a post authentication plugin. When OpenAM creates a stateless session, it writes the session properties into the session cookie, increasing the size of the cookie. Very large session cookies can exceed browser limitations. Therefore, when implementing a post authentication plugin in a deployment with stateless sessions, be sure to monitor the session cookie size and verify that you have not exceeded browser cookie size limits.

For more information about stateless session cookies, see "Session Cookies" in the Administration Guide.

Cookie security

The OpenAM administrator secures custom session properties residing on the OpenAM server for stateful sessions by using firewalls and other typical security techniques.

However, when using stateless sessions, custom session properties are written in cookies and reside on end users' systems. Cookies can be long-lasting and might represent a security issue if any session properties are of a sensitive nature. When developing a post authentication plugin for a deployment that uses stateless sessions, be sure that you are aware of the measures securing the session contained within the cookie.

For more information about stateless session cookie security, see "Stateless Session Cookie Security" in the Administration Guide.

This section explains how to create a post authentication plugin.

Designing Your Post Authentication Plugin

Your post authentication plugin class implements the AMPostAuthProcessInterface interface, and in particular the following three methods.

public void onLoginSuccess(
  Map requestParamsMap,
  HttpServletRequest request,
  HttpServletResponse response,
  SSOToken token
) throws AuthenticationException

public void onLoginFailure(
  Map requestParamsMap,
  HttpServletRequest request,
  HttpServletResponse response
) throws AuthenticationException

public void onLogout(
  HttpServletRequest request,
  HttpServletResponse response,
  SSOToken token
) throws AuthenticationException

OpenAM calls the onLoginSuccess() and onLoginFailure() methods immediately before informing the user of login success or failure, respectively. OpenAM calls the onLogout() method only when the user actively logs out, not when a user’s session times out.

See the OpenAM Java SDK API Specification for reference.

These methods can perform whatever processing you require. Yet, know that OpenAM calls your methods synchronously as part of the authentication process. Therefore, if your methods take a long time to complete, you will keep users waiting. Minimize the processing done in your post authentication methods.

Building Your Sample Post Authentication Plugin

The following example post authentication plugin sets a session property during successful login, writing to its debug log if the operation fails.

package com.forgerock.openam.examples;

import java.util.Map;

import com.iplanet.sso.SSOException;
import com.iplanet.sso.SSOToken;

import com.sun.identity.authentication.spi.AMPostAuthProcessInterface;
import com.sun.identity.authentication.spi.AuthenticationException;
import com.sun.identity.shared.debug.Debug;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class SamplePAP implements AMPostAuthProcessInterface {
    private final static String PROP_NAME = "MyProperty";
    private final static String PROP_VALUE = "MyValue";
    private final static String DEBUG_FILE = "SamplePAP";

    protected Debug debug = Debug.getInstance(DEBUG_FILE);

    public void onLoginSuccess(
            Map requestParamsMap,
            HttpServletRequest request,
            HttpServletResponse response,
            SSOToken token
    ) throws AuthenticationException {
        try {
            token.setProperty(PROP_NAME, PROP_VALUE);
        } catch (SSOException e) {
            debug.error("Unable to set property");
        }
    }

    public void onLoginFailure(
            Map requestParamsMap,
            HttpServletRequest request,
            HttpServletResponse response
    ) throws AuthenticationException {
        // Not used
    }

    public void onLogout(
            HttpServletRequest request,
            HttpServletResponse response,
            SSOToken token
    ) throws AuthenticationException {
        // Not used
    }
}

The sample post authentication plugin source is available online. Get a local clone so that you can try the sample on your system. In the sources you find the following files.

pom.xml

Apache Maven project file for the module

This file specifies how to build the sample post authentication plugin, and also specifies its dependencies on OpenAM components and on the Servlet API.

src/main/java/com/forgerock/openam/examples/SamplePAP.java

Core class for the sample post authentication plugin

Build the module using Apache Maven.

$ cd /path/to/openam-post-auth-sample
$ mvn install
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building openam-post-auth-sample 1.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------

...

[INFO]
[INFO] --- maven-jar-plugin:2.3.1:jar (default-jar) @ openam-post-auth-sample --
[INFO] Building jar: .../target/openam-post-auth-sample-1.0.0-SNAPSHOT.jar

...

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 6.727s
[INFO] Finished at: Mon Nov 25 17:07:23 CET 2013
[INFO] Final Memory: 20M/227M
[INFO] ------------------------------------------------------------------------

Copy the .jar to the WEB-INF/lib directory where you deployed OpenAM.

$ cp target/*.jar /path/to/tomcat/webapps/openam/WEB-INF/lib/

Restart OpenAM or the container in which it runs.

Configuring Your Post Authentication Plugin

You can associate post authentication plugins with realms or services (authentication chains). Where you configure the plugin depends on the scope to which the plugin should apply:

  • Plugins configured at the realm level are executed when authenticating to any authentication chain in the realm, provided the authentication chain does not have an associated plugin.

  • Plugins configured at the service level are executed if that authentication chain is used for authentication. Any plugins configured at the realm level will not execute.

In OpenAM Console, navigate to Realms > Realm Name > Authentication > Settings > Post Authentication Processing. In the Authentication Post Processing Classes list, add the sample plugin class, com.forgerock.openam.examples.SamplePAP, and then click Save.

Alternatively, you can configure sample plugin for the realm by using the ssoadm command.

$ ssoadm
  set-svc-attrs
  --adminid amadmin
  --password-file /tmp/pwd.txt
  --servicename iPlanetAMAuthService
  --realm /myRealm
  --attributevalues iplanet-am-auth-post-login-process-class=
  com.forgerock.openam.examples.SamplePAP

iPlanetAMAuthService under /myRealm was
  modified.

Testing Your Post Authentication Plugin

To test the sample post authentication plugin, login successfully to OpenAM in the scope where the plugin is configured. For example, if you configured your plugin for the realm, /myRealm, specify the realm in the login URL.

http://openam.example.com:8080/openam/UI/Login?realm=myRealm

Although as a user you do not notice anywhere in the user interface that OpenAM calls your plugin, a policy agent or custom client code could retrieve the session property that your plugin added to the user session.

Extending UMA Workflow with Extension Points

OpenAM provides a number of extension points for extending the UMA workflow. These extension points are provided as filters and are dynamically loaded by using the Java ServiceLoader framework during the UMA workflow.

The extension points available are described in the sections below:

Resource Set Registration Extension Point

OpenAM provides the ResourceRegistrationFilter extension point, which can be used to extend UMA resource set registration functionality.

Resource Set Registration Extension Methods
Method Parameters Description

beforeResourceRegistration

resourceSet (type: ResourceSetDescription)

Invoked before a resource set is registered in the backend.

Changes made to the __resourceSet__ object at this stage __will__ be persisted.

afterResourceRegistration

resourceSet (type: ResourceSetDescription)

Invoked after a resource set is registered in the backend.

Changes made to the __resourceSet__ object at this stage __will not__ be persisted.

Permission Request Extension Point

OpenAM provides the PermissionRequestFilter extension point, which can be used to extend UMA permission request functionality.

Permission Request Extension Methods
Method Parameters Description

onPermissionRequest

resourceSet (type: ResourceSetDescription)

__requestedScopes__ (type: `Set<String>`)
__requestingClientId__ (type: `String`)

Invoked before a permission request is created.

Authorization Request Extension Point

OpenAM provides the RequestAuthorizationFilter extension point, which can be used to extend UMA authorization functionality.

Authorization Request Extension Methods
Method Parameters Description

beforeAuthorization

permissionTicket (type: PermissionTicket)

__requestingParty__ (type: `Subject`)
__resourceOwner__ (type: `Subject`)

Invoked before authorization of a request is attempted.

Throws `UmaException` if authorization of the request should not be attempted.

afterAuthorization

isAuthorized (type: boolean)

__permissionTicket__ (type: `PermissionTicket`)
__requestingParty__ (type: `Subject`)
__resourceOwner__ (type: `Subject`)

Invoked before authorization of a request is attempted.

If the authorization request was successful, __isAuthorized__ will be `true`.

Resource Sharing Extension Point

OpenAM provides the ResourceDelegationFilter extension point, which can be used to extend UMA resource sharing functionality.

Resource Sharing Extension Methods
Method Parameters Description

beforeResourceShared

umaPolicy (type: UmaPolicy)

Invoked before creating a sharing policy for a resource.

Changes to the __umaPolicy__ object at this stage __will__ be persisted.
Throws `ResourceException` if a sharing policy for the resource should not be created.

afterResourceShared

umaPolicy (type: UmaPolicy)

Invoked after creating a sharing policy for a resource.

Changes to the __umaPolicy__ object at this stage __will not__ be persisted.

beforeResourceSharedModification

currentUmaPolicy (type: UmaPolicy)

__updatedUmaPolicy__ (type: `UmaPolicy`)

Invoked before altering the sharing policy of a resource.

Changes to the __updatedUmaPolicy__ object at this stage __will__ be persisted.
Throws `ResourceException` if the sharing policy of the resource should not be modified.

onResourceSharedDeletion

umaPolicy (type: UmaPolicy)

Invoked before deleting the sharing policy of a resource.

Throws `ResourceException` if the sharing policy of the resource should not be deleted.

beforeQueryResourceSets

userId (type: String)

__queryFilter__ (type: `QueryFilter<JsonPointer>`)

Invoked before querying the resource sets owned or shared with a user.

The __userId__ parameter provides the ID of the user making the query request.
The __queryFilter__ parameter provides the incoming request query filter.
Returns a `QueryFilter` that can be used to return the user's resource sets.