ISAM

Linking Client Certificates to an ISAM Account

Share this post:

As a part of my job I am frequently contacted by technologists that use IBM Security Access Manager (ISAM) trying to build a solution for identity and access management scenarios. In fact, it’s one of the fun parts of what I do – it gives me a chance to problem solve and dabble with one of the products we build. I get to experiment with our latest features and I get the opportunity to piece those features together in novel ways to provide real solutions to real people’s problems.

One such engagement passed my way this week that I found it sufficiently interesting to share.

 

The problem

Employees have an account in ISAM and today they login with regular LDAP-based username and password authentication for browser  scenarios. These same employees have now been issued with staff badges (let’s say smart cards) that they can use with their computers (and a browser plug-in) to perform client certificate authentication. Whether or not it’s a staff badge with a browser plug-in, or some other issued client certificate solution is irrelevant. The key point is that staff now have access to a client certificate for authentication but there is no ISAM server-side correlation established between the client certificate and the user who possesses that certificate.

The ask is for a solution where an employee can self-service link their certificate to their account and then subsequently use that certificate for future authentication to the same ISAM account. There may be applications for which certificate authentication is required, but it’s also possible to just use the certificate as a more convenient way to login than username/password and consider the two methods of equivalent “strength”.

 

Solutions Overview

My first thoughts about this problem space got me thinking about “aliases for an account”, and a series of articles I wrote years ago on this topic. It was so long ago in fact that the articles have been archived from their original web format but can still be found as PDF’s here:

 

At the time I was experimenting with linking OpenID 2.0 identifiers, and even Information Cards to an account and using them for self-registration. Ultimately these were just cryptographically provable aliases for an account, and quite honestly certificate serial numbers extracted from a trusted issuer are no different. What is different is the technology platform. The ISAM appliance has essentially replaced Tivoli Federated Identity Manager for on-premise access and federation technologies from IBM. ISAM brings much more capability to the table, and some of these new built-in capabilities allow us to implement a solution to the certificate linking scenario with minimal customisation.

The solution I put together for this scenario makes use of the following ISAM technical capabilities:

  • Step-up authentication. This is the ability to require, for certain web resources, a second authentication method when the user is already authenticated with a primary authentication method. In our case the username/password is the first authentication method, and client certificate authentication is the second authentication method.
  • Advanced configuration of the web reverse proxy (formerly WebSEAL) using a secondary port for “prompt_as_needed” client certificate authentication.
  • The EAI certificate authentication  capability for enabling externalised programmatic mapping from client certificate attributes to a local account during client certificate authentication processing.
  • The authentication service built into ISAM’s Advanced Access Control, including the new scriptable Infomap authentication mechanism. This service can be used as the implementation of the externalised EAI certificate authentication described above. I consider this use of an AAC authentication policy as the certificate EAI implementation as the most novel aspect of the entire solution.
  • Use of ISAM APIs callable from Javascript on ISAM to interact directly with the user registry to store and retrieve linked certificate information. The Javadoc for these APIs needs to be downloaded from the File Downloads menu in your ISAM appliance, however I found this article from my colleague Philip Nye provides a brief introduction to their use (UserLookupHelper and User classes).
  • Minimal customisation of the ISAM template pages to rationalise the user experience.

Architecturally, the solution looks like this:

 

 

Technical Details

This section breaks down the configuration of the solution by the various technical product capabilities:

Configuring certificate authentication and step-up authentication for the certificate linking process

Certificate authentication requires that the CA cert chain of the issuer of your client certificates be added to the pdsrv keystore in ISAM. In my test environment I used a self-signed client cert I called “linked certificate”, so I just added it’s public key to the pdsrv keystore in my ISAM appliance:

Certificate authentication also requires a number of changes to the web reverse proxy configuration files. Due to the way TLS is negotiated with client certificates (particularly in Chrome) I found I needed to follow the guidance for secondary port configuration in this technote.

In summary, my key reverse proxy configuration file settings are shown here:

[certificate]
accept-client-certs = prompt_as_needed
secondary-port = 444
eai-uri = /certeai/sps/authsvc?PolicyId=urn:ibm:security:authentication:asf:cert_eai
eai-data = SerialNumber:serialnumber

[server]
cache-host-header = yes

