diff --git a/Fido2/.gitignore b/Fido2/.gitignore
deleted file mode 100644
index c94c421..0000000
--- a/Fido2/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-*.iml
-.gradle
-local.properties
-.idea
-.DS_Store
-/build
-/captures
-.externalNativeBuild
diff --git a/Fido2/README.md b/Fido2/README.md
deleted file mode 100644
index c259eff..0000000
--- a/Fido2/README.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# FIDO2 Sample
-This sample shows how to use the FIDO2 API, however we recommend [migrating from FIDO2 to Credential Manager](https://developer.android.com/training/sign-in/fido2-migration).
diff --git a/Fido2/app/.gitignore b/Fido2/app/.gitignore
deleted file mode 100644
index 796b96d..0000000
--- a/Fido2/app/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/build
diff --git a/Fido2/app/build.gradle b/Fido2/app/build.gradle
deleted file mode 100644
index 75fd03f..0000000
--- a/Fido2/app/build.gradle
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright 2021 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-apply plugin: 'com.android.application'
-apply plugin: 'kotlin-android'
-apply plugin: 'kotlin-kapt'
-apply plugin: 'dagger.hilt.android.plugin'
-
-android {
- compileSdkVersion 31
- defaultConfig {
- applicationId 'com.google.android.gms.identity.sample.fido2'
- minSdkVersion 21
- targetSdkVersion 31
- versionCode 1
- versionName '1.0'
- testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
- vectorDrawables.useSupportLibrary = true
- buildConfigField 'String', 'API_BASE_URL', "\"https://webauthn-codelab.glitch.me/auth\""
- resValue 'string', 'host', 'https://webauthn-codelab.glitch.me'
- resValue 'string', 'asset_statements', """
- [{
- "include": "https://webauthn-codelab.glitch.me/.well-known/assetlinks.json"
- }]
- """
- }
- signingConfigs {
- debug {
- storeFile file('../debug.jks')
- storePassword 'android'
- keyAlias 'androiddebugkey'
- keyPassword 'android'
- }
- }
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
- }
- kotlinOptions {
- jvmTarget = '1.8'
- }
- buildFeatures {
- dataBinding true
- }
- buildTypes {
- debug {
- signingConfig signingConfigs.debug
- }
- release {
- signingConfig signingConfigs.debug
- minifyEnabled false
- proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
- }
- }
-}
-
-dependencies {
- implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
-
- implementation 'com.google.android.gms:play-services-fido:19.0.0-beta'
-
- implementation 'androidx.appcompat:appcompat:1.3.1'
- implementation 'androidx.fragment:fragment-ktx:1.3.6'
-
- implementation 'androidx.core:core-ktx:1.6.0'
- implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
-
- implementation "androidx.datastore:datastore-preferences:1.0.0"
-
- def coroutine_version = '1.5.0'
- implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutine_version"
- implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutine_version"
- implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:$coroutine_version"
-
- def hilt_version = '2.38.1'
- implementation "com.google.dagger:hilt-android:$hilt_version"
- kapt "com.google.dagger:hilt-compiler:$hilt_version"
- kapt "androidx.hilt:hilt-compiler:1.0.0"
-
- def lifecycle_version = '2.4.0-alpha03'
- implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
- implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"
- implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
- testImplementation 'androidx.arch.core:core-testing:2.1.0'
-
- implementation 'com.google.android.material:material:1.4.0'
-
- def okhttp_version = '4.9.0'
- implementation "com.squareup.okhttp3:okhttp:$okhttp_version"
- implementation "com.squareup.okhttp3:logging-interceptor:$okhttp_version"
- implementation "ru.gildor.coroutines:kotlin-coroutines-okhttp:1.0"
-
- testImplementation 'junit:junit:4.13.2'
- androidTestImplementation 'androidx.test:runner:1.4.0'
- androidTestImplementation 'androidx.test:rules:1.4.0'
-
- androidTestImplementation 'androidx.test.ext:junit:1.1.3'
- androidTestImplementation 'androidx.test.ext:truth:1.4.0'
- androidTestImplementation 'com.google.truth:truth:1.1.2'
-
- androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
-}
diff --git a/Fido2/app/proguard-rules.pro b/Fido2/app/proguard-rules.pro
deleted file mode 100644
index f1b4245..0000000
--- a/Fido2/app/proguard-rules.pro
+++ /dev/null
@@ -1,21 +0,0 @@
-# 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
diff --git a/Fido2/app/src/main/AndroidManifest.xml b/Fido2/app/src/main/AndroidManifest.xml
deleted file mode 100644
index ca81adc..0000000
--- a/Fido2/app/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/Base64Ext.kt b/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/Base64Ext.kt
deleted file mode 100644
index 87b512a..0000000
--- a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/Base64Ext.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2021 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.gms.identity.sample.fido2
-
-import android.util.Base64
-
-private const val BASE64_FLAG = Base64.NO_PADDING or Base64.NO_WRAP or Base64.URL_SAFE
-
-fun ByteArray.toBase64(): String {
- return Base64.encodeToString(this, BASE64_FLAG)
-}
-
-fun String.decodeBase64(): ByteArray {
- return Base64.decode(this, BASE64_FLAG)
-}
diff --git a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/Fido2App.kt b/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/Fido2App.kt
deleted file mode 100644
index 3cc2b3f..0000000
--- a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/Fido2App.kt
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2021 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.gms.identity.sample.fido2
-
-import android.app.Application
-import android.os.Build
-import androidx.datastore.core.DataStore
-import androidx.datastore.preferences.core.PreferenceDataStoreFactory
-import androidx.datastore.preferences.core.Preferences
-import androidx.datastore.preferences.preferencesDataStoreFile
-import com.google.android.gms.identity.sample.fido2.api.AddHeaderInterceptor
-import dagger.Module
-import dagger.Provides
-import dagger.hilt.InstallIn
-import dagger.hilt.android.HiltAndroidApp
-import dagger.hilt.components.SingletonComponent
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.SupervisorJob
-import okhttp3.OkHttpClient
-import java.util.concurrent.TimeUnit
-import javax.inject.Singleton
-
-@HiltAndroidApp
-class Fido2App : Application()
-
-@Module
-@InstallIn(SingletonComponent::class)
-object AppModule {
-
- @Singleton
- @Provides
- fun provideOkHttpClient() : OkHttpClient {
- val userAgent = "${BuildConfig.APPLICATION_ID}/${BuildConfig.VERSION_NAME} " +
- "(Android ${Build.VERSION.RELEASE}; ${Build.MODEL}; ${Build.BRAND})"
- return OkHttpClient.Builder()
- .addInterceptor(AddHeaderInterceptor(userAgent))
- .readTimeout(30, TimeUnit.SECONDS)
- .writeTimeout(40, TimeUnit.SECONDS)
- .connectTimeout(40, TimeUnit.SECONDS)
- .build()
- }
-
- @Singleton
- @Provides
- fun provideAppCoroutineScope() : CoroutineScope = CoroutineScope(SupervisorJob())
-
- @Singleton
- @Provides
- fun provideDataStore(application: Application): DataStore {
- return PreferenceDataStoreFactory.create {
- application.preferencesDataStoreFile("auth")
- }
- }
-}
diff --git a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/api/AddHeaderInterceptor.kt b/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/api/AddHeaderInterceptor.kt
deleted file mode 100644
index cef5d5e..0000000
--- a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/api/AddHeaderInterceptor.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2021 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.gms.identity.sample.fido2.api
-
-import okhttp3.Interceptor
-import okhttp3.Response
-
-internal class AddHeaderInterceptor(private val userAgent: String) : Interceptor {
- override fun intercept(chain: Interceptor.Chain): Response {
- return chain.proceed(
- chain.request().newBuilder()
- .header("User-Agent", userAgent)
- .header("X-Requested-With", "XMLHttpRequest")
- .build()
- )
- }
-}
diff --git a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/api/ApiException.kt b/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/api/ApiException.kt
deleted file mode 100644
index fc912ab..0000000
--- a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/api/ApiException.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright 2021 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.gms.identity.sample.fido2.api
-
-class ApiException(message: String) : RuntimeException(message)
diff --git a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/api/ApiResult.kt b/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/api/ApiResult.kt
deleted file mode 100644
index bff318f..0000000
--- a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/api/ApiResult.kt
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2021 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.gms.identity.sample.fido2.api
-
-/**
- * Represents the result of an API call.
- */
-sealed class ApiResult {
-
- /**
- * API returned successfully with data.
- */
- class Success(
- /**
- * The session ID to be used for the subsequent API calls.
- * Might be null if the API call does not return a new cookie.
- */
- val sessionId: String?,
-
- /**
- * The result data.
- */
- val data: T
- ) : ApiResult()
-
- /**
- * API returned unsuccessfully with code 401, and the user should be signed out.
- */
- object SignedOutFromServer : ApiResult()
-}
diff --git a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/api/AuthApi.kt b/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/api/AuthApi.kt
deleted file mode 100644
index 94588cc..0000000
--- a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/api/AuthApi.kt
+++ /dev/null
@@ -1,545 +0,0 @@
-/*
- * Copyright 2021 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.gms.identity.sample.fido2.api
-
-import android.util.JsonReader
-import android.util.JsonToken
-import android.util.JsonWriter
-import android.util.Log
-import com.google.android.gms.fido.fido2.api.common.Attachment
-import com.google.android.gms.fido.fido2.api.common.AuthenticatorAssertionResponse
-import com.google.android.gms.fido.fido2.api.common.AuthenticatorAttestationResponse
-import com.google.android.gms.fido.fido2.api.common.AuthenticatorSelectionCriteria
-import com.google.android.gms.fido.fido2.api.common.PublicKeyCredential
-import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialCreationOptions
-import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialDescriptor
-import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialParameters
-import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialRequestOptions
-import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialRpEntity
-import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialType
-import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialUserEntity
-import com.google.android.gms.identity.sample.fido2.BuildConfig
-import com.google.android.gms.identity.sample.fido2.decodeBase64
-import com.google.android.gms.identity.sample.fido2.toBase64
-import okhttp3.MediaType.Companion.toMediaTypeOrNull
-import okhttp3.OkHttpClient
-import okhttp3.Request
-import okhttp3.RequestBody
-import okhttp3.RequestBody.Companion.toRequestBody
-import okhttp3.Response
-import okhttp3.ResponseBody
-import ru.gildor.coroutines.okhttp.await
-import java.io.StringReader
-import java.io.StringWriter
-import javax.inject.Inject
-
-/**
- * Interacts with the server API.
- */
-class AuthApi @Inject constructor(
- private val client: OkHttpClient
-) {
-
- companion object {
- private const val BASE_URL = BuildConfig.API_BASE_URL
- private val JSON = "application/json".toMediaTypeOrNull()
- private const val SessionIdKey = "connect.sid="
- private const val TAG = "AuthApi"
- }
-
- /**
- * @param username The username to be used for sign-in.
- * @return The Session ID.
- */
- suspend fun username(username: String): ApiResult {
- val call = client.newCall(
- Request.Builder()
- .url("$BASE_URL/username")
- .method("POST", jsonRequestBody {
- name("username").value(username)
- })
- .build()
- )
- val response = call.await()
- return response.result("Error calling /username") { }
- }
-
- /**
- * @param sessionId The session ID received on `username()`.
- * @param password A password.
- * @return An [ApiResult].
- */
- suspend fun password(sessionId: String, password: String): ApiResult {
- val call = client.newCall(
- Request.Builder()
- .url("$BASE_URL/password")
- .addHeader("Cookie", formatCookie(sessionId))
- .method("POST", jsonRequestBody {
- name("password").value(password)
- })
- .build()
- )
- val response = call.await()
- return response.result("Error calling /password") { }
- }
-
- /**
- * @param sessionId The session ID.
- * @return A list of all the credentials registered on the server.
- */
- suspend fun getKeys(sessionId: String): ApiResult> {
- val call = client.newCall(
- Request.Builder()
- .url("$BASE_URL/getKeys")
- .addHeader("Cookie", formatCookie(sessionId))
- .method("POST", jsonRequestBody {})
- .build()
- )
- val response = call.await()
- return response.result("Error calling /getKeys") {
- parseUserCredentials(body ?: throw ApiException("Empty response from /getKeys"))
- }
- }
-
- /**
- * @param sessionId The session ID.
- * @return A pair. The `first` element is an [PublicKeyCredentialCreationOptions] that can be
- * used for a subsequent FIDO2 API call. The `second` element is a challenge string that should
- * be sent back to the server in [registerResponse].
- */
- suspend fun registerRequest(sessionId: String): ApiResult {
- val call = client.newCall(
- Request.Builder()
- .url("$BASE_URL/registerRequest")
- .addHeader("Cookie", formatCookie(sessionId))
- .method("POST", jsonRequestBody {
- name("attestation").value("none")
- name("authenticatorSelection").objectValue {
- name("authenticatorAttachment").value("platform")
- name("userVerification").value("required")
- }
- })
- .build()
- )
- val response = call.await()
- return response.result("Error calling /registerRequest") {
- parsePublicKeyCredentialCreationOptions(
- body ?: throw ApiException("Empty response from /registerRequest")
- )
- }
- }
-
- /**
- * @param sessionId The session ID to be used for the sign-in.
- * @param credential The PublicKeyCredential object.
- * @return A list of all the credentials registered on the server, including the newly
- * registered one.
- */
- suspend fun registerResponse(
- sessionId: String,
- credential: PublicKeyCredential
- ): ApiResult> {
- val rawId = credential.rawId.toBase64()
- val response = credential.response as AuthenticatorAttestationResponse
-
- val call = client.newCall(
- Request.Builder()
- .url("$BASE_URL/registerResponse")
- .addHeader("Cookie", formatCookie(sessionId))
- .method("POST", jsonRequestBody {
- name("id").value(rawId)
- name("type").value(PublicKeyCredentialType.PUBLIC_KEY.toString())
- name("rawId").value(rawId)
- name("response").objectValue {
- name("clientDataJSON").value(
- response.clientDataJSON.toBase64()
- )
- name("attestationObject").value(
- response.attestationObject.toBase64()
- )
- }
- })
- .build()
- )
- val apiResponse = call.await()
- return apiResponse.result("Error calling /registerResponse") {
- parseUserCredentials(
- body ?: throw ApiException("Empty response from /registerResponse")
- )
- }
- }
-
- /**
- * @param sessionId The session ID.
- * @param credentialId The credential ID to be removed.
- */
- suspend fun removeKey(sessionId: String, credentialId: String): ApiResult {
- val call = client.newCall(
- Request.Builder()
- .url("$BASE_URL/removeKey?credId=$credentialId")
- .addHeader("Cookie", formatCookie(sessionId))
- .method("POST", jsonRequestBody {})
- .build()
- )
- val response = call.await()
- return response.result("Error calling /removeKey") { }
- }
-
- /**
- * @param sessionId The session ID to be used for the sign-in.
- * @param credentialId The credential ID of this device.
- * @return A pair. The `first` element is a [PublicKeyCredentialRequestOptions] that can be used
- * for a subsequent FIDO2 API call. The `second` element is a challenge string that should
- * be sent back to the server in [signinResponse].
- */
- suspend fun signinRequest(
- sessionId: String,
- credentialId: String?
- ): ApiResult {
- val call = client.newCall(
- Request.Builder()
- .url(
- buildString {
- append("$BASE_URL/signinRequest")
- if (credentialId != null) {
- append("?credId=$credentialId")
- }
- }
- )
- .addHeader("Cookie", formatCookie(sessionId))
- .method("POST", jsonRequestBody {})
- .build()
- )
- val response = call.await()
- return response.result("Error calling /signinRequest") {
- parsePublicKeyCredentialRequestOptions(
- body ?: throw ApiException("Empty response from /signinRequest")
- )
- }
- }
-
- /**
- * @param sessionId The session ID to be used for the sign-in.
- * @param credential The PublicKeyCredential object.
- * @return A list of all the credentials registered on the server, including the newly
- * registered one.
- */
- suspend fun signinResponse(
- sessionId: String,
- credential: PublicKeyCredential
- ): ApiResult> {
- val rawId = credential.rawId.toBase64()
- val response = credential.response as AuthenticatorAssertionResponse
-
- val call = client.newCall(
- Request.Builder()
- .url("$BASE_URL/signinResponse")
- .addHeader("Cookie", formatCookie(sessionId))
- .method("POST", jsonRequestBody {
- name("id").value(rawId)
- name("type").value(PublicKeyCredentialType.PUBLIC_KEY.toString())
- name("rawId").value(rawId)
- name("response").objectValue {
- name("clientDataJSON").value(
- response.clientDataJSON.toBase64()
- )
- name("authenticatorData").value(
- response.authenticatorData.toBase64()
- )
- name("signature").value(
- response.signature.toBase64()
- )
- name("userHandle").value(
- response.userHandle?.toBase64() ?: ""
- )
- }
- })
- .build()
- )
- val apiResponse = call.await()
- return apiResponse.result("Error calling /signingResponse") {
- parseUserCredentials(body ?: throw ApiException("Empty response from /signinResponse"))
- }
- }
-
- private fun parsePublicKeyCredentialRequestOptions(
- body: ResponseBody
- ): PublicKeyCredentialRequestOptions {
- val builder = PublicKeyCredentialRequestOptions.Builder()
- JsonReader(body.byteStream().bufferedReader()).use { reader ->
- reader.beginObject()
- while (reader.hasNext()) {
- when (reader.nextName()) {
- "challenge" -> builder.setChallenge(reader.nextString().decodeBase64())
- "userVerification" -> reader.skipValue()
- "allowCredentials" -> builder.setAllowList(parseCredentialDescriptors(reader))
- "rpId" -> builder.setRpId(reader.nextString())
- "timeout" -> builder.setTimeoutSeconds(reader.nextDouble())
- else -> reader.skipValue()
- }
- }
- reader.endObject()
- }
- return builder.build()
- }
-
- private fun parsePublicKeyCredentialCreationOptions(
- body: ResponseBody
- ): PublicKeyCredentialCreationOptions {
- val builder = PublicKeyCredentialCreationOptions.Builder()
- JsonReader(body.byteStream().bufferedReader()).use { reader ->
- reader.beginObject()
- while (reader.hasNext()) {
- when (reader.nextName()) {
- "user" -> builder.setUser(parseUser(reader))
- "challenge" -> builder.setChallenge(reader.nextString().decodeBase64())
- "pubKeyCredParams" -> builder.setParameters(parseParameters(reader))
- "timeout" -> builder.setTimeoutSeconds(reader.nextDouble())
- "attestation" -> reader.skipValue() // Unused
- "excludeCredentials" -> builder.setExcludeList(
- parseCredentialDescriptors(reader)
- )
- "authenticatorSelection" -> builder.setAuthenticatorSelection(
- parseSelection(reader)
- )
- "rp" -> builder.setRp(parseRp(reader))
- }
- }
- reader.endObject()
- }
- return builder.build()
- }
-
- private fun parseRp(reader: JsonReader): PublicKeyCredentialRpEntity {
- var id: String? = null
- var name: String? = null
- reader.beginObject()
- while (reader.hasNext()) {
- when (reader.nextName()) {
- "id" -> id = reader.nextString()
- "name" -> name = reader.nextString()
- else -> reader.skipValue()
- }
- }
- reader.endObject()
- return PublicKeyCredentialRpEntity(id!!, name!!, /* icon */ null)
- }
-
- private fun parseSelection(reader: JsonReader): AuthenticatorSelectionCriteria {
- val builder = AuthenticatorSelectionCriteria.Builder()
- reader.beginObject()
- while (reader.hasNext()) {
- when (reader.nextName()) {
- "authenticatorAttachment" -> builder.setAttachment(
- Attachment.fromString(reader.nextString())
- )
- "userVerification" -> reader.skipValue()
- else -> reader.skipValue()
- }
- }
- reader.endObject()
- return builder.build()
- }
-
- private fun parseCredentialDescriptors(
- reader: JsonReader
- ): List {
- val list = mutableListOf()
- reader.beginArray()
- while (reader.hasNext()) {
- var id: String? = null
- reader.beginObject()
- while (reader.hasNext()) {
- when (reader.nextName()) {
- "id" -> id = reader.nextString()
- "type" -> reader.skipValue()
- "transports" -> reader.skipValue()
- else -> reader.skipValue()
- }
- }
- reader.endObject()
- list.add(
- PublicKeyCredentialDescriptor(
- PublicKeyCredentialType.PUBLIC_KEY.toString(),
- id!!.decodeBase64(),
- /* transports */ null
- )
- )
- }
- reader.endArray()
- return list
- }
-
- private fun parseUser(reader: JsonReader): PublicKeyCredentialUserEntity {
- reader.beginObject()
- var id: String? = null
- var name: String? = null
- var displayName = ""
- while (reader.hasNext()) {
- when (reader.nextName()) {
- "id" -> id = reader.nextString()
- "name" -> name = reader.nextString()
- "displayName" -> displayName = reader.nextString()
- else -> reader.skipValue()
- }
- }
- reader.endObject()
- return PublicKeyCredentialUserEntity(
- id!!.decodeBase64(),
- name!!,
- null, // icon
- displayName
- )
- }
-
- private fun parseParameters(reader: JsonReader): List {
- val parameters = mutableListOf()
- reader.beginArray()
- while (reader.hasNext()) {
- reader.beginObject()
- var type: String? = null
- var alg = 0
- while (reader.hasNext()) {
- when (reader.nextName()) {
- "type" -> type = reader.nextString()
- "alg" -> alg = reader.nextInt()
- else -> reader.skipValue()
- }
- }
- reader.endObject()
- parameters.add(PublicKeyCredentialParameters(type!!, alg))
- }
- reader.endArray()
- return parameters
- }
-
- private fun jsonRequestBody(body: JsonWriter.() -> Unit): RequestBody {
- val output = StringWriter()
- JsonWriter(output).use { writer ->
- writer.beginObject()
- writer.body()
- writer.endObject()
- }
- return output.toString().toRequestBody(JSON)
- }
-
- private fun parseUserCredentials(body: ResponseBody): List {
- fun readCredentials(reader: JsonReader): List {
- val credentials = mutableListOf()
- reader.beginArray()
- while (reader.hasNext()) {
- reader.beginObject()
- var id: String? = null
- var publicKey: String? = null
- while (reader.hasNext()) {
- when (reader.nextName()) {
- "credId" -> id = reader.nextString()
- "publicKey" -> publicKey = reader.nextString()
- else -> reader.skipValue()
- }
- }
- reader.endObject()
- if (id != null && publicKey != null) {
- credentials.add(Credential(id, publicKey))
- }
- }
- reader.endArray()
- return credentials
- }
- JsonReader(body.byteStream().bufferedReader()).use { reader ->
- reader.beginObject()
- while (reader.hasNext()) {
- val name = reader.nextName()
- if (name == "credentials") {
- return readCredentials(reader)
- } else {
- reader.skipValue()
- }
- }
- reader.endObject()
- }
- throw ApiException("Cannot parse credentials")
- }
-
- private fun throwResponseError(response: Response, message: String): Nothing {
- val b = response.body
- if (b != null) {
- throw ApiException("$message; ${parseError(b)}")
- } else {
- throw ApiException(message)
- }
- }
-
- private fun parseError(body: ResponseBody): String {
- val errorString = body.string()
- try {
- JsonReader(StringReader(errorString)).use { reader ->
- reader.beginObject()
- while (reader.hasNext()) {
- val name = reader.nextName()
- if (name == "error") {
- val token = reader.peek()
- if (token == JsonToken.STRING) {
- return reader.nextString()
- }
- return "Unknown"
- } else {
- reader.skipValue()
- }
- }
- reader.endObject()
- }
- } catch (e: Exception) {
- Log.e(TAG, "Cannot parse the error: $errorString", e)
- // Don't throw; this method is called during throwing.
- }
- return ""
- }
-
- private fun JsonWriter.objectValue(body: JsonWriter.() -> Unit) {
- beginObject()
- body()
- endObject()
- }
-
- private fun Response.result(errorMessage: String, data: Response.() -> T): ApiResult {
- if (!isSuccessful) {
- if (code == 401) { // Unauthorized
- return ApiResult.SignedOutFromServer
- }
- // All other errors throw an exception.
- throwResponseError(this, errorMessage)
- }
- val cookie = headers("set-cookie").find { it.startsWith(SessionIdKey) }
- val sessionId = if (cookie != null) parseSessionId(cookie) else null
- return ApiResult.Success(sessionId, data())
- }
-
- private fun parseSessionId(cookie: String): String {
- val start = cookie.indexOf(SessionIdKey)
- if (start < 0) {
- throw ApiException("Cannot find $SessionIdKey")
- }
- val semicolon = cookie.indexOf(";", start + SessionIdKey.length)
- val end = if (semicolon < 0) cookie.length else semicolon
- return cookie.substring(start + SessionIdKey.length, end)
- }
-
- private fun formatCookie(sessionId: String): String {
- return "$SessionIdKey$sessionId"
- }
-}
diff --git a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/api/Credential.kt b/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/api/Credential.kt
deleted file mode 100644
index d2c9a47..0000000
--- a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/api/Credential.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2021 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.gms.identity.sample.fido2.api
-
-/**
- * A credential registered on the server.
- */
-data class Credential(
- val id: String,
- val publicKey: String
-)
diff --git a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/repository/AuthRepository.kt b/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/repository/AuthRepository.kt
deleted file mode 100644
index 39053cb..0000000
--- a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/repository/AuthRepository.kt
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Copyright 2021 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.gms.identity.sample.fido2.repository
-
-import android.app.PendingIntent
-import android.util.Log
-import androidx.datastore.core.DataStore
-import androidx.datastore.preferences.core.Preferences
-import androidx.datastore.preferences.core.edit
-import androidx.datastore.preferences.core.stringPreferencesKey
-import androidx.datastore.preferences.core.stringSetPreferencesKey
-import com.google.android.gms.identity.sample.fido2.api.ApiException
-import com.google.android.gms.identity.sample.fido2.api.ApiResult
-import com.google.android.gms.identity.sample.fido2.api.AuthApi
-import com.google.android.gms.identity.sample.fido2.api.Credential
-import com.google.android.gms.identity.sample.fido2.toBase64
-import com.google.android.gms.fido.fido2.Fido2ApiClient
-import com.google.android.gms.fido.fido2.api.common.PublicKeyCredential
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.channels.BufferOverflow
-import kotlinx.coroutines.flow.MutableSharedFlow
-import kotlinx.coroutines.flow.asSharedFlow
-import kotlinx.coroutines.flow.first
-import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.tasks.await
-import javax.inject.Inject
-import javax.inject.Singleton
-
-/**
- * Works with the API, the local data store, and FIDO2 API.
- */
-@Singleton
-class AuthRepository @Inject constructor(
- private val api: AuthApi,
- private val dataStore: DataStore,
- scope: CoroutineScope
-) {
-
- private companion object {
- const val TAG = "AuthRepository"
-
- // Keys for SharedPreferences
- val USERNAME = stringPreferencesKey("username")
- val SESSION_ID = stringPreferencesKey("session_id")
- val CREDENTIALS = stringSetPreferencesKey("credentials")
- val LOCAL_CREDENTIAL_ID = stringPreferencesKey("local_credential_id")
-
- suspend fun DataStore.read(key: Preferences.Key): T? {
- return data.map { it[key] }.first()
- }
- }
-
- private var fido2ApiClient: Fido2ApiClient? = null
-
- fun setFido2APiClient(client: Fido2ApiClient?) {
- fido2ApiClient = client
- }
-
- private val signInStateMutable = MutableSharedFlow(
- replay = 1,
- onBufferOverflow = BufferOverflow.DROP_OLDEST
- )
- /** The current [SignInState]. */
- val signInState = signInStateMutable.asSharedFlow()
-
- /**
- * The list of credentials this user has registered on the server. This is only populated when
- * the sign-in state is [SignInState.SignedIn].
- */
- val credentials =
- dataStore.data.map { it[CREDENTIALS] ?: emptySet() }.map { parseCredentials(it) }
-
- init {
- scope.launch {
- val username = dataStore.read(USERNAME)
- val sessionId = dataStore.read(SESSION_ID)
- val initialState = when {
- username.isNullOrBlank() -> SignInState.SignedOut
- sessionId.isNullOrBlank() -> SignInState.SigningIn(username)
- else -> SignInState.SignedIn(username)
- }
- signInStateMutable.emit(initialState)
- if (initialState is SignInState.SignedIn) {
- refreshCredentials()
- }
- }
- }
-
- /**
- * Sends the username to the server. If it succeeds, the sign-in state will proceed to
- * [SignInState.SigningIn].
- */
- suspend fun username(username: String) {
- when (val result = api.username(username)) {
- ApiResult.SignedOutFromServer -> forceSignOut()
- is ApiResult.Success -> {
- dataStore.edit { prefs ->
- prefs[USERNAME] = username
- prefs[SESSION_ID] = result.sessionId!!
- }
- signInStateMutable.emit(SignInState.SigningIn(username))
- }
- }
- }
-
- /**
- * Signs in with a password. This should be called only when the sign-in state is
- * [SignInState.SigningIn]. If it succeeds, the sign-in state will proceed to
- * [SignInState.SignedIn].
- */
- suspend fun password(password: String) {
- val username = dataStore.read(USERNAME)!!
- val sessionId = dataStore.read(SESSION_ID)!!
- try {
- when (val result = api.password(sessionId, password)) {
- ApiResult.SignedOutFromServer -> forceSignOut()
- is ApiResult.Success -> {
- if (result.sessionId != null) {
- dataStore.edit { prefs ->
- prefs[SESSION_ID] = result.sessionId
- }
- }
- signInStateMutable.emit(SignInState.SignedIn(username))
- refreshCredentials()
- }
- }
- } catch (e: ApiException) {
- Log.e(TAG, "Invalid login credentials", e)
-
- // start login over again
- dataStore.edit { prefs ->
- prefs.remove(USERNAME)
- prefs.remove(SESSION_ID)
- prefs.remove(CREDENTIALS)
- }
-
- signInStateMutable.emit(
- SignInState.SignInError(e.message ?: "Invalid login credentials")
- )
- }
- }
-
- private suspend fun refreshCredentials() {
- val sessionId = dataStore.read(SESSION_ID)!!
- when (val result = api.getKeys(sessionId)) {
- ApiResult.SignedOutFromServer -> forceSignOut()
- is ApiResult.Success -> {
- dataStore.edit { prefs ->
- result.sessionId?.let { prefs[SESSION_ID] = it }
- prefs[CREDENTIALS] = result.data.toStringSet()
- }
- }
- }
- }
-
- private fun List.toStringSet(): Set {
- return mapIndexed { index, credential ->
- "$index;${credential.id};${credential.publicKey}"
- }.toSet()
- }
-
- private fun parseCredentials(set: Set): List {
- return set.map { s ->
- val (index, id, publicKey) = s.split(";")
- index to Credential(id, publicKey)
- }.sortedBy { (index, _) -> index }
- .map { (_, credential) -> credential }
- }
-
- /**
- * Clears the credentials. The sign-in state will proceed to [SignInState.SigningIn].
- */
- suspend fun clearCredentials() {
- val username = dataStore.read(USERNAME)!!
- dataStore.edit { prefs ->
- prefs.remove(CREDENTIALS)
- }
- signInStateMutable.emit(SignInState.SigningIn(username))
- }
-
- /**
- * Clears all the sign-in information. The sign-in state will proceed to
- * [SignInState.SignedOut].
- */
- suspend fun signOut() {
- dataStore.edit { prefs ->
- prefs.remove(USERNAME)
- prefs.remove(SESSION_ID)
- prefs.remove(CREDENTIALS)
- }
- signInStateMutable.emit(SignInState.SignedOut)
- }
-
- private suspend fun forceSignOut() {
- dataStore.edit { prefs ->
- prefs.remove(USERNAME)
- prefs.remove(SESSION_ID)
- prefs.remove(CREDENTIALS)
- }
- signInStateMutable.emit(SignInState.SignInError("Signed out by server"))
- }
-
- /**
- * Starts to register a new credential to the server. This should be called only when the
- * sign-in state is [SignInState.SignedIn].
- */
- suspend fun registerRequest(): PendingIntent? {
- fido2ApiClient?.let { client ->
- try {
- val sessionId = dataStore.read(SESSION_ID)!!
- when (val apiResult = api.registerRequest(sessionId)) {
- ApiResult.SignedOutFromServer -> forceSignOut()
- is ApiResult.Success -> {
- if (apiResult.sessionId != null) {
- dataStore.edit { prefs ->
- prefs[SESSION_ID] = apiResult.sessionId
- }
- }
- val task = client.getRegisterPendingIntent(apiResult.data)
- return task.await()
- }
- }
- } catch (e: Exception) {
- Log.e(TAG, "Cannot call registerRequest", e)
- }
- }
- return null
- }
-
- /**
- * Finishes registering a new credential to the server. This should only be called after
- * a call to [registerRequest] and a local FIDO2 API for public key generation.
- */
- suspend fun registerResponse(credential: PublicKeyCredential) {
- try {
- val sessionId = dataStore.read(SESSION_ID)!!
- val credentialId = credential.rawId.toBase64()
- when (val result = api.registerResponse(sessionId, credential)) {
- ApiResult.SignedOutFromServer -> forceSignOut()
- is ApiResult.Success -> {
- dataStore.edit { prefs ->
- result.sessionId?.let { prefs[SESSION_ID] = it }
- prefs[CREDENTIALS] = result.data.toStringSet()
- prefs[LOCAL_CREDENTIAL_ID] = credentialId
- }
- }
- }
- } catch (e: ApiException) {
- Log.e(TAG, "Cannot call registerResponse", e)
- }
- }
-
- /**
- * Removes a credential registered on the server.
- */
- suspend fun removeKey(credentialId: String) {
- try {
- val sessionId = dataStore.read(SESSION_ID)!!
- when (api.removeKey(sessionId, credentialId)) {
- ApiResult.SignedOutFromServer -> forceSignOut()
- is ApiResult.Success -> refreshCredentials()
- }
- } catch (e: ApiException) {
- Log.e(TAG, "Cannot call removeKey", e)
- }
- }
-
- /**
- * Starts to sign in with a FIDO2 credential. This should only be called when the sign-in state
- * is [SignInState.SigningIn].
- */
- suspend fun signinRequest(): PendingIntent? {
- fido2ApiClient?.let { client ->
- val sessionId = dataStore.read(SESSION_ID)!!
- val credentialId = dataStore.read(LOCAL_CREDENTIAL_ID)
- if (credentialId != null) {
- when (val apiResult = api.signinRequest(sessionId, credentialId)) {
- ApiResult.SignedOutFromServer -> forceSignOut()
- is ApiResult.Success -> {
- val task = client.getSignPendingIntent(apiResult.data)
- return task.await()
- }
- }
- }
- }
- return null
- }
-
- /**
- * Finishes to signing in with a FIDO2 credential. This should only be called after a call to
- * [signinRequest] and a local FIDO2 API for key assertion.
- */
- suspend fun signinResponse(credential: PublicKeyCredential) {
- try {
- val username = dataStore.read(USERNAME)!!
- val sessionId = dataStore.read(SESSION_ID)!!
- val credentialId = credential.rawId.toBase64()
- when (val result = api.signinResponse(sessionId, credential)) {
- ApiResult.SignedOutFromServer -> forceSignOut()
- is ApiResult.Success -> {
- dataStore.edit { prefs ->
- result.sessionId?.let { prefs[SESSION_ID] = it }
- prefs[CREDENTIALS] = result.data.toStringSet()
- prefs[LOCAL_CREDENTIAL_ID] = credentialId
- }
- signInStateMutable.emit(SignInState.SignedIn(username))
- refreshCredentials()
- }
- }
- } catch (e: ApiException) {
- Log.e(TAG, "Cannot call registerResponse", e)
- }
- }
-}
diff --git a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/repository/SignInState.kt b/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/repository/SignInState.kt
deleted file mode 100644
index 7124046..0000000
--- a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/repository/SignInState.kt
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2021 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.gms.identity.sample.fido2.repository
-
-/**
- * Represents the sign in/out state of the user. Used to navigate between screens in the app.
- */
-sealed class SignInState {
-
- /**
- * The user is signed out.
- */
- object SignedOut : SignInState()
-
- /**
- * The user is signing in. The user has entered the username and is ready to sign in with
- * password or FIDO2.
- */
- data class SigningIn(
- val username: String
- ) : SignInState()
-
- /**
- * The user sign-in failed.
- */
- data class SignInError(
- val error: String
- ) : SignInState()
-
- /**
- * The user is signed in.
- */
- data class SignedIn(
- val username: String
- ) : SignInState()
-}
diff --git a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/ui/MainActivity.kt b/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/ui/MainActivity.kt
deleted file mode 100644
index c9ff884..0000000
--- a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/ui/MainActivity.kt
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2021 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.gms.identity.sample.fido2.ui
-
-import android.os.Bundle
-import android.widget.Toast
-import androidx.activity.viewModels
-import androidx.appcompat.app.AppCompatActivity
-import androidx.fragment.app.Fragment
-import androidx.fragment.app.commit
-import androidx.lifecycle.lifecycleScope
-import com.google.android.gms.identity.sample.fido2.R
-import com.google.android.gms.identity.sample.fido2.repository.SignInState
-import com.google.android.gms.identity.sample.fido2.ui.auth.AuthFragment
-import com.google.android.gms.identity.sample.fido2.ui.home.HomeFragment
-import com.google.android.gms.identity.sample.fido2.ui.username.UsernameFragment
-import com.google.android.gms.fido.Fido
-import dagger.hilt.android.AndroidEntryPoint
-import kotlinx.coroutines.flow.collect
-
-@AndroidEntryPoint
-class MainActivity : AppCompatActivity() {
-
- private val viewModel: MainViewModel by viewModels()
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.main_activity)
- setSupportActionBar(findViewById(R.id.toolbar))
-
- lifecycleScope.launchWhenStarted {
- viewModel.signInState.collect { state ->
- when (state) {
- is SignInState.SignedOut -> {
- showFragment(UsernameFragment::class.java) { UsernameFragment() }
- }
- is SignInState.SigningIn -> {
- showFragment(AuthFragment::class.java) { AuthFragment() }
- }
- is SignInState.SignInError -> {
- Toast.makeText(this@MainActivity, state.error, Toast.LENGTH_LONG).show()
- // return to username prompt
- showFragment(UsernameFragment::class.java) { UsernameFragment() }
- }
- is SignInState.SignedIn -> {
- showFragment(HomeFragment::class.java) { HomeFragment() }
- }
- }
- }
- }
- }
-
- override fun onResume() {
- super.onResume()
- viewModel.setFido2ApiClient(Fido.getFido2ApiClient(this))
- }
-
- override fun onPause() {
- super.onPause()
- viewModel.setFido2ApiClient(null)
- }
-
- private fun showFragment(clazz: Class, create: () -> Fragment) {
- val manager = supportFragmentManager
- if (!clazz.isInstance(manager.findFragmentById(R.id.container))) {
- manager.commit {
- replace(R.id.container, create())
- }
- }
- }
-
-}
diff --git a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/ui/MainViewModel.kt b/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/ui/MainViewModel.kt
deleted file mode 100644
index 68b9545..0000000
--- a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/ui/MainViewModel.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2021 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.gms.identity.sample.fido2.ui
-
-import androidx.lifecycle.ViewModel
-import com.google.android.gms.identity.sample.fido2.repository.AuthRepository
-import com.google.android.gms.fido.fido2.Fido2ApiClient
-import dagger.hilt.android.lifecycle.HiltViewModel
-import javax.inject.Inject
-
-@HiltViewModel
-class MainViewModel @Inject constructor(
- private val repository: AuthRepository
-) : ViewModel() {
-
- val signInState = repository.signInState
-
- fun setFido2ApiClient(client: Fido2ApiClient?) {
- repository.setFido2APiClient(client)
- }
-
-}
diff --git a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/ui/auth/AuthFragment.kt b/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/ui/auth/AuthFragment.kt
deleted file mode 100644
index f7210ec..0000000
--- a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/ui/auth/AuthFragment.kt
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright 2021 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.gms.identity.sample.fido2.ui.auth
-
-import android.app.Activity
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.view.inputmethod.EditorInfo
-import android.widget.Toast
-import androidx.activity.result.ActivityResult
-import androidx.activity.result.IntentSenderRequest
-import androidx.activity.result.contract.ActivityResultContracts
-import androidx.fragment.app.Fragment
-import androidx.fragment.app.viewModels
-import androidx.lifecycle.lifecycleScope
-import com.google.android.gms.identity.sample.fido2.R
-import com.google.android.gms.identity.sample.fido2.databinding.AuthFragmentBinding
-import com.google.android.gms.fido.Fido
-import com.google.android.gms.fido.fido2.api.common.AuthenticatorErrorResponse
-import com.google.android.gms.fido.fido2.api.common.PublicKeyCredential
-import dagger.hilt.android.AndroidEntryPoint
-import kotlinx.coroutines.flow.collect
-import kotlinx.coroutines.launch
-
-@AndroidEntryPoint
-class AuthFragment : Fragment() {
-
- private val viewModel: AuthViewModel by viewModels()
- private lateinit var binding: AuthFragmentBinding
-
- private val signIntentLauncher = registerForActivityResult(
- ActivityResultContracts.StartIntentSenderForResult(),
- ::handleSignResult
- )
-
- override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View? {
- binding = AuthFragmentBinding.inflate(inflater, container, false)
- binding.lifecycleOwner = viewLifecycleOwner
- binding.viewModel = viewModel
- return binding.root
- }
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- binding.inputPassword.setOnEditorActionListener { _, actionId, _ ->
- if (actionId == EditorInfo.IME_ACTION_GO) {
- viewModel.submitPassword()
- true
- } else {
- false
- }
- }
-
- viewLifecycleOwner.lifecycleScope.launchWhenStarted {
- launch {
- viewModel.signinRequests.collect { intent ->
- signIntentLauncher.launch(IntentSenderRequest.Builder(intent).build())
- }
- }
- launch {
- viewModel.processing.collect { processing ->
- if (processing) {
- binding.processing.show()
- } else {
- binding.processing.hide()
- }
- }
- }
- }
- }
-
- private fun handleSignResult(activityResult: ActivityResult) {
- val bytes = activityResult.data?.getByteArrayExtra(Fido.FIDO2_KEY_CREDENTIAL_EXTRA)
- when {
- activityResult.resultCode != Activity.RESULT_OK ->
- Toast.makeText(requireContext(), R.string.cancelled, Toast.LENGTH_LONG).show()
- bytes == null ->
- Toast.makeText(requireContext(), R.string.auth_error, Toast.LENGTH_LONG).show()
- else -> {
- val credential = PublicKeyCredential.deserializeFromBytes(bytes)
- val response = credential.response
- if (response is AuthenticatorErrorResponse) {
- Toast.makeText(requireContext(), response.errorMessage, Toast.LENGTH_LONG)
- .show()
- } else {
- viewModel.signinResponse(credential)
- }
- }
- }
- }
-}
diff --git a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/ui/auth/AuthViewModel.kt b/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/ui/auth/AuthViewModel.kt
deleted file mode 100644
index 8d077e1..0000000
--- a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/ui/auth/AuthViewModel.kt
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright 2021 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.gms.identity.sample.fido2.ui.auth
-
-import android.app.PendingIntent
-import androidx.lifecycle.ViewModel
-import androidx.lifecycle.viewModelScope
-import com.google.android.gms.identity.sample.fido2.repository.AuthRepository
-import com.google.android.gms.identity.sample.fido2.repository.SignInState
-import com.google.android.gms.fido.fido2.api.common.PublicKeyCredential
-import dagger.hilt.android.lifecycle.HiltViewModel
-import kotlinx.coroutines.channels.Channel
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.SharingStarted
-import kotlinx.coroutines.flow.asStateFlow
-import kotlinx.coroutines.flow.combine
-import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.receiveAsFlow
-import kotlinx.coroutines.flow.stateIn
-import kotlinx.coroutines.launch
-import javax.inject.Inject
-
-@HiltViewModel
-class AuthViewModel @Inject constructor(
- private val repository: AuthRepository
-) : ViewModel() {
-
- val password = MutableStateFlow("")
-
- private val _processing = MutableStateFlow(false)
- val processing = _processing.asStateFlow()
-
- private val _errorMessage = MutableStateFlow(null)
- val errorMessage = _errorMessage.asStateFlow()
-
- val signInEnabled = combine(processing, password) { isProcessing, password ->
- !isProcessing && password.isNotBlank()
- }.stateIn(viewModelScope, SharingStarted.Eagerly, false)
-
- private val signinRequestChannel = Channel(capacity = Channel.CONFLATED)
- val signinRequests = signinRequestChannel.receiveAsFlow()
-
- init {
- // See if we can authenticate using FIDO.
- viewModelScope.launch {
- val intent = repository.signinRequest()
- if (intent != null) {
- signinRequestChannel.send(intent)
- }
- }
- }
-
- val currentUsername = repository.signInState.map { state ->
- when (state) {
- is SignInState.SigningIn -> state.username
- is SignInState.SignedIn -> state.username
- else -> "(user)"
- }
- }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), "(user)")
-
- fun submitPassword() {
- viewModelScope.launch {
- _processing.value = true
- try {
- repository.password(password.value)
- } finally {
- _processing.value = false
- }
- }
- }
-
- fun signinResponse(credential: PublicKeyCredential) {
- viewModelScope.launch {
- _processing.value = true
- try {
- repository.signinResponse(credential)
- } finally {
- _processing.value = false
- }
- }
- }
-
-}
diff --git a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/ui/home/CredentialAdapter.kt b/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/ui/home/CredentialAdapter.kt
deleted file mode 100644
index 8a5dc3b..0000000
--- a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/ui/home/CredentialAdapter.kt
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2021 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.gms.identity.sample.fido2.ui.home
-
-import android.view.LayoutInflater
-import android.view.ViewGroup
-import androidx.recyclerview.widget.DiffUtil
-import androidx.recyclerview.widget.ListAdapter
-import androidx.recyclerview.widget.RecyclerView
-import com.google.android.gms.identity.sample.fido2.api.Credential
-import com.google.android.gms.identity.sample.fido2.databinding.CredentialItemBinding
-
-class CredentialAdapter(
- private val onDeleteClicked: (String) -> Unit
-) : ListAdapter(DIFF_CALLBACK) {
-
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CredentialViewHolder {
- return CredentialViewHolder(
- CredentialItemBinding.inflate(
- LayoutInflater.from(parent.context),
- parent,
- false
- ),
- onDeleteClicked
- )
- }
-
- override fun onBindViewHolder(holder: CredentialViewHolder, position: Int) {
- holder.binding.credential = getItem(position)
- }
-}
-
-private val DIFF_CALLBACK = object : DiffUtil.ItemCallback() {
- override fun areItemsTheSame(oldItem: Credential, newItem: Credential): Boolean {
- return oldItem.id == newItem.id
- }
-
- override fun areContentsTheSame(oldItem: Credential, newItem: Credential): Boolean {
- return oldItem == newItem
- }
-}
-
-class CredentialViewHolder(
- val binding: CredentialItemBinding,
- onDeleteClicked: (String) -> Unit
-) : RecyclerView.ViewHolder(binding.root) {
- init {
- binding.delete.setOnClickListener {
- binding.credential?.let { c ->
- onDeleteClicked(c.id)
- }
- }
- }
-}
diff --git a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/ui/home/DeleteConfirmationFragment.kt b/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/ui/home/DeleteConfirmationFragment.kt
deleted file mode 100644
index 529e30e..0000000
--- a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/ui/home/DeleteConfirmationFragment.kt
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2021 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.gms.identity.sample.fido2.ui.home
-
-import android.app.Dialog
-import android.os.Bundle
-import androidx.appcompat.app.AlertDialog
-import androidx.fragment.app.DialogFragment
-import com.google.android.gms.identity.sample.fido2.R
-
-class DeleteConfirmationFragment : DialogFragment() {
-
- companion object {
- private const val ARG_CREDENTIAL_ID = "credential_id"
-
- fun newInstance(credentialId: String) = DeleteConfirmationFragment().apply {
- arguments = Bundle().apply {
- putString(ARG_CREDENTIAL_ID, credentialId)
- }
- }
- }
-
- override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
- val credentialId = arguments?.getString(ARG_CREDENTIAL_ID) ?: throw RuntimeException()
- return AlertDialog.Builder(requireContext())
- .setMessage(getString(R.string.delete_confirmation, credentialId))
- .setPositiveButton(android.R.string.ok) { _, _ ->
- (parentFragment as Listener).onDeleteConfirmed(credentialId)
- dismiss()
- }
- .setNegativeButton(android.R.string.cancel) { _, _ ->
- dismiss()
- }
- .create()
- }
-
- interface Listener {
- fun onDeleteConfirmed(credentialId: String)
- }
-
-}
diff --git a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/ui/home/HomeFragment.kt b/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/ui/home/HomeFragment.kt
deleted file mode 100644
index 7fd6c69..0000000
--- a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/ui/home/HomeFragment.kt
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright 2021 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.gms.identity.sample.fido2.ui.home
-
-import android.app.Activity
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.Toast
-import androidx.activity.result.ActivityResult
-import androidx.activity.result.IntentSenderRequest
-import androidx.activity.result.contract.ActivityResultContracts
-import androidx.core.view.isVisible
-import androidx.fragment.app.Fragment
-import androidx.fragment.app.viewModels
-import androidx.lifecycle.lifecycleScope
-import com.google.android.gms.fido.Fido
-import com.google.android.gms.fido.fido2.api.common.AuthenticatorErrorResponse
-import com.google.android.gms.fido.fido2.api.common.PublicKeyCredential
-import com.google.android.gms.identity.sample.fido2.R
-import com.google.android.gms.identity.sample.fido2.databinding.HomeFragmentBinding
-import dagger.hilt.android.AndroidEntryPoint
-import kotlinx.coroutines.flow.collect
-import kotlinx.coroutines.launch
-
-@AndroidEntryPoint
-class HomeFragment : Fragment(), DeleteConfirmationFragment.Listener {
-
- companion object {
- private const val TAG = "HomeFragment"
- private const val FRAGMENT_DELETE_CONFIRMATION = "delete_confirmation"
- }
-
- private val viewModel: HomeViewModel by viewModels()
- private lateinit var binding: HomeFragmentBinding
-
- private val createCredentialIntentLauncher = registerForActivityResult(
- ActivityResultContracts.StartIntentSenderForResult(),
- ::handleCreateCredentialResult
- )
-
- override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?, savedInstanceState: Bundle?
- ): View? {
- binding = HomeFragmentBinding.inflate(inflater, container, false)
- binding.lifecycleOwner = viewLifecycleOwner
- binding.viewModel = viewModel
- return binding.root
- }
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- val credentialAdapter = CredentialAdapter { credentialId ->
- DeleteConfirmationFragment.newInstance(credentialId)
- .show(childFragmentManager, FRAGMENT_DELETE_CONFIRMATION)
- }
- binding.credentials.adapter = credentialAdapter
-
- viewLifecycleOwner.lifecycleScope.launchWhenStarted {
- viewModel.credentials.collect { credentials ->
- credentialAdapter.submitList(credentials)
- binding.emptyCredentials.isVisible = credentials.isEmpty()
- binding.credentialsCaption.isVisible = credentials.isNotEmpty()
- }
- }
-
- // Menu
- binding.appBar.replaceMenu(R.menu.home)
- binding.appBar.setOnMenuItemClickListener { item ->
- when (item.itemId) {
- R.id.action_reauth -> {
- viewModel.reauth()
- true
- }
- R.id.action_sign_out -> {
- viewModel.signOut()
- true
- }
- else -> false
- }
- }
-
- viewLifecycleOwner.lifecycleScope.launchWhenStarted {
- viewModel.processing.collect { processing ->
- if (processing) {
- binding.processing.show()
- } else {
- binding.processing.hide()
- }
- }
- }
-
- // FAB
- binding.add.setOnClickListener {
- lifecycleScope.launch {
- val intent = viewModel.registerRequest()
- if (intent != null) {
- createCredentialIntentLauncher.launch(
- IntentSenderRequest.Builder(intent).build()
- )
- }
- }
- }
- }
-
- override fun onDeleteConfirmed(credentialId: String) {
- viewModel.removeKey(credentialId)
- }
-
- private fun handleCreateCredentialResult(activityResult: ActivityResult) {
- val bytes = activityResult.data?.getByteArrayExtra(Fido.FIDO2_KEY_CREDENTIAL_EXTRA)
- when {
- activityResult.resultCode != Activity.RESULT_OK ->
- Toast.makeText(requireContext(), R.string.cancelled, Toast.LENGTH_LONG).show()
- bytes == null ->
- Toast.makeText(requireContext(), R.string.credential_error, Toast.LENGTH_LONG)
- .show()
- else -> {
- val credential = PublicKeyCredential.deserializeFromBytes(bytes)
- val response = credential.response
- if (response is AuthenticatorErrorResponse) {
- Toast.makeText(requireContext(), response.errorMessage, Toast.LENGTH_LONG)
- .show()
- } else {
- viewModel.registerResponse(credential)
- }
- }
- }
- }
-}
diff --git a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/ui/home/HomeViewModel.kt b/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/ui/home/HomeViewModel.kt
deleted file mode 100644
index 7654fc9..0000000
--- a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/ui/home/HomeViewModel.kt
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright 2021 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.gms.identity.sample.fido2.ui.home
-
-import android.app.PendingIntent
-import androidx.lifecycle.ViewModel
-import androidx.lifecycle.viewModelScope
-import com.google.android.gms.identity.sample.fido2.repository.AuthRepository
-import com.google.android.gms.identity.sample.fido2.repository.SignInState
-import com.google.android.gms.fido.fido2.api.common.PublicKeyCredential
-import dagger.hilt.android.lifecycle.HiltViewModel
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.SharingStarted
-import kotlinx.coroutines.flow.asStateFlow
-import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.stateIn
-import kotlinx.coroutines.launch
-import javax.inject.Inject
-
-@HiltViewModel
-class HomeViewModel @Inject constructor(
- private val repository: AuthRepository
-) : ViewModel() {
-
- private val _processing = MutableStateFlow(false)
- val processing = _processing.asStateFlow()
-
- val currentUsername = repository.signInState.map { state ->
- when (state) {
- is SignInState.SigningIn -> state.username
- is SignInState.SignedIn -> state.username
- else -> "(user)"
- }
- }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), "(user)")
-
- val credentials = repository.credentials.stateIn(
- viewModelScope, SharingStarted.WhileSubscribed(), emptyList()
- )
-
- fun reauth() {
- viewModelScope.launch {
- repository.clearCredentials()
- }
- }
-
- fun signOut() {
- viewModelScope.launch {
- repository.signOut()
- }
- }
-
- suspend fun registerRequest(): PendingIntent? {
- _processing.value = true
- try {
- return repository.registerRequest()
- } finally {
- _processing.value = false
- }
- }
-
- fun registerResponse(credential: PublicKeyCredential) {
- viewModelScope.launch {
- _processing.value = true
- try {
- repository.registerResponse(credential)
- } finally {
- _processing.value = false
- }
- }
- }
-
- fun removeKey(credentialId: String) {
- viewModelScope.launch {
- _processing.value = true
- try {
- repository.removeKey(credentialId)
- } finally {
- _processing.value = false
- }
- }
- }
-
-}
diff --git a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/ui/username/UsernameFragment.kt b/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/ui/username/UsernameFragment.kt
deleted file mode 100644
index 5ed3905..0000000
--- a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/ui/username/UsernameFragment.kt
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2021 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.gms.identity.sample.fido2.ui.username
-
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.view.inputmethod.EditorInfo
-import androidx.fragment.app.Fragment
-import androidx.fragment.app.viewModels
-import androidx.lifecycle.lifecycleScope
-import com.google.android.gms.identity.sample.fido2.databinding.UsernameFragmentBinding
-import dagger.hilt.android.AndroidEntryPoint
-import kotlinx.coroutines.flow.collect
-
-@AndroidEntryPoint
-class UsernameFragment : Fragment() {
-
- private val viewModel: UsernameViewModel by viewModels()
- private lateinit var binding: UsernameFragmentBinding
-
- override fun onCreateView(
- inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View? {
- binding = UsernameFragmentBinding.inflate(inflater, container, false)
- binding.lifecycleOwner = viewLifecycleOwner
- binding.viewModel = viewModel
- return binding.root
- }
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- viewLifecycleOwner.lifecycleScope.launchWhenStarted {
- viewModel.sending.collect { sending ->
- if (sending) {
- binding.sending.show()
- } else {
- binding.sending.hide()
- }
- }
- }
-
- binding.inputUsername.setOnEditorActionListener { _, actionId, _ ->
- if (actionId == EditorInfo.IME_ACTION_NEXT) {
- viewModel.sendUsername()
- true
- } else {
- false
- }
- }
- }
-
-}
diff --git a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/ui/username/UsernameViewModel.kt b/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/ui/username/UsernameViewModel.kt
deleted file mode 100644
index e35416c..0000000
--- a/Fido2/app/src/main/java/com/google/android/gms/identity/sample/fido2/ui/username/UsernameViewModel.kt
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2021 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.gms.identity.sample.fido2.ui.username
-
-import androidx.lifecycle.ViewModel
-import androidx.lifecycle.viewModelScope
-import com.google.android.gms.identity.sample.fido2.repository.AuthRepository
-import dagger.hilt.android.lifecycle.HiltViewModel
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.SharingStarted
-import kotlinx.coroutines.flow.asStateFlow
-import kotlinx.coroutines.flow.combine
-import kotlinx.coroutines.flow.stateIn
-import kotlinx.coroutines.launch
-import javax.inject.Inject
-
-@HiltViewModel
-class UsernameViewModel @Inject constructor(
- private val repository: AuthRepository
-) : ViewModel() {
-
- private val _sending = MutableStateFlow(false)
- val sending = _sending.asStateFlow()
-
- val username = MutableStateFlow("")
-
- val nextEnabled = combine(sending, username) { isSending, username ->
- !isSending && username.isNotBlank()
- }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), false)
-
- fun sendUsername() {
- val username = username.value
- if (username.isNotBlank()) {
- viewModelScope.launch {
- _sending.value = true
- try {
- repository.username(username)
- } finally {
- _sending.value = false
- }
- }
- }
- }
-}
diff --git a/Fido2/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/Fido2/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
deleted file mode 100644
index 00c25f2..0000000
--- a/Fido2/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Fido2/app/src/main/res/drawable/ic_add.xml b/Fido2/app/src/main/res/drawable/ic_add.xml
deleted file mode 100644
index 459764c..0000000
--- a/Fido2/app/src/main/res/drawable/ic_add.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
diff --git a/Fido2/app/src/main/res/drawable/ic_delete.xml b/Fido2/app/src/main/res/drawable/ic_delete.xml
deleted file mode 100644
index 51d48f0..0000000
--- a/Fido2/app/src/main/res/drawable/ic_delete.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
diff --git a/Fido2/app/src/main/res/drawable/ic_launcher_background.xml b/Fido2/app/src/main/res/drawable/ic_launcher_background.xml
deleted file mode 100644
index 7f3a242..0000000
--- a/Fido2/app/src/main/res/drawable/ic_launcher_background.xml
+++ /dev/null
@@ -1,187 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Fido2/app/src/main/res/layout/auth_fragment.xml b/Fido2/app/src/main/res/layout/auth_fragment.xml
deleted file mode 100644
index 58e6054..0000000
--- a/Fido2/app/src/main/res/layout/auth_fragment.xml
+++ /dev/null
@@ -1,129 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Fido2/app/src/main/res/layout/credential_item.xml b/Fido2/app/src/main/res/layout/credential_item.xml
deleted file mode 100644
index e2d9a44..0000000
--- a/Fido2/app/src/main/res/layout/credential_item.xml
+++ /dev/null
@@ -1,82 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Fido2/app/src/main/res/layout/home_fragment.xml b/Fido2/app/src/main/res/layout/home_fragment.xml
deleted file mode 100644
index fc0488a..0000000
--- a/Fido2/app/src/main/res/layout/home_fragment.xml
+++ /dev/null
@@ -1,128 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Fido2/app/src/main/res/layout/main_activity.xml b/Fido2/app/src/main/res/layout/main_activity.xml
deleted file mode 100644
index 2f955e3..0000000
--- a/Fido2/app/src/main/res/layout/main_activity.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Fido2/app/src/main/res/layout/username_fragment.xml b/Fido2/app/src/main/res/layout/username_fragment.xml
deleted file mode 100644
index 57a2bac..0000000
--- a/Fido2/app/src/main/res/layout/username_fragment.xml
+++ /dev/null
@@ -1,112 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Fido2/app/src/main/res/menu/home.xml b/Fido2/app/src/main/res/menu/home.xml
deleted file mode 100644
index 784b880..0000000
--- a/Fido2/app/src/main/res/menu/home.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
diff --git a/Fido2/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/Fido2/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
deleted file mode 100644
index 71c7a0c..0000000
--- a/Fido2/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
diff --git a/Fido2/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/Fido2/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
deleted file mode 100644
index 71c7a0c..0000000
--- a/Fido2/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
diff --git a/Fido2/app/src/main/res/mipmap-hdpi/ic_launcher.png b/Fido2/app/src/main/res/mipmap-hdpi/ic_launcher.png
deleted file mode 100644
index 898f3ed..0000000
Binary files a/Fido2/app/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ
diff --git a/Fido2/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/Fido2/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
deleted file mode 100644
index dffca36..0000000
Binary files a/Fido2/app/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ
diff --git a/Fido2/app/src/main/res/mipmap-mdpi/ic_launcher.png b/Fido2/app/src/main/res/mipmap-mdpi/ic_launcher.png
deleted file mode 100644
index 64ba76f..0000000
Binary files a/Fido2/app/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ
diff --git a/Fido2/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/Fido2/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
deleted file mode 100644
index dae5e08..0000000
Binary files a/Fido2/app/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ
diff --git a/Fido2/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/Fido2/app/src/main/res/mipmap-xhdpi/ic_launcher.png
deleted file mode 100644
index e5ed465..0000000
Binary files a/Fido2/app/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ
diff --git a/Fido2/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/Fido2/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
deleted file mode 100644
index 14ed0af..0000000
Binary files a/Fido2/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ
diff --git a/Fido2/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/Fido2/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
deleted file mode 100644
index b0907ca..0000000
Binary files a/Fido2/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ
diff --git a/Fido2/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/Fido2/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
deleted file mode 100644
index d8ae031..0000000
Binary files a/Fido2/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ
diff --git a/Fido2/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/Fido2/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
deleted file mode 100644
index 2c18de9..0000000
Binary files a/Fido2/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ
diff --git a/Fido2/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/Fido2/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
deleted file mode 100644
index beed3cd..0000000
Binary files a/Fido2/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ
diff --git a/Fido2/app/src/main/res/values/colors.xml b/Fido2/app/src/main/res/values/colors.xml
deleted file mode 100644
index 39af33f..0000000
--- a/Fido2/app/src/main/res/values/colors.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
- #3F51B5
- #303F9F
- #6D4C41
-
diff --git a/Fido2/app/src/main/res/values/dimens.xml b/Fido2/app/src/main/res/values/dimens.xml
deleted file mode 100644
index 5e3b9e4..0000000
--- a/Fido2/app/src/main/res/values/dimens.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
- 8dp
- 16dp
- 24dp
- 32dp
- 64dp
-
diff --git a/Fido2/app/src/main/res/values/strings.xml b/Fido2/app/src/main/res/values/strings.xml
deleted file mode 100644
index 5a6aae7..0000000
--- a/Fido2/app/src/main/res/values/strings.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-
-
-
- FIDO2
-
-
-
- Sign In
- Username
- For the purpose of demonstration, this app accepts any username.
- Next
-
-
-
- Welcome, %s!
- For the purpose of demonstration, the password you type is ignored.
- Password
- Cancelled
- Error trying to authenticate
-
-
-
- Your registered credentials:
- "You don't have any credentials.\nTap '+' to add one."
- Reauth
- Sign Out
- Delete
- Are you sure you want to delete this credential?\n\n%s
- Error creating credential
- Add credential
-
-
diff --git a/Fido2/app/src/main/res/values/styles.xml b/Fido2/app/src/main/res/values/styles.xml
deleted file mode 100644
index 084cd10..0000000
--- a/Fido2/app/src/main/res/values/styles.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
-
-
diff --git a/Fido2/build.gradle b/Fido2/build.gradle
deleted file mode 100644
index 909ecfc..0000000
--- a/Fido2/build.gradle
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2021 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-buildscript {
- ext.kotlin_version = '1.5.21'
- repositories {
- google()
- mavenCentral()
- }
- dependencies {
- classpath 'com.android.tools.build:gradle:7.0.0'
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
- classpath 'com.google.dagger:hilt-android-gradle-plugin:2.38.1'
- }
-}
-
-allprojects {
- repositories {
- google()
- mavenCentral()
- }
-}
-
-task clean(type: Delete) {
- delete rootProject.buildDir
-}
diff --git a/Fido2/debug.jks b/Fido2/debug.jks
deleted file mode 100644
index 1e31764..0000000
Binary files a/Fido2/debug.jks and /dev/null differ
diff --git a/Fido2/gradle.properties b/Fido2/gradle.properties
deleted file mode 100644
index d79feb7..0000000
--- a/Fido2/gradle.properties
+++ /dev/null
@@ -1,40 +0,0 @@
-#
-# Copyright 2021 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-# Project-wide Gradle settings.
-# IDE (e.g. Android Studio) users:
-# Gradle settings configured through the IDE *will override*
-# any settings specified in this file.
-# For more details on how to configure your build environment visit
-# http://www.gradle.org/docs/current/userguide/build_environment.html
-# Specifies the JVM arguments used for the daemon process.
-# The setting is particularly useful for tweaking memory settings.
-org.gradle.jvmargs=-Xmx1536m
-# When configured, Gradle will run in incubating parallel mode.
-# This option should only be used with decoupled projects. More details, visit
-# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
-# org.gradle.parallel=true
-# AndroidX package structure to make it clearer which packages are bundled with the
-# Android operating system, and which are packaged with your app's APK
-# https://developer.android.com/topic/libraries/support-library/androidx-rn
-android.useAndroidX=true
-# Automatically convert third-party libraries to use AndroidX
-android.enableJetifier=true
-# Kotlin code style for this project: "official" or "obsolete":
-kotlin.code.style=official
-
-# The URL of the server
-host=https://webauthn-codelab.glitch.me
diff --git a/Fido2/gradle/wrapper/gradle-wrapper.jar b/Fido2/gradle/wrapper/gradle-wrapper.jar
deleted file mode 100644
index f6b961f..0000000
Binary files a/Fido2/gradle/wrapper/gradle-wrapper.jar and /dev/null differ
diff --git a/Fido2/gradle/wrapper/gradle-wrapper.properties b/Fido2/gradle/wrapper/gradle-wrapper.properties
deleted file mode 100644
index 88441a2..0000000
--- a/Fido2/gradle/wrapper/gradle-wrapper.properties
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# Copyright 2021 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-#Tue Nov 17 16:25:58 JST 2020
-distributionBase=GRADLE_USER_HOME
-distributionPath=wrapper/dists
-zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
diff --git a/Fido2/gradlew b/Fido2/gradlew
deleted file mode 100755
index 8b31a7a..0000000
--- a/Fido2/gradlew
+++ /dev/null
@@ -1,188 +0,0 @@
-#!/usr/bin/env sh
-
-#
-# Copyright 2021 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-##############################################################################
-##
-## Gradle start up script for UN*X
-##
-##############################################################################
-
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
- ls=`ls -ld "$PRG"`
- link=`expr "$ls" : '.*-> \(.*\)$'`
- if expr "$link" : '/.*' > /dev/null; then
- PRG="$link"
- else
- PRG=`dirname "$PRG"`"/$link"
- fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS=""
-
-# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
-
-warn () {
- echo "$*"
-}
-
-die () {
- echo
- echo "$*"
- echo
- exit 1
-}
-
-# OS specific support (must be 'true' or 'false').
-cygwin=false
-msys=false
-darwin=false
-nonstop=false
-case "`uname`" in
- CYGWIN* )
- cygwin=true
- ;;
- Darwin* )
- darwin=true
- ;;
- MINGW* )
- msys=true
- ;;
- NONSTOP* )
- nonstop=true
- ;;
-esac
-
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
-
-# Determine the Java command to use to start the JVM.
-if [ -n "$JAVA_HOME" ] ; then
- if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
- # IBM's JDK on AIX uses strange locations for the executables
- JAVACMD="$JAVA_HOME/jre/sh/java"
- else
- JAVACMD="$JAVA_HOME/bin/java"
- fi
- if [ ! -x "$JAVACMD" ] ; then
- die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
- fi
-else
- JAVACMD="java"
- which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-fi
-
-# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
- MAX_FD_LIMIT=`ulimit -H -n`
- if [ $? -eq 0 ] ; then
- if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
- MAX_FD="$MAX_FD_LIMIT"
- fi
- ulimit -n $MAX_FD
- if [ $? -ne 0 ] ; then
- warn "Could not set maximum file descriptor limit: $MAX_FD"
- fi
- else
- warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
- fi
-fi
-
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
- GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
-
-# For Cygwin, switch paths to Windows format before running java
-if $cygwin ; then
- APP_HOME=`cygpath --path --mixed "$APP_HOME"`
- CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
- JAVACMD=`cygpath --unix "$JAVACMD"`
-
- # We build the pattern for arguments to be converted via cygpath
- ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
- SEP=""
- for dir in $ROOTDIRSRAW ; do
- ROOTDIRS="$ROOTDIRS$SEP$dir"
- SEP="|"
- done
- OURCYGPATTERN="(^($ROOTDIRS))"
- # Add a user-defined pattern to the cygpath arguments
- if [ "$GRADLE_CYGPATTERN" != "" ] ; then
- OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
- fi
- # Now convert the arguments - kludge to limit ourselves to /bin/sh
- i=0
- for arg in "$@" ; do
- CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
- CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
-
- if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
- eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
- else
- eval `echo args$i`="\"$arg\""
- fi
- i=$((i+1))
- done
- case $i in
- (0) set -- ;;
- (1) set -- "$args0" ;;
- (2) set -- "$args0" "$args1" ;;
- (3) set -- "$args0" "$args1" "$args2" ;;
- (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
- (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
- (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
- (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
- (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
- (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
- esac
-fi
-
-# Escape application args
-save () {
- for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
- echo " "
-}
-APP_ARGS=$(save "$@")
-
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
-
-# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
-if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
- cd "$(dirname "$0")"
-fi
-
-exec "$JAVACMD" "$@"
diff --git a/Fido2/gradlew.bat b/Fido2/gradlew.bat
deleted file mode 100644
index e95643d..0000000
--- a/Fido2/gradlew.bat
+++ /dev/null
@@ -1,84 +0,0 @@
-@if "%DEBUG%" == "" @echo off
-@rem ##########################################################################
-@rem
-@rem Gradle startup script for Windows
-@rem
-@rem ##########################################################################
-
-@rem Set local scope for the variables with windows NT shell
-if "%OS%"=="Windows_NT" setlocal
-
-set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
-set APP_BASE_NAME=%~n0
-set APP_HOME=%DIRNAME%
-
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS=
-
-@rem Find java.exe
-if defined JAVA_HOME goto findJavaFromJavaHome
-
-set JAVA_EXE=java.exe
-%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto init
-
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:findJavaFromJavaHome
-set JAVA_HOME=%JAVA_HOME:"=%
-set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-
-if exist "%JAVA_EXE%" goto init
-
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:init
-@rem Get command-line arguments, handling Windows variants
-
-if not "%OS%" == "Windows_NT" goto win9xME_args
-
-:win9xME_args
-@rem Slurp the command line arguments.
-set CMD_LINE_ARGS=
-set _SKIP=2
-
-:win9xME_args_slurp
-if "x%~1" == "x" goto execute
-
-set CMD_LINE_ARGS=%*
-
-:execute
-@rem Setup the command line
-
-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
-
-@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
-
-:end
-@rem End local scope for the variables with windows NT shell
-if "%ERRORLEVEL%"=="0" goto mainEnd
-
-:fail
-rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
-rem the _cmd.exe /c_ return code!
-if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
-exit /b 1
-
-:mainEnd
-if "%OS%"=="Windows_NT" endlocal
-
-:omega
diff --git a/Fido2/settings.gradle b/Fido2/settings.gradle
deleted file mode 100644
index 33e604e..0000000
--- a/Fido2/settings.gradle
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright 2021 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-include ':app'