OpenAM is a great open source Single Sign On and federation application, with a lot of features accumulated over its years of existence, first as Sun Access Manager, then as Sun and Oracle OpenSSO, before Forgerock finally takes over and names it OpenAM.

Finding the exact feature you want, and working around its limitations, can be quite time consuming.

In our case, we wanted to be able to choose the right authentication method (say, Kerberos, Active Directory, several types of strong authentication) based on two factors :

  • IP Address : Is the user coming from the internal network or from the internet ?
  • Targeted Service Provider : Our OpenAM instance is used as SAML2 IDP, and we want to provide different levels of security depending on which SAML2 Service Provider the user is trying to access. In other words, accessing your Google Apps account should require a stronger authentication than a not-so-secret company-wide intrante.

Initially, we only managed IP address-based authentication, for which we used policies as is described in several blogs. However, we did not find any easy way to extend this feature to switch the authentication based on the Service Provider.

Here is the solution we eventually implemented :

In this architecture, a reverse proxy (we used Apache HTTPd with mod_proxy) redirects the user to one of two realms based on his IP address. Inside each realm, we developped a custom implementation of the IDPAuthnContextMapper class to choose the authentication based on the requested Service Provider.

IP address-based authentication switching

The IDP has two realms "internal" and "external". A reverse proxy is in charge of switching from one realm to the other based on the user's IP address. This way the user only sees one URL, whereas there actually are two :
  • The SAML endpoint that the user sees : https://sso.example.com/auth/SSORedirect/metaAlias/idp
  • The actual SAML endpoints that the proxy queries :
    • https://sso.example.com/SSORedirect/metaAlias/internal/idp
    • https://sso.example.com/SSORedirect/metaAlias/external/idp
With this, we can configure completely different authentication modules and chainings depending on where the user comes from.

This requires a bit of configuration overhead, since me must set the IDP's and SP's configuration twice (once for each realm), but it works well overall.

If you follow OpenAM releases, you may have noticed that there is an Adaptative Risk authentication module that can fail or succeed based on a user's IP address. Coupled with authentication chainings, this is another way to perform IP-based authentication switching. However, in our case we wanted to always have Kerberos as the internal authentication method, and with the Adaptative Risk module we could not find a way to avoid showing the Kerberos popup for external users.



Service Provider-based authentication switching

In OpenAM, there is an interface dedicated to choosing the authentication chaining based on the SAML Request, the IDPAuthnContextMapper. The default implentation chooses the authentication chaining or module based on the SAML authentication context provided in the SP's SAML request.

In our case, we simply reimplemented the interface to decide based on the issuer provided in the SAML request instead of the authentication context.

We are lucky since OpenAM allows to easily inject your own IPDAuthnContextMapper implementation in replacement of the existing one. Here is what we can see in the IDP configuration screen :