[interfaces]
# This will change based on the ip and the server SSL certificate label you are using for your WebSEAL
interface1 = network-interface=192.168.42.102;https-port=444;certificate-label=www.myidp.ibm.com;accept-client-certs=required;always-neg-tls=yes

[authentication-levels]
level = unauthenticated
level = password
level = ssl

You can see from the eai-uri above that we need to create a junction to the ISAM AAC runtime called /certeai. First import the “localhost:443” certificate into the pdsrv keystore (this is the Local Runtime cert you can see in my earlier screenshot), then create the junction:

pdadmin> server task default-webseald-localhost create -t ssl -h localhost -p 443 -c iv_user,iv_user_l,iv_creds -b ignore /certeai

There is a special reason that the -c switch explicitly calls out iv_user_l. You will see why later in the Infomap rule…

We only utilise step-up authentication on a resource to guide the user through the process of linking their certificate to their account. It can also be used for applications where certificate authentication is considered stronger and required (rather than just a more convenient form of authentication than username/password). Such step-up authentication is controlled with a POP in ISAM, which can be attached to any web resource. If you consider certificate authentication as a convenience mechanism only, you would only need to attach the POP to the one location used when you guide employees through certificate linking.

For the purposes of this demonstration, we’ll use a static content page as the “landing” page for account linking. This will have the level2 POP (for step-up to certificate authentication) attached to it. Create that page as shown, or use a different application landing page if you wish:

Using pdadmin (or via API), create the following ACL and POP ISAM policy templates and attachments as shown, making adjustments for your WebSEAL management root as needed:

#
# Create a "nobody" ACL attached to the /certeai junction since
# it should never be called via a browser
# WebSEAL calls to the /certeai internally
#
acl create nobody
acl modify nobody set group iv-admin TcmdbsvaBRrxl
acl modify nobody set group webseal-servers Tgmdbsrxl
acl modify nobody set user sec_master TcmdbsvaBRrxl
acl modify nobody set any-other T
acl modify nobody set unauthenticated T
acl attach /WebSEAL/localhost-default/certeai nobody

#
# Create a level2pop attached to the certificate linking landing
# page. You can also attach it to any other web resource (such as
# application junctions) you want protected with certificate
# authentication.
#
pop create level2pop
pop modify level2pop set ipauth anyothernw 2
pop attach /WebSEAL/localhost-default/linking.html level2pop

server replicate

Configuring the Certificate EAI implementation as an AAC authentication policy

Not too long back I published another article on Infomap authentication: An Introduction to the InfoMap Authentication Mechanism in ISAM 9.0.2

Please review that article to understand the principals of the authentication service including authentication policies and authentication mechanisms.

Uploading the Infomap mapping rule and creating the authentication mechanism

Upload the following mapping rule to Advanced Access Control, called CertificateEAI. The rule contains lots of comments to explain what it is doing:

/********************* START OF MAPPING RULE *********************/
importClass(Packages.com.tivoli.am.fim.trustserver.sts.utilities.IDMappingExtUtils);
importClass(Packages.com.ibm.security.access.user.UserLookupHelper);

/*
* This rule is to be used within an InfoMap authentication mechanism to
* manage certificate EAI processing.
*/
var CERT_SERIAL_LDAP_ATTR = "businessCategory";

/**
* Finds the username of a user with a linked cert serial number, or null of it's not linked to an existing user
*/
function findLinkedUser(lh,sn) {
  var result = null;
  var strs = lh.search(CERT_SERIAL_LDAP_ATTR, sn, 1);
  if (strs != null && strs.length > 0) {
    var ldapUser = lh.getUserByNativeId(strs[0]);
    if (ldapUser != null) {
      result = ldapUser.getId();
    }
  }

  return result;
}

/**
* Links a certificate serial number to a user
*/
function linkCertificate(lh,u,sn) {
  var ldapUser = lh.getUser(u);
  if (ldapUser != null) {
    ldapUser.addAttribute(CERT_SERIAL_LDAP_ATTR,sn);
    // this is just for info/display, not used in any other logic
    context.set(Scope.SESSION, "urn:ibm:security:asf:response:token:attributes", "just_linked", "true");
  }
}

