One-Time Passwords – HOTP and TOTP

About One-Time Passwords in general

One-Time Passwords (OTP) are pretty much what their name says: a password that can be only used one time. Comparing to regular passwords OTP is considered safer since the password keeps on changing, meaning that it isn’t vulnerable against replay attacks.

When it comes to authentication mechanisms, usually OTP is used as an additional authentication mechanism (hence OTP is commonly referred to as two factor authentication/second factor authentication/step-up authentication). The main/first authentication step is still using regular passwords, so in order your authentication to be successful you need to prove two things: knowledge and possession of a secret.

Since the OTP is only usable once, memorizing them isn’t quite simple. There is two main way of acquiring these One-Time Passwords:

  • hardware tokens: for example YubiKey devices, which you can plug in to your USB port and will automatically type in the OTP code for you.
  • software tokens: like Google Authenticator, in this case a simple Android application displays you the OTP code which you can enter on your login form.

There is two main standard for generating One-Time Passwords: HOTP and TOTP, both of which are governed by the Initiative For Open Authentication (OATH). In the followings we will discuss the differences between these algorithms and finally we will attempt to use these authentication mechanisms with OpenAM.

Hmac-based One-Time Password algorithm

This algorithm relies on two basic things: a shared secret and a moving factor (a.k.a counter). As part of the algorithm an HmacSHA1 hash (to be precise it’s a hash-based message authentication code) of the moving factor will be generated using the shared secret. This algorithm is event-based, meaning that whenever a new OTP is generated, the moving factor will be incremented, hence the subsequently generated passwords should be different each time.

Time-based One-Time Password algorithm

This algorithm works similarly to HOTP: it also relies on a shared secret and a moving factor, however the moving factor works a bit differently. In case of TOTP, the moving factor constantly changes based on the time passed since an epoch. The HmacSHA1 is calculated in the same way as with HOTP.

Which one is better?

The main difference between HOTP and TOTP is that the HOTP passwords can be valid for an unknown amount of time, while the TOTP passwords keep on changing and are only valid for a short window in time. Because of this difference generally speaking the TOTP is considered as a more secure One-Time Password solution.

So how does OpenAM implement OTP?

In OpenAM currently there is two authentication module offering One-Time Password capabilities: HOTP and OATH. So let’s see what is the difference between them and how to use them in practice.

HOTP authentication module

The HOTP module – as you can figure – tries to implement the Hmac-based One-Time Password algorithm, but it does so by circumventing some portions of the specification. Let me try to summarize what’s different exactly:

  • The shared secret isn’t really shared between the user and OpenAM, actually it is just a freshly generated random number, each HOTP code will be based on a different shared secret.
  • The moving factor is statically held in OpenAM, and it just keeps on incrementing by each user performing HOTP based authentications.
  • A given HOTP code is only valid for a limited amount of time (so it’s a bit similar to TOTP in this sense).

These differences also mean that it does not work with a hardware/software token since the OTP code generation depends on OpenAM’s internal state and not on shared information. So in order to be able to use the generated OTP code, OpenAM has to share it somehow with the user: this can be via SMS or E-mail or both.

So let’s create an example HOTP module using ssoadm:

openam/bin/ssoadm create-auth-instance --realm / --name HOTP --authtype HOTP --adminid amadmin --password-file .pass

Now we have an HOTP module in our root realm, let’s configure it:

openam/bin/ssoadm update-auth-instance --realm / --name HOTP --adminid amadmin --password-file .pass -D hotp.properties

Where hotp.properties contains:

sunAMAuthHOTPAuthLevel=0
sunAMAuthHOTPSMSGatewayImplClassName=com.sun.identity.authentication.modules.hotp.DefaultSMSGatewayImpl
sunAMAuthHOTPSMTPHostName=smtp.gmail.com
sunAMAuthHOTPSMTPHostPort=465
sunAMAuthHOTPSMTPUserName=example
sunAMAuthHOTPSMTPUserPassword=secret123
sunAMAuthHOTPSMTPSSLEnabled=SSL
sunAMAuthHOTPSMTPFromAddress=demo@example.com
sunAMAuthHOTPPasswordValidityDuration=5
sunAMAuthHOTPPasswordLength=8
sunAMAuthHOTPasswordDelivery=E-mail
sunAMAuthHOTPAutoClicking=true
openamEmailAttribute=mail

NOTE: The names of the service attributes can be found in the OPENAM_HOME/config/xml/amAuthHOTP.xml file.

At this stage I’ve modified the built-in demo user’s e-mail address, so I actually receive the OTP codes for my tests.

Last step is to create an authentication chain with the new HOTP module:

openam/bin/ssoadm create-auth-cfg --realm / --name hotptest --adminid amadmin --password-file .pass
openam/bin/ssoadm add-auth-cfg-entr --realm / --name hotptest --modulename DataStore --criteria REQUISITE --adminid amadmin --password-file .pass
openam/bin/ssoadm add-auth-cfg-entr --realm / --name hotptest --modulename HOTP --criteria REQUIRED --adminid amadmin --password-file .pass

Here the first command created the chain itself, the other two commands just added the necessary modules to the chain.

We can test this now by visiting /openam/UI/Login?service=hotptest . Since I don’t like to take screenshots you just have to believe me that the authentication was successful and I’ve received my HOTP code in e-mail, which was in turn accepted by the HOTP module. ๐Ÿ™‚

