• Stars
    star
    110
  • Rank 316,770 (Top 7 %)
  • Language
    Java
  • License
    BSD 3-Clause "New...
  • Created almost 6 years ago
  • Updated almost 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A WebAuthn Authenticator for Android leveraging hardware-backed key storage and biometric user verification.

Android WebAuthn Authenticator Library

This library is meant to serve as an example implementation of the WebAuthn authenticator model. While the specification is currently in Candidate Recommendation, this library conforms as much as possible to the guidelines and implementation procedures outlined by the document.

This implementation currently requires Android API level 28 (Android 9.0) due to the use of the BiometricPrompt.

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.duo-labs:android-webauthn-authenticator:master-SNAPSHOT'
    }

Using Source

Pull the source

$ cd ~/your/project/src/directory
$ git clone [email protected]:duo-labs/android-webauthn-authenticator.git

Add the module to your Android project

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

Add the module as a dependency

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

Select the android-webauthn-authenticator module. After a Gradle sync, you should be able to use the duo.labs.webauthn package.

Usage

You must first instantiate an Authenticator object.

// Authenticator(Context ctx, boolean authenticationRequired, boolean strongboxRequired)
Authenticator authenticator = new Authenticator(context, true, true);

The Authenticator object is safe to instantiate multiple times.

The arguments passed to the constructor determine whether the keys it generates will require biometric authentication (i.e. can be turned off for testing) and if keys should be stored by the StrongBox Keymaster.

Note that StrongBox is only available on some Android devices.

Make Credential (User Registration)

You can create a new credential by passing an AuthenticatorMakeCredentialOptions object to Authenticator.makeCredential(). You can instantiate an AuthenticatorMakeCredentialOptions object directly and manually set its fields, or use our JSON format.

Our JSON format mostly tracks the arguments to authenticatorMakeCredential from the WebAuthn specification, with a few changes necessary for the serialization of binary data. Here's an example:

{
    "authenticatorExtensions": "", // optional and currently ignored
    "clientDataHash": "LTCT/hWLtJenIgi0oUhkJz7dE8ng+pej+i6YI1QQu60=", // base64
    "credTypesAndPubKeyAlgs": [
        ["public-key", -7]
    ],
    "excludeCredentials": [
        {
            "type": "public-key",
            "id": "lVGyXHwz6vdYignKyctbkIkJto/ADbYbHhE7+ss/87o=" // base64
            // "transports" member optional but ignored
        }
    ],
    "requireResidentKey": true,
    "requireUserPresence": false,
    "requireUserVerification": true,
    "rp": {
        "name": "webauthn.io",
        "id": "webauthn.io"
    },
    "user": {
        "name": "testuser",
        "displayName": "Test User",
        "id": "/QIAAAAAAAAAAA==" // base64
    }
}

Note that requireResidentKey and requireUserPresence are effectively ignored: keys are resident by design, and user presence will always be verified. User verification will always be performed if the Authenticator is instantiated with authenticationRequired set to true; otherwise biometric authentication will not be performed and credential generation will fail if requireUserVerification is true.

(Per the spec, requireUserPresence must be the inverse of requireUserVerification)

Create the options object from JSON:

AuthenticatorMakeCredentialOptions makeCredentialOptions = AuthenticatorMakeCredentialOptions.fromJSON(options);

Then, make a new credential with the options given.

AttestationObject attestationObject = authenticator.makeCredential(makeCredentialOptions);
// or if you want to require user verification and need the biometric dialog:
AttestationObject attestationObject = authenticator.makeCredential(makeCredentialOptions, context, cancellationSignal);

makeCredential requires an application context in order to show the BiometricPrompt, and also accepts an optional CancellationSignal to allow user-initiated cancellation.

Once you have an AttestationObject, you can also retrieve its CBOR representation as follows:

byte[] attestationObjectBytes = attestationObject.asCBOR();

Get Assertion (User Login)

Similar to makeCredential, getAssertion takes an AuthenticatorGetAssertionOptions object which you can either instantiate manually or deserialize from JSON.

The JSON format follows authenticatorGetAssertion with some changes made for handling of binary data. Here's an example:

{
    "allowCredentialDescriptorList": [{
        "id": "jVtTOKLHRMN17I66w48XWuJadCitXg0xZKaZvHdtW6RDCJhxO6Cfff9qbYnZiMQ1pl8CzPkXcXEHwpQYFknN2w==", // base64
        "type": "public-key"
    }],
    "authenticatorExtensions": "", // optional and ignored
    "clientDataHash": "BWlg/oAqeIhMHkGAo10C3sf4U/sy0IohfKB0OlcfHHU=", // base64
    "requireUserPresence": true,
    "requireUserVerification": false,
    "rpId": "webauthn.io"
}

Create the options object from JSON:

AuthenticatorGetAssertionOptions getAssertionOptions = AuthenticatorGetAssertionOptions.fromJSON(options);

Step 7 of authenticatorGetAssertion requires that the authenticator prompt a credential selection. You can use our provided SelectCredentialDialogFragment to provide an interface for user-selection, or implement the CredentialSelector interface to receive a callback when it is time to select a credential.

Programmatic Credential Selection

If you want to programatically select credentials, you'll need to implement CredentialSelector, which is a simple interface:

public interface CredentialSelector {
    public PublicKeyCredentialSource selectFrom(List<PublicKeyCredentialSource> credentialList);
}

