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 sunAMAuthHOTPSMTPFromAddressemail@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
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:
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:
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:
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.