Skip to content

Commit

Permalink
first open source version
Browse files Browse the repository at this point in the history
  • Loading branch information
Irina Makhalova committed Aug 6, 2019
1 parent 774745f commit 6875286
Show file tree
Hide file tree
Showing 292 changed files with 19,320 additions and 0 deletions.
70 changes: 70 additions & 0 deletions .gitignore
@@ -0,0 +1,70 @@
# Built application files
*.apk
*.ap_

# Files for the ART/Dalvik VM
*.dex

# Java class files
*.class

# Generated files
bin/
gen/
out/

# Gradle files
.gradle/
build/
/local.properties

# Local configuration file (sdk path, etc)
local.properties

# Proguard folder generated by Eclipse
proguard/

# Log Files
*.log

# Android Studio Navigation editor temp files
.navigation/

# Android Studio captures folder
captures/

# IntelliJ
*.iml
.idea/workspace.xml
.idea/tasks.xml
.idea/gradle.xml
.idea/assetWizardSettings.xml
.idea/dictionaries
.idea/libraries
.idea/caches
.idea/

# Keystore files
# Uncomment the following line if you do not want to check your keystore files in.
#*.jks

# External native build folder generated in Android Studio 2.2 and later
.externalNativeBuild

# Google Services (e.g. APIs or Firebase)
google-services.json

# Freeline
freeline.py
freeline/
freeline_project_description.json

# fastlane
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output
fastlane/readme.md

#extra
*.DS_Store
37 changes: 37 additions & 0 deletions README.md
@@ -0,0 +1,37 @@
# YubiKit for Android
**This is a pre-release version of YubiKit. Some of the specs and APIs may change in future releases so use this documentation and the library for prototyping and not for a public release. If you are an early adopter please provide detailed feedback about the design and issues you may find when using YubiKit.**

**YubiKit** is an Android library provided Yubico to interact with YubiKeys. The library supports NFC-enabled and USB YubiKeys.

Please note, **YubiKit** consumes data from the token and translates to the application for further processing. **YubiKit** performs data validation for the purposes of creating valid responses to the application, however content/logical validation and security decisions are outside the scope of the **YubiKit** and must be handled by the application.

**YubiKit** is multi-module library with following components:

[Yubikit](./yubikit/README.md) provides an functionality to detect YubiKey plugged in or tapped over NFC,

[OATH](./oath/README.md) allows applications, such as an authenticator app, to store OATH TOTP and HOTP secrets on a YubiKey, and to retrieve one-time passwords,

[OTP](./otp/README.md) provides classes to obtain Yubikey OTP

[FIDO2](./fido/README.md) supports a subset of FIDO2

All **YubiKit** modules has javadoc and sources deployed with the library archive. Use this documentation for a more detailed explanation of all the methods, properties and parameters from the API.

This library comes with a demo application named **YubikitDemo**. The application is implemented in Kotlin.

## FAQ <a name="faq"></a>

#### Q1. Are there any versions of Android where YubiKit does not work?

YubiKit for FIDO2 should work on Android API 24+
Other YubiKit modules should work on Android API 19+
Yubico typically tests and support n-1 per https://en.wikipedia.org/wiki/Android_version_history.

#### Q2. How can I debug my app on Android when a YubiKey takes up the USB port?

You can set up adb debugging over WiFi: https://developer.android.com/studio/command-line/adb#wireless