OATH authentication module

The OATH module is a more recent addition to OpenAM which implements both HOTP and TOTP as they are defined in the corresponding RFCs. This is how they work under the hood:

  • Both OTP mode retrieves the shared secret from the user profile (e.g. it is defined in an LDAP attribute of the user’s entry).
  • HOTP retrieves the moving factor from the user profile.
  • TOTP does not let a user to authenticate within the same TOTP window (since a given TOTP may be valid for several time windows), hence it stores the last login date in the user profile.

For the following tests I’ve been using the Google Authenticator Android app to generate my OTP codes.

Testing OATH + HOTP

First set up the authentication module instance:

openam/bin/ssoadm create-auth-instance --realm / --name OATH --authtype OATH --adminid amadmin --password-file .pass
openam/bin/ssoadm update-auth-instance --realm / --name OATH --adminid amadmin --password-file .pass -D oathhotp.properties

Where oathhotp.properties contains:

iplanet-am-auth-oath-auth-level=0
iplanet-am-auth-oath-password-length=6
iplanet-am-auth-oath-min-secret-key-length=32
iplanet-am-auth-oath-secret-key-attribute=givenName
iplanet-am-auth-oath-algorithm=HOTP
iplanet-am-auth-oath-hotp-window-size=100
iplanet-am-auth-oath-hotp-counter-attribute=sn
iplanet-am-auth-oath-add-checksum=False
iplanet-am-auth-oath-truncation-offset=-1

NOTE: here I’m using the givenName and the sn attributes for my personal tests but in a real environment I would use dedicated attributes for these of course.

Again let’s create a test authentication chain:

openam/bin/ssoadm create-auth-cfg --realm / --name oathtest --adminid amadmin --password-file .pass
openam/bin/ssoadm add-auth-cfg-entr --realm / --name oathtest --modulename DataStore --criteria REQUISITE --adminid amadmin --password-file .pass
openam/bin/ssoadm add-auth-cfg-entr --realm / --name oathtest --modulename OATH --criteria REQUIRED --adminid amadmin --password-file .pass

In order to actually test this setup I’m using a QR code generator to generate a scannable QR code for the Google Authenticator with the following value:

otpauth://hotp/Example:demo@example.com?secret=JBSWY3DPK5XXE3DEJ5TE6QKUJA======&issuer=Example&counter=1

NOTE: The Google Authenticator needs the secret key in Base32 encoded format, but the module needs the key to be in HEX encoded format (“48656c6c6f576f726c644f664f415448”) in the user profile.

After all these changes bring up /openam/UI/Login?service=oathservice and just simply ask for a new HOTP code on your phone, you should see something like this:

Google Authenticator - HOTP

Enter the same code on the login screen and you are in, yay. ๐Ÿ™‚

Testing OATH + TOTP

For testing TOTP I’ll be reusing the authentication modules and chains from the OATH HOTP test:

openam/bin/ssoadm update-auth-instance --realm / --name OATH --adminid amadmin --password-file .pass -D oathtotp.properties

Where oathtotp.properties contains:

iplanet-am-auth-oath-auth-level=0
iplanet-am-auth-oath-password-length=6
iplanet-am-auth-oath-min-secret-key-length=32
iplanet-am-auth-oath-secret-key-attribute=givenName
iplanet-am-auth-oath-algorithm=TOTP
iplanet-am-auth-oath-size-of-time-step=30
iplanet-am-auth-oath-steps-in-window=2
iplanet-am-auth-oath-last-login-time-attribute-name=sn

We need to generate a new QR code now with the following content:

otpauth://totp/Example:demo@example.com?secret=JBSWY3DPK5XXE3DEJ5TE6QKUJA======&issuer=Example

Again, let’s test it at /openam/UI/Login?service=oathtest and this time we should have a slightly different UI on the Google Authenticator:

Google Authenticator - TOTP

As you can see there is a nice indicator now showing us how long this TOTP code will remain valid.

I think now we know about OTP codes more than enough, hope you’ve found this article useful. ๐Ÿ˜‰

6 comments

  1. Hey, great post! Quick question, I’m using openAM 12.0.0 and I configured OATH/HOTP similarly to how you have it there. When I get past the login page, I get to a page that asks me to enter a OTP; however, I would like to request that an OTP be e-mailed to me. I see on other sites screenshots with that button, but I can’t find it on my page. Do you know if it has been removed in 12.0.0 or why its not appearing? Thanks!

  2. Only the HOTP authentication module allows “requesting” OTP code. The HOTP module actually has a setting called “sunAMAuthHOTPAutoClicking”, if that’s enabled then the OTP code will be automatically sent to the end-user, otherwise the user will need to manually click on the Request OTP button.

  3. I have got HOTP working successfully and I have also managed to get it working using the rest API, I tested using Curl but I need to set up HOTP and not send the OTP.

    I need OpenAM to generate the OTP and save somewhere where our developers can pick it up and use their own transport methods to send the OTP and and they also intend to use their own login screens. They want to do this so they can be flexible in future, i,e they may want to start using Whatsapp or some other transport method to send the OTP

    Thanks

    Z

Join the Conversation

Your email address will not be published. Required fields are marked *