/**
* Sets up context to login as user
*/
function login(u) {
  context.set(Scope.SESSION, "urn:ibm:security:asf:response:token:attributes", "username", u);
  context.set(Scope.SESSION, "urn:ibm:security:asf:response:token:attributes", "AUTHENTICATION_LEVEL", "2");
}

/////////////// MAIN LOGIC STARTS HERE

// Create a user lookup helper. This one uses the ISAM Runtime configuration.
// Requires bind-dn and bind-pwd in ldap.conf
var ulh = new UserLookupHelper();
ulh.init();

// get username from already authenticated user if it exists
var username = context.get(Scope.REQUEST, "urn:ibm:security:asf:request:token:attribute", "username");

// get the certificate serial number
var certSerialNumber = context.get(Scope.REQUEST, "urn:ibm:security:asf:request:header", "SerialNumber");

// find out the username of any account this might be linked to already
var linkedUser = findLinkedUser(ulh,certSerialNumber);

// useful trace
IDMappingExtUtils.traceString("username: " + username + " certSerialNumber: " + certSerialNumber + " linkedUser: " + linkedUser);

var result = false;

//
// This piece of magic ensures that the authentication policy was only called via the /certeai junction.
// That junction has an acl on it to prevent a client spoofing a request to the cert eai policy
// in cases where the runtime may also have another junction to it for use of the AAC for other purposes.
// The /certeai junction is the only one where iv_user_l is passed.
//
var iv_user_l = context.get(Scope.REQUEST, "urn:ibm:security:asf:request:header", "iv-user-l");
IDMappingExtUtils.traceString("iv_user_l: " + iv_user_l);
if (iv_user_l != null) {

  /*
   * First branch on whether or not the session is for a currently authenticated user
   */
  if (username != null && username.length() > 0) {
    // existing user session

    // is the certSerialNumber already linked to an account?
    if (linkedUser != null) {
      // is the same as the currently authenticated user?
      if (username == linkedUser) {
        // ok, log them in. They are just re-presenting what is already linked
        login(username);
        result = true;
      } else {
        // error - user is logged in but presented a cert that is linked to another account
        result = false;
      }
    } else {
      // linkedUser is null - link this certificate to the currently logged in user and proceed
      IDMappingExtUtils.traceString("Linking certSerialNumber: " + certSerialNumber + " to username: " + username);
      linkCertificate(ulh,username,certSerialNumber);
      login(username);
      result = true;
    }
  } else {
    // no currently authenticated user

    // is the certSerialNumber linked to an existing account?
    if (linkedUser != null) {
      // login as the linked user
      login(linkedUser);
      result = true;
    } else {
      // no authenticated user and cert not currently linked - error
      result = false;
    }
  }
} else {
// looks like this auth policy was called via a junction other than /app which had the iv_user_l header turned on.
}

success.setValue(result);
/********************* END OF MAPPING RULE *********************/

 

Create a new Infomap authentication mechanism, called CertificateEAI with mechanism uri:

urn:ibm:security:authentication:asf:mechanism:cert_eai

Use the CertificateEAI mapping rule (and no page) to configure the Infomap mechanism:

 

Creating the AAC authentication Policy

Create a new authentication policy with mechanism uri:

urn:ibm:security:authentication:asf:cert_eai

Note that this matches the PolicyId in the [certificate] eai-uri configured in the reverse proxy configuration file.

The authentication policy should have ONLY the Infomap mechanism configured in it:

Update the ldap.conf file to enable UserLookupHelper to work against ISAM Registry

In order for the UserLookupHelper we used in the Infomap rule to initialise properly, the bind-dn and bind-pwd must be updated in the ISAM runtime’s ldap.conf. The javadoc for UserLookupHelper (downloadable from the File Downloads section of the appliance) explains more about this and other ways to initialise the UserLookupHelper.

For our purposes where the users are defined in ISAM LDAP, update the ldap.conf file with a bind-dn and bind-pwd as shown. The password for your LDAP will be automatically obfuscated when you save the file:

Replacing WebSEAL page templates

I have made some very simple and minimal updates to a number of the WebSEAL template files that are served up during authentication flows. These files are:

  • login.html
  • certlogin.html
  • stepuplogin.html
  • help.html

A tarball of all the modified files is available here.

