YubiKey NEO

The YubiKey NEO emits NDEF Type 2 tags containing ever-changing Yubico One Time Passwords (OTP). These passwords are equivalent of those emitted by standard YubiKeys. The YubiKey NEO also has a USB connector, and can be used with any USB host device just like the standard YubiKey.

Working with the YubiKey NEO in Android

The two major modes of operation for the YubiKey NEO with Android smartphones are:

  • Out of the box – The NFC tag emitted by default will bring up the phones browser and access an URL containing the OTP. This URL might be a direct access URL for a specific service or a service provider/relying party in an identity federation. By default, the URL will take the user to a landing site hosted by Yubico.
  • With an installed application (App) – An installed application can register an “intent”, letting it intercept the NFC tag and handle it any way it wants. The intent can be registered as matching a specific URL (in case service specific YubiKey NEOs are used). For an application to work seamlessly with as many YubiKey NEOs as possible, the application should register an interest in the default Yubico landing site URL, possibly in addition to one specific for the application. If more than one installed application registers interest in the default Yubico landing site URL, the user will be prompted for which application to use when swiping the YubiKey NEO.


Basic documentation for working with NFC in Android.


Requirements

The applications AndroidManifest.xml needs to include the following to get access to NFC tags:

  • A minimum SDK version of 10 to have NFC API’s:
    <uses-sdk android:minsdkversion=”10″>
  • Permission to use NFC:
    <uses-permission android:name=”android.permission.NFC”>
  • If NFC is a requirement for using the App:
    <uses-feature android:name=”android.hardware.nfc”>

If the phone doesn’t have NFC it will return null from NfcAdapter.getDefaultAdapter(this) in an activity.

Getting NFC data onto the phone

For working with NFC there are two choices, foreground intent dispatch or global intent dispatch.

To register globally and launch an app when presenting the YubiKey NEO programmed with the demo.yubico.com URI the following needs to be in the apps AndroidManifest.xml:

<activity android:name=”.NdefActivity”>
<intent-filter>
<action android:name=”android.nfc.action.NDEF_DISCOVERED”/>
<category android:name=”android.intent.category.DEFAULT”/>
<data android:host=”demo.yubico.com” android:scheme=”http”/>
</intent-filter>
</activity>

The application will then be called in the onResume() function and can get the NDEF intent by getIntent().

To register for foreground dispatch with any YubiKey NEO with the http URI scheme configured the relevant activity would need the following to register an IntentFilter:

PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
ndef.addDataScheme(“http”);
NfcAdapter.getDefaultAdapter(this).enableForegroundDispatch(this, pendingIntent, new IntentFilter[] {ndef}, null);

The application will then be called in onNewIntent(Intent intent) when the device receives NFC data.

When NFC is no longer required, or in onPause(), the app will need to disable foreground dispatch:

NfcAdapter.getDefaultAdapter(this).disableForegroundDispatch(this);

When the application has received an intent with a NDEF message, the Yubico OTP (public id+ OTP) will be the last 44 characters, assuming a standard configuration with 12 characters of public id and 32 characters of OTP. You can get just the Yubico OTP from the intent with the following function:

private String getOtpFromIntent(Intent intent) {
Pattern otpPattern = Pattern.compile(“^.*([cbdefghijklnrtuv{44})$”);
String data = intent.getDataString();
Matcher matcher = otpPattern.matches(data);
if (matcher.matches()) {
return matcher.group(1);
} else {
return null;
}
}