Here's a barebones example:

AuthenticatorGetAssertionResult assertionObject = authenticator.getAssertion(getAssertionOptions, new CredentialSelector() {
    @Override
    public PublicKeyCredentialSource selectFrom(List<PublicKeyCredentialSource> credentialList) {
        return credentialList.get(0);
    }
});

User-driven Credential Selection

You can also create a credential selector dialog by using the SelectCredentialDialogFragment helper class, which takes a DialogFragment:

SelectCredentialDialogFragment credentialSelector = new SelectCredentialDialogFragment();
credentialSelector.populateFragmentActivity(fragmentActivity);
AuthenticatorGetAssertionResult assertionObject = authenticator.getAssertion(options, credentialSelector, context, cancellationSignal);

The fragmentActivity supplied should be the main Activity with which the user is currently interacting.

As with the makeCredential operation, in the user-driven case, getAssertion requires an application context in order to show the BiometricPrompt and accepts an optional CancellationSignal to allow user-initiated cancellation.

More Repositories

1

cloudmapper

CloudMapper helps you analyze your Amazon Web Services (AWS) environments.
JavaScript
5,990
star
2

parliament

AWS IAM linting library
Python
1,044
star
3

webauthn

WebAuthn (FIDO2) server library written in Go
Go
1,028
star
4

cloudtracker

CloudTracker helps you find over-privileged IAM users and roles by comparing CloudTrail logs with current IAM policies.
Python
885
star
5

py_webauthn

Pythonic WebAuthn 🐍
Python
863
star
6

webauthn.io

The source code for webauthn.io, a demonstration of WebAuthn.
Python
654
star
7

EFIgy

A small client application that uses the Duo Labs EFIgy API to inform you about the state of your Mac EFI firmware
Python
512
star
8

dlint

Dlint is a tool for encouraging best coding practices and helping ensure we're writing secure Python code.
Python
331
star
9

markdown-to-confluence

Syncs Markdown files to Confluence
Python
307
star
10

isthislegit

Dashboard to collect, analyze, and respond to reported phishing emails.
Python
286
star
11

idapython

A collection of IDAPython modules made with 💚 by Duo Labs
Python
285
star
12

chrome-extension-boilerplate

Boilerplate code for a Chrome extension using TypeScript, React, and Webpack.
TypeScript
209
star
13

secret-bridge

Monitors Github for leaked secrets
Python
189
star
14

apple-t2-xpc

Tools to explore the XPC interface of Apple's T2 chip
Python
160
star
15

twitterbots

The code used in the "Don't @ Me: Hunting Twitter Bots at Scale" Black Hat presentation
Python
151
star
16

cloudtrail-partitioner

Python
150
star
17

phish-collect

Python script to hunt phishing kits
Python
137
star
18

phinn

A toolkit to generate an offline Chrome extension to detect phishing attacks using a bespoke convolutional neural network.
JavaScript
130
star
19

xray

X-Ray allows you to scan your Android device for security vulnerabilities that put your device at risk.
Java
121
star
20

appsec-education

Presentations, training modules, and other education materials from Duo Security's Application Security team.
JavaScript
71
star
21

mysslstrip

CVE-2015-3152 PoC
Python
43
star
22

EFIgy-GUI

A Mac app that uses the Duo Labs EFIgy API to inform you about the state of your EFI firmware.
Objective-C
40
star
23

lookalike-domains

generate lookalike domains using a few simple techniques (homoglyphs, alt TLDs, prefix/suffix)
Python
31
star
24

apk2java

Automatically decompile APK's using Docker
Dockerfile
23
star
25

journal

The boilerplate for a new Journal site
21
star
26

srtgen

Automatic '.srt' subtitle generator
Python
21
star
27

markflow

Make your Markdown sparkle!
Python
20
star
28

neustar2mmdb

Tool to convert Neustar's GeoPoint data to Maxmind's GeoIP database format for ease of use.
Python
19
star
29

narrow

Low-effort reachability analysis for third-party code vulnerabilities.
Python
19
star
30

datasci-ctf

A capture-the-flag exercise based on data analysis challenges
Jupyter Notebook
16
star
31

duo-blog-going-passwordless-with-py-webauthn

Python
15
star
32

tutorials

Python
15
star
33

sharedsignals

Python tools for using OpenID's Shared Signals Framework (including CAEP)
15
star
34

chain-of-fools

A set of tools that allow researchers to experiment with certificate chain validation issues
Python
13
star
35

journal-cli

The command-line client for Journal
Jupyter Notebook
12
star
36

unmasking_data_leaks

The code from the talk "Unmasking Data Leaks: A Guide to Finding, Fixing, and Prevention" given at BSides SATX 2019.
Python
7
star
37

journal-theme

The Hugo theme that powers Journal
HTML
7
star
38

golang-workshop

Source files for a Golang Workshop
Go
5
star
39

vimes

A local DNS proxy based on CoreDNS.
Python
3
star
40

journal-docs

The documentation for Journal
2
star
41

dlint-plugin-example

An example plugin for dlint
Python
2
star
42

twitterbots-wallpapers

Wallpapers created from the crawlers in our "Don't @ Me" technical research paper
1
star
43

holidayhack-2019

Scripts and artifacts used to solve the 2019 SANS Holiday Hack Challenge
Python
1
star