Skip to end of metadata
Go to start of metadata


This document shows a step-by-step recipe on how to properly configure OpenAM to use OATH based HOTP (HMAC based One Time Password) for Two-Factor (strong) authentication.

HOTP is published as an informational RFC 4226 and is also a FIPS standard. The OpenAM OATH module supports both HOTP and TOTP. It is vital to note that the OATH module is designed to be “chained” after a primary authentication module such as DataStore or LDAP because OpenAM stores the associated tokens in the users profile and hence the user has to be “identified” first and then the token extracted from their profile.   It is important to understand the flow which is as follows:

The user types in the URL in their browser.

  1. The query parameter "realm=Intranet" forces OpenAM to look under the “Intranet” realm for its configuration.

  2. Since we have added a new service called “StrongAuth” which chains “LDAP” and “OATH” as the authentication modules, the user is first prompted with the LDAP module login page.

  3. Once the user is authenticated via LDAP, the user is then prompted for the OATH OTP. The user inputs the OTP from either a hardware device such as YubiKey or a Software Application.

  4. As the system knows the username, it searches the user's profile in the DataStore of OpenAM which usually is a directory server.  In particular it looks for the attribute that is configured to store the OATH "token" (secret key) and the associated “counter” attribute.  It then takes the OTP submitted by the user, does its HOTP magic and then sends a yay or nay to the authentication chain.  Read the RFC referenced above to understand what this “magic” is.

  5. By default once the user logs in, the “End User” form is displayed.

In the whole flow above the user experience is not a complicated. The user will first see the LDAP login page, then the OATH OTP form and then if successful finally the end user page.  



The ingredients for this recipe are as follows:

  • OpenAM 10.1 or greater installed and configured
  • Hardware or Software OATH Token Generator


Configure OpenAM for OATH

Log into OpenAM console, click on Access Control and choose your realm which in this case is “Intranet”. Click on the Authentication Tab, scroll down to Module Instances and either “ADD” or “Edit” the OATH module.

Two attributes in LDAP are required for storing the OATH “secret key” and the “counter”. In production, it is recommended to extend your LDAP schema to add these attributes however existing ones can also be used for proof of concept. For this example I have reused the “carLicense” and “roomNumber” attributes because they are the correct datatypes. Note also that the OTP length chosen here is 6 and the key length is 32 (hex). In production change these length according to your security standards.

Next to ensure these attributes are available to the user profile add them to the “LDAP Attributes” on the Data Store. Do so by clicking on the “Data Stores” tab, selecting the data store and then scrolling down to the “User Configuration” section. Add both carLicense and roomNumber to “LDAP User Attributes”. Don't forget to Save.

Now return back the Authentication tab and create a new Authentication Chain called “StrongAuth” or whatever name you prefer.

Add the “LDAP” and “OATH” modules to this chain and make sure LDAP is "REQUISITE" and OATH is “REQUIRED”. The order is also important so make sure to stack OATH after LDAP. Don't forget to Save.

Go back to the Authentication tab and change the “Organization Authentication Configuration” to use this new chain as the default. Don't forget to Save.

This competes the configuration on OpenAM.



Configure your OATH token generator and OpenAM User Profile

For this particular writeup, I am using the “OATH Token” iOS application which is available for Free. Other platforms have similar applications. Or you can buy a YubiKey USB powered hardware token generator. The point is that for each user you have to generate a “secret key/token" on the device/application and then copy/write they key to the LDAP attribute chosen to store the “secret key” in the preceding section. In our case it is the carLicense attribute.

Create a new token and call it “User1000” which in this case is the corresponding username in OpenAM. You can choose whatever you like. Click on the “Generate Random Key” button to generate the Secret Token.   

Add the above “Token Secret Key” into the user's profile of OpenAM using either command line ldapmodify or the OpenDJ console or another LDAP GUI editor of your choice. Note the “Counter Value” should also match. Remember that we are using the roomNumber attribute to store the value of the counter.

Now you are ready to test.



Testing your new Two-Factor Auth Chain

Log out of the console and type the following URL with the query parameter in your browser. You should be presented with a login screen which states: This server uses LDAP Authentication. Type in your userid which in this case is “user1000” and password. 

If the chain works correctly the next REQUIRED module is OATH and you will be prompted for the OATH One Time Password.  

Generate the OTP OATH token on your device or application and input it.

If the token is accepted you will be logged in and you should see the End User page of OpenAM.  

If the authentication fails the consult the debug log called Authentication under ~/openam/openam/debug. For example during my configuration i saw the error on the right column. I realized that i had forgotten to add the two LDAP attributes to the "LDAP User Attributes" for the DataStore.

amAuthOATH:03/29/2013 08:03:58:565 PM EDT: Thread[http-bio-8080-exec-6,5,main]

ERROR: OATH.checkOTP() : Secret key setting is empty or null

  • No labels


  1. Hi, I'm testing this. How can I avoid my adminuser (amAdmin) from being locked out due to having to enter a one-time password as soon as I have added the OATH module?

    1. Unknown User (sarris)


      You should use the admin authentication chain for login in as admin:

      or use

  2. Thanks. I figured out I was doing this on the / realm. (I used the instructions in the book "Open Source Identity Management Patterns and Practices Using OpenAM 10.x"). When using a specific realm, this works brilliantly.