IBM Security Global Forum

 View Only

Protecting entire ISAM WebSEAL site with multi-factor authentication using stepup login

By Shane Weeden posted Wed March 18, 2020 12:00 AM


Today I’m going a bit old-school with information on a basic ISAM scenario that has been available for years. This has come up in field questions several times recently, I think mostly with people who are relatively new to ISAM but understand the need for multi-factor security as a standard part of the authentication workflow. Basically the scenario is this:

I want my initial login process to be multi-factor authentication (MFA). The first step of user authentication is regular WebSEAL username/password authentication, and the second step an Advanced Access Control (AAC) authentication policy. How do I seamlessly force the user to complete the AAC authentication policy after username/password login?

This article is going to focus on just the above scenario. There are alternative approaches, such as not using regular WebSEAL forms-based username/password login and instead making the Username Password AAC module the first part of a multi-mechanism authentication policy and redirecting to AAC for all login, however many customers prefer to use native WebSEAL forms for authentication (or already have it in place), and then want to use an ISAM AAC policy just for multi-factor and do this all at initial user authentication time.

There are several high-level approaches to configuring ISAM for this scenario:

  • Use a combination of POP’s (protected object policy), manipulating the AUTHENTICATION_LEVEL attribute and using WebSEAL’s built-in step-up authentication capabilities.
  • Using an AAC authorization policy with AAC decision caching in WebSEAL so that this can be done efficiently for every web request access.
  • There is also an advanced hybrid approach documented in the Advanced Password-less Login section of the IBM Verify MMFA Cookbook. That scenario can also be adapted for the use case described here, adding back in username/password as a required first step, and replacing MMFA authentication (mobile-push to IBM Verify) with any other second-factor authentication policy. This scenario has the advantage of applying “conditional MFA” – i.e. only requiring second-factor authentication when the user is coming from a new browser (more accurately one without a remember-me cookie).

This article is going to document the approach described in the first bullet point above. It’s simple and will teach you about ways to trigger (and then handle) authentication flows in ISAM. From there you can work through the IBM Verify MMFA Cookbook and deduce how to apply what you have learned to more elaborate conditional multi-factor authentication flows.


The details for configuration described below are going to assume a starting point where you have ISAM AAC authentication policy configured and working, including configuring your WebSEAL (web reverse proxy) for AAC authentication and context-based access. This article will show you just how to do the enforced automatic sequencing of WebSEAL username/password authentication to your AAC authentication policy.

Configuring the Scenario

Credential viewing

I have written plenty of articles on viewing the ISAM credential in the past, most recently this one on Implementing an ISAM credential viewer in InfoMap.

You simply MUST have this level of visibility when developing a solution like this so that you can see what your credential looks like during varies phases of the authentication flow. When you are sure your solution works, you can remove the credential viewer, but when working through the scenario it is highly recommended you configure something to let you see what your credential looks like.

For the purposes of this article I’m going to junction to a cloud-hosted app that I have which does credential introspection:

pdadmin> server task default-webseald-localhost create -t tcp -h -p 80 -c all /genericeai

My WebSEAL is known (via a local hosts file entry) as I can view my credential with:

AAC authentication service policy kickoff via URL path

When using AAC authentication policies I much prefer to use the path policy kick-off method, set with the advanced configuration property sps.authService.policyKickoffMethod. Introduced in ISAM, this permits invocation of an authentication service policy with a URL path parameter rather than a query string value, so instead of:

you can set the advanced configuration property to “path”, and use:

The main reason I prefer path-based kickoff is that it is easier to attach ISAM ACLs and POPs to URL paths. This means you can easily set different ACLs and POPs for different AAC authentication policies. For example some authentication policies may require the user to already be logged with username/password and are second-factor only, whereas others may require unauthenticated access because they implement login directly from an unauthenticated state. This document is only going to use path-based kickoff in the example configuration, so set advanced property to path as shown:

Throughout the rest of this article I will be using the urn:ibm:security:authentication:asf:macotp policy, however you can substitute with whatever second-factor login policy or policies that you intend to use.

POP configuration for step-up login

All protected resources behind the WebSEAL reverse proxy will be protected with a POP that requires AUTHENTICATION_LEVEL=2, except for a subset that are needed in order to get the user to that level (i.e. resources used during initial login, and the authentication policy which does second-factor authentication). So what we do is create a level2pop, attach it to the WebSEAL root, then override that POP at other levels in the WebSEAL object space tree with either a level1pop (for users that are authenticated with username/password), or level0pop (for resources that require unauthenticated access like images shown on a login page).

Create the pop policies with pdadmin using commands as shown:

pop create level0pop
pop modify level0pop set ipauth anyothernw 0
pop create level1pop
pop modify level1pop set ipauth anyothernw 1
pop create level2pop
pop modify level2pop set ipauth anyothernw 2

Here are some example attachment operations that I used in my test environment when writing this article:

# Note - repeat this level0pop attachment for *all* resources that need to be retrieved unauthenticated
# They will separately need to ensure they have an effective ACL which permits unauthenticated access as well
pop attach /WebSEAL/localhost-default/favicon.ico level0pop
pop attach /WebSEAL/localhost-default/icons level0pop
pop attach /WebSEAL/localhost-default/pics level0pop
pop attach /WebSEAL/localhost-default/mga/sps/static level0pop
pop attach /WebSEAL/localhost-default/genericeai level0pop

