Skip to content

WIOsense/rauth-android

Repository files navigation

WIOsense Android Roaming Authenticator

This library provides a FIDO2 roaming authenticator and CTAP1/2 implementation for Android devices. It leverages modern Android OS security concepts to provide easy support for resident keys with strong authentication via biometric user verification or clientPIN functionality compliant with the FIDO2 specification, and so, legacy U2F specification.

The library contains 2 main components, i.e. the Authenticator class and the TransactionManager. The Authenticator implements the authenticator main logic and functionality and can be used directly in any app via the utilities and auxiliary classes existent within the library.

The TransactionManager role is to provide an easy way to bind diverse transport layers to the Authenticator and handle the CTAP messages and handshakes between a remote client and the authenticator. Currently the TransactionManager is focused on handling well the HID CTAP protocol. The physical transport of this can be implemented either via USB connections or the Bluetooth HID device profile and this is up to the calling applications to decide, configure and setup.

An example in this sense is for instance the WioKey application which uses the Bluetooth HID device profile available in Android 9.0+ for the communication. We recommend the latter version of implementing HID for an improved user experience and easy interaction support with major desktop platforms (Windows 10, macOS, Linux) out of the box.

For security, the resident keys are protected by default by the Android KeyStore and strong authentication via AndroidX BiometricPrompt or clientPIN user verfication. Jump to security for more details.

Quickstart

You can use JitPack to include this module in your Android project, or you can include the source code.

Using JitPack

Add this in your root build.gradle:

    allprojects {
        repositories {
            ...
            maven { url 'https://jitpack.io' }
        }
    }

Add this to your dependencies list:

    dependencies {
        implementation 'com.github.wiosense:rauth-android:master-SNAPSHOT'
    }

Using Source

Pull the source

$ cd ~/your/project/src/directory
$ git clone https://github.com/wiosense/rauth-android.git

Add the module to your Android project

In Android Studio: File -> New -> Import Module and then point it at the rauth-android directory.

Add the module as a dependency

In Android Studio: File -> Project Structure -> App -> Dependencies -> + -> Module Dependency

Select the roaming-authenticator module. After a Gradle sync, you should be able to use the de.wiosense.webauthn package.

Authenticator.java usage

The Authenticator class implements the operations described in the Authenticator API section of Client To Authenticator Protocol (CTAP), and also provides APIs to manage the credentials that are contained in the Android Keystore.

You must first instantiate an authenticator object, which is safe to instantiate multiple times.

    //Authenticator(Context ctx, boolean strongboxRequired)
    Authenticator roamingAuthenticator = new Authenticator(appContext, true);

Here the strongboxRequired flag chooses whether to enforce the usage of a StrongBox Keymaster HSM. Not all phones support this, but you can easily check at runtime by calling:

    boolean hasStrongbox = currentContext.getPackageManager()
                                .hasSystemFeature(PackageManager.FEATURE_STRONGBOX_KEYSTORE);

It's important to note that all the following calls are blocking unless stated and shouldn't be executed in the UI thread of the app. Also, from this point on, all mentions to CBOR objects are related to this CBOR implementation.

GetInfo

You can poll the internal state and capabilities of the authenticator by calling the Authenticator.getInfo() method. This returns a GetInfoResult object that can be put into CBOR formatted byte array by calling GetInfoResult.asCBOR.

MakeCredential (WebAuthn Registration)

You can create a new credential by passing a MakeCredentialOptions object to the Authenticator.makeCredential method. Or alternatively, you can also pass a Map CBOR object that is formatted according to the CTAP spec, this is usually handled by the internals of the TransactionManager.

This will return an AttestationObject which you can inspect and retrieve a byte array formatter CBOR like so:

    byte[] attestation = attestationObject.asCBOR();

The returned object can be of any of three subclasses depending on the options that were passed to Authenticator.makeCredentials:

  • NoneAttestation
  • PackedBasicAttestation
  • PackedSelfAttestation

GetAssertion (WebAuthn Authentication)

You can make an authentication request by passing a GetAssertionOptions object to the Authenticator.getAssertion method. Or alternatively, you can also pass a Map CBOR object that is formatted according to the CTAP spec, this is usually handleded by the internals of the TransactionManager.

This will return an AssertionObject which you can inspect and retrieve a byte array formatter CBOR like so:

    byte[] assertion = assertionObject.asCBOR();

GetPinResult (WebAuthn PIN management for higher security requirements)

The Authenticator.getPinResult method can be called with a ClientPINOptions object. However, it is important to point out that this particular method has a series of subcommands that internally are handled differently, but all return the same ClientPINResult object that can be serialized like the previous results objects. This command is usually used as a handshake, which needs to be handled by the user of the authenticator.

Apart from using the CTAP2 method to manage the PIN, the following APIs are provided for internal management:

  • Authenticator.selfSetPin which can set a PIN or override a previously set one after user verification
  • Authenticator.resetPin which gracefully removes a previously set PIN after user verification
  • Authenticator.isPinSet which returns a boolean specifying whether a PIN is currently set or not.

Credential Management