## 6. Additional resources <a name="additional_resources"></a>
1. Yubico - [Developers website](https://developers.yubico.com)
2. Yubico - [Online Demo](https://demo.yubico.com)
![]()
5 changes: 5 additions & 0 deletions ReleaseNotes.txt
@@ -0,0 +1,5 @@
This application is a demo of YubiKit. YubiKit is a library provided by Yubico for interacting with YubiKeys
It shows different scenarios and cases for how you can use YubiKeys for authentication process.
Read about YubiKey and its advantages at https://www.yubico.com/
Web version of demo is implemented on https://demo.yubico.com/playground and for FIDO2/WebauthN https://demo.yubico.com/webauthn
iOS version of demo and YubiKit: https://github.com/YubicoLabs/yubikit-ios
1 change: 1 addition & 0 deletions YubikitDemo/.gitignore
@@ -0,0 +1 @@
/build
17 changes: 17 additions & 0 deletions YubikitDemo/QuickStart.md
@@ -0,0 +1,17 @@
# Quick Start Guide

--

This guide provides a few steps to follow before starting with YubiKit:

1. YubiKit requires a physical key to test its features.

2. Before starting to look at the SDK make sure you have the zip file containing all the necessary assets for using the library. The most important ones are:
- The **YubiKitDemo** folder containing the SDK Demo application.
- The **Readme.md** which contains detailed information on how to use the library.

3. Have a quick look at the **Readme.md** file to familiarise with the features of the YubiKit.

4. Open the YubiKitDemo Android Studio project and run it on a real device (not emulator). FIDO2 API are not supported on emulator so a real device is required to see the features.

---
130 changes: 130 additions & 0 deletions YubikitDemo/build.gradle
@@ -0,0 +1,130 @@
apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

apply plugin: 'kotlin-kapt'

android {
compileSdkVersion project.compileSdkVersion
defaultConfig {
applicationId "com.yubico.yubikit.demo"
minSdkVersion project.minFidoSdkVersion
targetSdkVersion project.targetSdkVersion
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true

buildConfigField "String", "APP_NAME", "\"YubikitDemo\""
buildConfigField "String", "NAMESPACE", "\"webauthnflow\""
buildConfigField "String", "SERVER_URL", "\"https://demo.yubico.com\""
buildConfigField "String", "TABLE_NAME", "\"authenticators\""
}

signingConfigs {
// Use the provided 'debug.keystore' for signing so that the webauthn
// server accepts the package signature
release {
storeFile file('../keystore/debug.keystore')
storePassword 'android'
keyAlias 'androiddebugkey'
keyPassword 'android'
}
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
debug {
signingConfig signingConfigs.release
}
}
}

configurations.all {
// check for updates every build
resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
}

dependencies {
implementation project(":fidodemo")

// yubikit
implementation project(':yubikit')
implementation (project(':oath')) {
exclude module:'yubikit'
}
implementation (project(':otp')) {
exclude module:'yubikit'
}
implementation (project(':management')) {
exclude module:'yubikit'
}

// ui libraries
def appcompatVersion = "1.0.2"
implementation "androidx.appcompat:appcompat:$appcompatVersion"
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
def androidxuiVersion = "1.0.0"
implementation "androidx.preference:preference:$androidxuiVersion"

// webview
implementation "androidx.browser:browser:$androidxuiVersion"

// architecture/lifecycle
def lifecycleVersion = "1.1.0"
implementation "androidx.lifecycle:lifecycle-livedata:$lifecycleVersion"
implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.0.0'

// navigation
def nav_version = "2.1.0-alpha05"
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version" // For Kotlin use navigation-fragment-ktx
implementation "androidx.navigation:navigation-ui-ktx:$nav_version" // For Kotlin use navigation-ui-ktx

// network
def retrofitVersion = "2.4.0"
def okhttpVersion = "3.11.0"
def moshiVersion = "1.8.0"
implementation "com.squareup.moshi:moshi:$moshiVersion"
implementation "com.squareup.moshi:moshi-kotlin:$moshiVersion"
implementation "com.squareup.retrofit2:converter-moshi:$retrofitVersion"
implementation "com.squareup.retrofit2:retrofit:$retrofitVersion"
implementation "com.squareup.okhttp3:okhttp:$okhttpVersion"

// decoders
implementation 'commons-codec:commons-codec:1.11'

// unit tests
def mockito_version = "2.11.0"
def robolectric_version = "4.2"
def junit_version = "1.1.1"
testImplementation 'junit:junit:4.12'
testImplementation "androidx.test.ext:junit:$junit_version"
testImplementation "org.robolectric:robolectric:$robolectric_version"
testImplementation "org.mockito:mockito-core:$mockito_version"

// ui tests
// Core library
def ui_test_version = "1.2.0"
androidTestImplementation "androidx.test:core:$ui_test_version"

// AndroidJUnitRunner and JUnit Rules
androidTestImplementation "androidx.test:runner:$ui_test_version"
androidTestImplementation "androidx.test:rules:$ui_test_version"

// Assertions
androidTestImplementation "androidx.test.ext:junit:$junit_version"
androidTestImplementation "androidx.test.ext:truth:$ui_test_version"
androidTestImplementation 'com.google.truth:truth:0.42'

// Espresso dependencies
def espresso_version = "3.2.0"
androidTestImplementation "androidx.test.espresso:espresso-core:$espresso_version"
androidTestImplementation "androidx.test.espresso:espresso-contrib:$espresso_version"
}
21 changes: 21 additions & 0 deletions YubikitDemo/proguard-rules.pro
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
@@ -0,0 +1,25 @@
# send APK into android device
~/adb_tools/adb push /Users/oscarso/Documents/com/Yubico/src/oso-test-androidyubikit-irina-readme/YubikitDemo/build/outputs/apk/debug/YubikitDemo-debug.apk /data/local/tmp/com.yubico.yubikit.demo

# install APK
~/adb_tools/adb shell pm install -t -r "/data/local/tmp/com.yubico.yubikit.demo"

# send testcase into android device
~/adb_tools/adb push /Users/oscarso/Documents/com/Yubico/src/oso-test-androidyubikit-irina-readme/YubikitDemo/build/outputs/apk/androidTest/debug/YubikitDemo-debug-androidTest.apk /data/local/tmp/com.yubico.yubikit.demo.test

# install testcase
~/adb_tools/adb shell pm install -t -r "/data/local/tmp/com.yubico.yubikit.demo.test"

# enable NFC
~/adb_tools/adb shell svc nfc enable

# execute test
~/adb_tools/adb shell am instrument -w -r -e debug false -e class 'com.yubico.yubikit.demo.EspressoTest' com.yubico.yubikit.demo.test/androidx.test.runner.AndroidJUnitRunner

# disable NFC
~/adb_tools/adb shell svc nfc disable

# clearn app state
# Note: cannot uninstall
~/adb_tools/adb shell pm clear com.yubico.yubikit.demo

@@ -0,0 +1,24 @@
package com.yubico.yubikit.demo

import androidx.test.espresso.IdlingResource

class ElapsedTimeIdlingResource(private val waitingTime: Long) : IdlingResource {
private val startTime: Long = System.currentTimeMillis()
private var resourceCallback: IdlingResource.ResourceCallback? = null

override fun getName() =
ElapsedTimeIdlingResource::class.java.name + ":" + waitingTime

override fun isIdleNow(): Boolean {
val elapsed = System.currentTimeMillis() - startTime
val idle = elapsed >= waitingTime
if (idle) {
resourceCallback?.onTransitionToIdle()
}
return idle
}

override fun registerIdleTransitionCallback(resourceCallback: IdlingResource.ResourceCallback) {
this.resourceCallback = resourceCallback
}
}
@@ -0,0 +1,46 @@
package com.yubico.yubikit.demo;

import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import androidx.test.espresso.Espresso;
import androidx.test.espresso.IdlingRegistry;
import androidx.test.espresso.action.ViewActions;
import androidx.test.espresso.contrib.NavigationViewActions;
import androidx.test.espresso.matcher.ViewMatchers;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.rule.ActivityTestRule;

import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withSubstring;


@RunWith(AndroidJUnit4.class)
public class EspressoTest {

@Rule
public ActivityTestRule<MainActivity> activityTestRule = new ActivityTestRule<>(MainActivity.class);

@Test
public void smartcarddemo_nfc() throws Exception {

//wait for completion, or timeout in ElapsedTimeIdlingResource(X) where X is in milliseconds
ElapsedTimeIdlingResource iresLogRead = new ElapsedTimeIdlingResource(3000);

//navigate to Smartcard Demo
onView(withId(R.id.nav_view))
.perform(NavigationViewActions.navigateTo(R.id.smartcard_fragment));

IdlingRegistry.getInstance().register(iresLogRead);

//Test pass if "signature is valid" is shown; otherwise, test fails.
onView(withId(R.id.log))
.check(matches(withSubstring("Signature is valid")));

IdlingRegistry.getInstance().unregister(iresLogRead);
}
}

0 comments on commit 6875286

Please sign in to comment.