# Note - If you use AAC authentication policies for any form of initial user login from an unauthenticated state, change this attachment to level0pop
pop attach /WebSEAL/localhost-default/mga/sps/authsvc level1pop

# Note - repeat this level1pop attachment for *all* authentication policies that might be used for stepup login
pop attach /WebSEAL/localhost-default/mga/sps/authsvc/policy/macotp level1pop

pop attach /WebSEAL/localhost-default level2pop


WebSEAL configuration

We need WebSEAL to render and then process the normal forms-based login first, before then performing stepup login via the AAC 2FA policy. This is required because most 2FA AAC policies need an initially authenticated user so that they can look up email, phone number, TOTP secret, etc – whatever is needed for that particular user to perform the desired second factor authentication.

Adjusting login.html to always show forms-based login

A small adjustment is required to ensure WebSEAL’s standard login.html file renders the normal forms-based login properly. This is necessary because when attaching the level2pop to the WebSEAL root object space, any access for a page is going to result in WebSEAL rendering the login.html, but expecting the type of authentication to be immediately ext-auth-interface (EAI) – because of the ordering in the [authentication-levels] stanza entries that you will see later. WebSEAL gets a little too smart here – and tries to go directly to the authentication mechanism it thinks will get the user to AUTHENTICATION_LEVEL 2 without knowing that we first require the user to get to AUTHENTICATION_LEVEL 1 using forms-based login.

There are two ways to make the adjustment – pick either one depending on your needs.

Alternative 1: Updating WebSEAL configuration file to show all login methods:

The simplest is to update the following entry in the WebSEAL configuration file:

show-all-auth-prompts = yes

Alternative 2: Updating WebSEAL login.hmtl file to show all login methods:

Alternatively you can manually modify login.html. The standard login.html file contains a special macro called %BASICAUTHN% which is used to conditionally comment out the username/password form with HTML comments. Unless WebSEAL thinks that the required authentication level will be password, then this macro will be replaced with the “start HTML comment” string, i.e. <!--, rending login.html without the ability to login with username and password.

For EACH language directory (not just the C directory), find login.html, and simply delete the line that contains the string %BASICAUTHN%, as shown:

Configuring WebSEAL to redirect to AAC for  stepup authentication

Next we want to set up WebSEAL to use our AAC authentication policy for step-up authentication instead of the built-in stepuplogin.html file. If you don’t do this, then after username/password login you should see an error like this:

In the WebSEAL configuration file, validate and update where necessary the following settings:

level = unauthenticated
level = password
level = ext-auth-interface

enable-local-response-redirect = yes

local-response-redirect-uri = [stepup] /mga/sps/authsvc/policy/macotp

Using the AuthSvcCredential Mapping Rule to set AUTHENTICATION_LEVEL

In order to ensure that the AUTHENTICATION_LEVEL attribute is correctly set to 2 when your authentication policy runs (if you don’t you’ll end up in an endless redirect loop during login), you should update the AuthSvcCredential Mapping rule, adding code similar to that shown below. This mapping rule runs at the end of every successfully completed AAC authentication policy. This is not strictly necessary for the built-in otp mechanisms as they have this functionality built-in (see advanced configuration property poc.otp.authLevel) however generally speaking this technique will work for any authentication policy you are using to achieve stepup. Change the myPolicyURIs variable below as required for your own policy:


// if you have more than one policy that could be used to statisfy 2FA, add to this array
var myPolicyURIs = [ "urn:ibm:security:authentication:asf:macotp" ];
var currentPolicy = ''+context.get(Scope.SESSION, "urn:ibm:security:asf:policy", "policyID");
if (myPolicyURIs.indexOf(currentPolicy) >= 0) {
    stsuu.getAttributeContainer().setAttribute(new Attribute("AUTHENTICATION_LEVEL", "urn:ibm:names:ITFIM:5.1:accessmanager", "2"));

That’s it!

Testing the Scenario

You should be able to visit a protected page (for example the root document, in my case, then complete regular WebSEAL forms-based login. At this point your credential is at AUTHENTICATION_LEVEL 1, however because you are accessing a resource protected with the level2pop, you are immediately taken through the stepup login flow. As we have configured a selective (i.e. only for stepup) local-response-redirect-uri, this operation is a redirect to our authentication policy instead of returning the stepuplogin.html WebSEAL management page. Finally once AAC authentication completes (which is an ext-auth-interface mechanism according to WebSEAL), the AuthSvcCredential mapping rule will set the credential attribute AUTHENTICATION_LEVEL to 2. This will then satisfy the level2pop, and your originally requested resource will load. The user experience is as shown – remember in this case I am using the macotp authentication policy for second-factor:

Next Steps

The above scenario shows a simple way to require multi-factor authentication every time someone logs into an ISAM-protected website. Most advanced authentication flows though only do second-factor authentication under certain conditions, such as when a user is coming from a new browser. There are several ways to implement conditional multi-factor, including the advanced password-less scenario shown in the IBM Verify Cookbook, and also using the technique I documented in this article on Risked-Based Access with Persistent Cookie Device Fingerprint. Whichever way you decide to go, take a moment to review the steps shown in this article as a starting point – they re-enforce ways in which simple stepup login flows can be triggered and managed based on the AUTHENTICATION_LEVEL attribute, and POPs.