They are configured in ISAM here:

The solution will work fine with the out-of-the-box page templates, however I have added specific messages in the templates that make it more applicable to the certificate linking scenario.

Diff my provided files against the originals to understand the changes that were made.

Testing the Solution

This section walks through the typical user experience for someone linking their certificate to an existing account. It assumes you have an existing ISAM user that can login via username/password (I use “testuser”), and a certificate installed on your browser. The CA trust chain for the certificate should be in WebSEAL’s pdsrv keystore. The certificate is not linked to any ISAM account.

The user accesses the linking page, in my case: https://www.myidp.ibm.com/linking.html and is presented with the certlogin.html page. It has been customized as shown below. As the user has no linked certificate, first login with username and password:

The user is now authenticated, however because the level2pop is attached to linking.html, you are now challenged for step-up certificate authentication (stepuplogin.html), which has been modified as shown:

Press the button to initiate certificate login, and present your certificate (Firefox example shown). You should finish up on the rather uninteresting linking page:

At this point the certificate is linked to the user’s account, and the user is logged in at authentication level 2. An LDAP search reveals the certificate serial number as a value of the businessCategory attribute for the user:

ldapsearch -H ldaps://isam.myidp.ibm.com:636 -D cn=root,secAuthority=Default -w passw0rd -b cn=testuser,dc=iswga businessCategory

# testuser, iswga
dn: cn=testuser,dc=iswga
businessCategory: 7d:99:71:8e:f1:86:c1:69

If you have read some of my earlier articles, you will know I am a firm believer in developers being able to see their ISAM credentials so that you can inspect the attributes and see how you have logged in. I have hosted an epac viewer on Bluemix and you are welcome to junction to it (no guarantees it will always be available). Just pass the -c iv_creds header and it will print your epac:

padmin> server task default-webseald-localhost create -t tcp -h genericeai.mybluemix.net -p 80 -c all /genericeai

Then in your browser visit https://www.myidp.ibm.com/genericeai/epac.jsp

Notice the just_linked attribute, and how it’s inserted into the credential from the Infomap code?!

Further exercises

There are other experiences you can try as well, such as:

  • From an unauthenticated state, try to perform certificate authentication using a certificate not linked to any account. This will result in an error.
  • From an authenticated state, try to step-up authenticate using a certificate that is linked to another user. This will result in an error. It would be fairly trivial to modify the Infomap code to unlink from the currently-linked user and re-link to the currently-authenticated user if you wished.
  • From an authenticated state using an account that already has a linked certificate, try to step-up authenticate with a certificate not linked to any account (this is linking more than one certificate to your account). This should be successful and if you run the ldapsearch you should see two businessCategory values. In future you can use either certificate to authenticate. You could also modify the Infomap code to “replace” rather than “add” the linked attribute.

Summary

In this article I have demonstrated how to combine some of ISAM’s advanced features to implement a solution for allowing users to self-service link a client certificate to an existing ISAM account. I hope the detailed technical explanations have given you a deeper understanding of ISAM and in particular certificate authentication, the certificate EAI, and the authentication service in advanced access control.

Till next time – Cheers!

-Shane.

 

 

 

 

More stories

ISAM FIDO2 – Metadata and registration policy enforcement

This article is the third in a technical series on configuring and using FIDO2 capabilities in ISAM 9.0.7. If you haven’t already done so, please read and complete the exercises in my first and second FIDO2 technical articles as here I’ll be picking up where the second article left off. What authenticator is that? Let’s take […]

Continue reading

ISAM FIDO2 – Usernameless login and Mediators

This article is the second in a technical series on configuring and using FIDO2 capabilities in ISAM 9.0.7. If you haven’t already done so, please read and complete the exercises in my first FIDO2 technical article as here I’ll be picking up where that one left off. Configuring a credential viewer Anyone working with ISAM […]

Continue reading

FIDO2 in less than 15 minutes with ISAM 9.0.7

In this article I’m going to show you how to configure FIDO2 on ISAM and get simple WebAuthn registration and authentication flows working. The pre-requisite is that you have an ISAM 9.0.7 system with a web reverse proxy and advanced access control configured and working. From there our 15 minute goal to getting FIDO2/WebAuthn running […]

Continue reading