Yubikey - one time tokens

Submitted by xqus on Tue, 03/01/2011 - 21:54

YubiKey is the leading one time password token for simple, open online identity protection, and with the help of phpSec your users can be using their Yubikey for authentication in your application.

Getting ready

In order to use the Yubikey API you need a API key. You can create one here for free (Yubikey required).
Then after recieving your key, you need to tell phpSec about it. Below is an exaple, you need to change this to your own client ID and secret.

phpsecYubikey::$_clientId     = 5118;
phpsecYubikey::$_clientSecret = 'n7cIJF1IaL8WeTUsluWRSpRLOqs=';

Now what?

To enable your users to use their Yubikey to log in, you will have to store their Yubikey ID in the user database. All Yubikey OTP contains starts with the Yubikey ID (the first characters of the passwords). This ID will be the same every time, and unique for each Yubikey. We can use this to know who the Yubikey that was used belongs to. The Yubikey ID can be extracted from a OTP with the phpsecYubikey::getYubikeyId() method. This has to be done upon registration, or later if a user want's to attach a Yubikey to his account.

$yubikeyId = phpsecYubikey::getYubikeyId($_POST['otp']);

We can then store $yubikeyId in our database as the users Yubikey ID.

Validating a Yubikey OTP

When a user tries to log in using his username and Yubikey what we first do is to fetch the Yubikey that belongs to the user trying to log in. Let's say the ID from the databse is stored in $user['yubikey'].  Then we need to compare this to the Yubikey ID from the OTP from the login form, to make sure the Yubikey used is the same that the user has attached to his account.

if(phpsecYubikey::getYubikeyId($_POST['otp']) == $user['yubikey']) {
  // Yubikey belongs to user.
} else {
  // Login failed.
}

This is by itself not enough, becuse we still need to validate the Yubikey against the Yubico authentication servers to make sure the OTP is valid, and not beeing reused. This is done with the phpsecYubikey::verify() method. All we need to do is to expand the code from the example above.

if(phpsecYubikey::getYubikeyId($_POST['otp']) == $user['yubikey'] && phpsecYubikey::verify($_POST['otp'])) {
  // Yubikey belongs to user, and is valid.
} else {
  // Login failed.
}

What if something goes wrong?

Let's face it. Something is bound to go wrong. To see the last error produced by phpsecYubikey, we can use the phpsecYubikey::$lastError property. Let's expand the example above one more time. Please note that only calls to phpsecYubikey::verify() will produce errors.

if(phpsecYubikey::getYubikeyId($_POST['otp']) == $user['yubikey'] && phpsecYubikey::verify($_POST['otp'])) {
  // Yubikey belongs to user, and is valid. 
} else {
  // Login failed.
  echo phpsecYubikey::$lastError;
}

A full list of error codes are available here.

Copyright (c) 2011, 2012 Audun Larsen.

Drupal theme by Kiwi Themes.