PingIDM 7.5.0

Authenticate using a trusted servlet filter

This sample demonstrates how to use a custom servlet filter and the Trusted Request Attribute Authentication Module to allow IDM to authenticate through another service.

To configure authentication using PingAM, refer to the sample platform setup documentation.

Prepare the sample

Before you start this sample, complete the following steps:

  1. Prepare a fresh IDM installation, as described in Prepare IDM.

  2. Download and install the Apache Maven build tool.

  3. Build the custom servlet filter bundle file:

    cd /path/to/openidm/samples/trusted-servlet-filter/filter
    mvn clean install
  4. Copy the newly built servlet bundle file to the openidm/bundle directory:

    cp target/sample-trusted-servletfilter-1.0.jar /path/to/openidm/bundle

The sample servlet filter

In the previous section, you built a bundle file from the Java file named SampleTrustedServletFilter.java, located in the directory /path/to/openidm/samples/trusted-servlet-filter/filter/src/main/java/org/forgerock/openidm/sample/trustedservletfilter.

The following line from the file looks for the X-Special-Trusted-User header, to identify a specific User ID as a "trusted" user.

final String specialHeader = ((HttpServletRequest) servletRequest).getHeader("X-Special-Trusted-User");

The next line sets the special Servlet attribute X-ForgeRock-AuthenticationId to this trusted User ID.

servletRequest.setAttribute("X-ForgeRock-AuthenticationId", specialHeader);

The rest of the servlet filter chain continues request processing:

filterChain.doFilter(servletRequest, servletResponse);

This sample includes a servletfilter-trust.json file that calls the compiled IDM trusted servlet filterClass:

{
   "classPathURLs" : [ ],
   "systemProperties" : { },
   "requestAttributes" : { },
   "scriptExtensions" : { },
   "initParams" : { },
   "urlPatterns" : [
      "/*"
   ],
   "filterClass" : "org.forgerock.openidm.sample.trustedservletfilter.SampleTrustedServletFilter"
}

Run the sample

In this section, you will demonstrate the servlet filter by configuring it with the special header described in the previous section. Normally, a servlet filter used for authentication does not let a client masquerade as any user. This sample demonstrates a basic use of a servlet filter by establishing the authentication ID.

  1. Start IDM with the configuration for the trusted filter sample:

    cd /path/to/openidm/
    ./startup.sh -p samples/trusted-servlet-filter
  2. Create a new managed user, Barbara Jensen, with userName bjensen:

    curl \
    --header "X-OpenIDM-Username: openidm-admin" \
    --header "X-OpenIDM-Password: openidm-admin" \
    --header "Accept-API-Version: resource=1.0" \
    --header "Content-Type: application/json" \
    --request POST \
    --data '
       {
          "userName": "bjensen",
          "telephoneNumber": "6669876987",
          "givenName": "Barbara",
          "sn": "Jensen",
          "description": "Example User",
          "mail": "bjensen@example.com",
          "authzRoles" : [
             {
                "_ref" : "internal/role/openidm-authorized"
             }
          ]
       }' \
    "http://localhost:8080/openidm/managed/user"
    {
      "_id": "9dce06d4-2fc1-4830-a92b-bd35c2f6bcbb",
      "_rev": "000000004988917b",
      "userName": "bjensen",
      "telephoneNumber": "6669876987",
      "givenName": "Barbara",
      "sn": "Jensen",
      "description": "Example User",
      "mail": "bjensen@example.com",
      "accountStatus": "active",
      "effectiveRoles": [],
      "effectiveAssignments": [],
      "memberOfOrgIDs": [],
      "effectiveAssignments": []
    }

    Note the ID of the new user—you will need it in the steps that follow.

  3. Use the special request header X-Special-Trusted-User to authenticate bjensen (specifying her ID as the header value).

    curl \
    --header "X-Special-Trusted-User: 9dce06d4-2fc1-4830-a92b-bd35c2f6bcbb" \
    --header "Accept-API-Version: resource=1.0" \
    --request GET \
    "http://localhost:8080/openidm/info/login?_fields=authenticationId,authorization"
    {
      "_id": "login",
      "authenticationId": "9dce06d4-2fc1-4830-a92b-bd35c2f6bcbb",
      "authorization": {
        "userRolesProperty": "authzRoles",
        "component": "managed/user",
        "authLogin": false,
        "authenticationIdProperty": "userName",
        "roles": [
          "internal/role/openidm-authorized"
        ],
        "ipAddress": "127.0.0.1",
        "id": "9dce06d4-2fc1-4830-a92b-bd35c2f6bcbb",
        "moduleId": "TRUSTED_ATTRIBUTE"
      }
    }

    Note that the output includes the user’s authentication and authorization details. In this case, bjensen, with ID 9dce06d4-2fc1-4830-a92b-bd35c2f6bcbb is authenticated with the openidm-authorized role.

Customize the sample for an external system

To customize this sample for an external authentication/authorization system, you need a servlet filter which authenticates against that external system. You may use a third-party supplied filter, or develop your own filter, using the one in this sample as a model.

The filter you use should have at least the following capabilities:

  • Perform REST calls to another system.

  • Search through databases.

  • Inspect headers related to authentication and authorization requests.

This servlet filter must set the username of the authenticated user in a special request attribute. You need to configure that same attribute name in the TRUSTED_ATTRIBUTE authentication module, specifically the value of authenticationIdAttribute.

It is helpful if you have a filter that returns an object with the userRoles property. If your filter does not support queries using the following parameter:

queryOnResource + "/" + authenticationId

You will need to provide a security context augmentation script that populates the following authorization properties in the "security" object:

  • security.authorization.component

  • security.authorization.roles

The value for the security.authorization.component is automatically set to the value specified in any existing queryOnResource property.