Merge "Define converter methods to parse the app requests."

This commit is contained in:
Helen Qin
2022-10-31 16:43:33 +00:00
committed by Android (Google) Code Review
22 changed files with 930 additions and 9 deletions

View File

@@ -36,7 +36,8 @@ public final class Credential implements Parcelable {
*
* @hide
*/
@NonNull public static final String TYPE_PASSWORD = "android.credentials.TYPE_PASSWORD";
@NonNull public static final String TYPE_PASSWORD_CREDENTIAL =
"android.credentials.TYPE_PASSWORD_CREDENTIAL";
/**
* The credential type.

View File

@@ -36,7 +36,7 @@ import com.android.credentialmanager.createflow.CreateScreenState
import com.android.credentialmanager.createflow.RequestDisplayInfo
import com.android.credentialmanager.getflow.GetCredentialUiState
import com.android.credentialmanager.getflow.GetScreenState
import com.android.credentialmanager.jetpack.CredentialEntryUi.Companion.TYPE_PUBLIC_KEY_CREDENTIAL
import com.android.credentialmanager.jetpack.provider.CredentialEntryUi.Companion.TYPE_PUBLIC_KEY_CREDENTIAL
// Consider repo per screen, similar to view model?
class CredentialManagerRepo(

View File

@@ -39,8 +39,8 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.core.graphics.drawable.toBitmap
import com.android.credentialmanager.R
import com.android.credentialmanager.jetpack.CredentialEntryUi.Companion.TYPE_PASSWORD_CREDENTIAL
import com.android.credentialmanager.jetpack.CredentialEntryUi.Companion.TYPE_PUBLIC_KEY_CREDENTIAL
import com.android.credentialmanager.jetpack.provider.CredentialEntryUi.Companion.TYPE_PASSWORD_CREDENTIAL
import com.android.credentialmanager.jetpack.provider.CredentialEntryUi.Companion.TYPE_PUBLIC_KEY_CREDENTIAL
import com.android.credentialmanager.ui.theme.Grey100
import com.android.credentialmanager.ui.theme.Shapes
import com.android.credentialmanager.ui.theme.Typography

View File

@@ -0,0 +1,52 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* 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.android.credentialmanager.jetpack.developer
import android.credentials.Credential
import android.os.Bundle
/**
* Base request class for registering a credential.
*
* @property type the credential type
* @property data the request data in the [Bundle] format
* @property requireSystemProvider true if must only be fulfilled by a system provider and false
* otherwise
*/
open class CreateCredentialRequest(
val type: String,
val data: Bundle,
val requireSystemProvider: Boolean,
) {
companion object {
@JvmStatic
fun createFrom(from: android.credentials.CreateCredentialRequest): CreateCredentialRequest {
return try {
when (from.type) {
Credential.TYPE_PASSWORD_CREDENTIAL ->
CreatePasswordRequest.createFrom(from.data)
PublicKeyCredential.TYPE_PUBLIC_KEY_CREDENTIAL ->
CreatePublicKeyCredentialBaseRequest.createFrom(from.data)
else ->
CreateCredentialRequest(from.type, from.data, from.requireSystemProvider())
}
} catch (e: FrameworkClassParsingException) {
CreateCredentialRequest(from.type, from.data, from.requireSystemProvider())
}
}
}
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* 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.android.credentialmanager.jetpack.developer
import android.credentials.Credential
import android.os.Bundle
/**
* A request to save the user password credential with their password provider.
*
* @property id the user id associated with the password
* @property password the password
* @throws NullPointerException If [id] is null
* @throws NullPointerException If [password] is null
* @throws IllegalArgumentException If [password] is empty
*/
class CreatePasswordRequest constructor(
val id: String,
val password: String,
) : CreateCredentialRequest(
Credential.TYPE_PASSWORD_CREDENTIAL,
toBundle(id, password),
false,
) {
init {
require(password.isNotEmpty()) { "password should not be empty" }
}
companion object {
const val BUNDLE_KEY_ID = "androidx.credentials.BUNDLE_KEY_ID"
const val BUNDLE_KEY_PASSWORD = "androidx.credentials.BUNDLE_KEY_PASSWORD"
@JvmStatic
internal fun toBundle(id: String, password: String): Bundle {
val bundle = Bundle()
bundle.putString(BUNDLE_KEY_ID, id)
bundle.putString(BUNDLE_KEY_PASSWORD, password)
return bundle
}
@JvmStatic
fun createFrom(data: Bundle): CreatePasswordRequest {
try {
val id = data.getString(BUNDLE_KEY_ID)
val password = data.getString(BUNDLE_KEY_PASSWORD)
return CreatePasswordRequest(id!!, password!!)
} catch (e: Exception) {
throw FrameworkClassParsingException()
}
}
}
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* 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.android.credentialmanager.jetpack.developer
import android.os.Bundle
/**
* Base request class for registering a public key credential.
*
* @property requestJson The request in JSON format
* @throws NullPointerException If [requestJson] is null. This is handled by the Kotlin runtime
* @throws IllegalArgumentException If [requestJson] is empty
*
* @hide
*/
abstract class CreatePublicKeyCredentialBaseRequest constructor(
val requestJson: String,
type: String,
data: Bundle,
requireSystemProvider: Boolean,
) : CreateCredentialRequest(type, data, requireSystemProvider) {
init {
require(requestJson.isNotEmpty()) { "request json must not be empty" }
}
companion object {
const val BUNDLE_KEY_REQUEST_JSON = "androidx.credentials.BUNDLE_KEY_REQUEST_JSON"
const val BUNDLE_KEY_SUBTYPE = "androidx.credentials.BUNDLE_KEY_SUBTYPE"
@JvmStatic
fun createFrom(data: Bundle): CreatePublicKeyCredentialBaseRequest {
return when (data.getString(BUNDLE_KEY_SUBTYPE)) {
CreatePublicKeyCredentialRequest
.BUNDLE_VALUE_SUBTYPE_CREATE_PUBLIC_KEY_CREDENTIAL_REQUEST ->
CreatePublicKeyCredentialRequestPrivileged.createFrom(data)
CreatePublicKeyCredentialRequestPrivileged
.BUNDLE_VALUE_SUBTYPE_CREATE_PUBLIC_KEY_CREDENTIAL_REQUEST_PRIVILEGED ->
CreatePublicKeyCredentialRequestPrivileged.createFrom(data)
else -> throw FrameworkClassParsingException()
}
}
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* 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.android.credentialmanager.jetpack.developer
import android.os.Bundle
/**
* A request to register a passkey from the user's public key credential provider.
*
* @property requestJson the request in JSON format
* @property allowHybrid defines whether hybrid credentials are allowed to fulfill this request,
* true by default
* @throws NullPointerException If [requestJson] or [allowHybrid] is null. This is handled by the
* Kotlin runtime
* @throws IllegalArgumentException If [requestJson] is empty
*
* @hide
*/
class CreatePublicKeyCredentialRequest @JvmOverloads constructor(
requestJson: String,
@get:JvmName("allowHybrid")
val allowHybrid: Boolean = true
) : CreatePublicKeyCredentialBaseRequest(
requestJson,
PublicKeyCredential.TYPE_PUBLIC_KEY_CREDENTIAL,
toBundle(requestJson, allowHybrid),
false,
) {
companion object {
const val BUNDLE_KEY_ALLOW_HYBRID = "androidx.credentials.BUNDLE_KEY_ALLOW_HYBRID"
const val BUNDLE_VALUE_SUBTYPE_CREATE_PUBLIC_KEY_CREDENTIAL_REQUEST =
"androidx.credentials.BUNDLE_VALUE_SUBTYPE_CREATE_PUBLIC_KEY_CREDENTIAL_REQUEST"
@JvmStatic
internal fun toBundle(requestJson: String, allowHybrid: Boolean): Bundle {
val bundle = Bundle()
bundle.putString(BUNDLE_KEY_SUBTYPE,
BUNDLE_VALUE_SUBTYPE_CREATE_PUBLIC_KEY_CREDENTIAL_REQUEST)
bundle.putString(BUNDLE_KEY_REQUEST_JSON, requestJson)
bundle.putBoolean(BUNDLE_KEY_ALLOW_HYBRID, allowHybrid)
return bundle
}
@JvmStatic
fun createFrom(data: Bundle): CreatePublicKeyCredentialRequest {
try {
val requestJson = data.getString(BUNDLE_KEY_REQUEST_JSON)
val allowHybrid = data.get(BUNDLE_KEY_ALLOW_HYBRID)
return CreatePublicKeyCredentialRequest(requestJson!!, (allowHybrid!!) as Boolean)
} catch (e: Exception) {
throw FrameworkClassParsingException()
}
}
}
}

View File

@@ -0,0 +1,143 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* 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.android.credentialmanager.jetpack.developer
import android.os.Bundle
/**
* A privileged request to register a passkey from the user’s public key credential provider, where
* the caller can modify the rp. Only callers with privileged permission, e.g. user’s default
* brower, caBLE, can use this.
*
* @property requestJson the privileged request in JSON format
* @property allowHybrid defines whether hybrid credentials are allowed to fulfill this request,
* true by default
* @property rp the expected true RP ID which will override the one in the [requestJson]
* @property clientDataHash a hash that is used to verify the [rp] Identity
* @throws NullPointerException If any of [allowHybrid], [requestJson], [rp], or [clientDataHash] is
* null. This is handled by the Kotlin runtime
* @throws IllegalArgumentException If any of [requestJson], [rp], or [clientDataHash] is empty
*
* @hide
*/
class CreatePublicKeyCredentialRequestPrivileged @JvmOverloads constructor(
requestJson: String,
val rp: String,
val clientDataHash: String,
@get:JvmName("allowHybrid")
val allowHybrid: Boolean = true
) : CreatePublicKeyCredentialBaseRequest(
requestJson,
PublicKeyCredential.TYPE_PUBLIC_KEY_CREDENTIAL,
toBundle(requestJson, rp, clientDataHash, allowHybrid),
false,
) {
init {
require(rp.isNotEmpty()) { "rp must not be empty" }
require(clientDataHash.isNotEmpty()) { "clientDataHash must not be empty" }
}
/** A builder for [CreatePublicKeyCredentialRequestPrivileged]. */
class Builder(var requestJson: String, var rp: String, var clientDataHash: String) {
private var allowHybrid: Boolean = true
/**
* Sets the privileged request in JSON format.
*/
fun setRequestJson(requestJson: String): Builder {
this.requestJson = requestJson
return this
}
/**
* Sets whether hybrid credentials are allowed to fulfill this request, true by default.
*/
fun setAllowHybrid(allowHybrid: Boolean): Builder {
this.allowHybrid = allowHybrid
return this
}
/**
* Sets the expected true RP ID which will override the one in the [requestJson].
*/
fun setRp(rp: String): Builder {
this.rp = rp
return this
}
/**
* Sets a hash that is used to verify the [rp] Identity.
*/
fun setClientDataHash(clientDataHash: String): Builder {
this.clientDataHash = clientDataHash
return this
}
/** Builds a [CreatePublicKeyCredentialRequestPrivileged]. */
fun build(): CreatePublicKeyCredentialRequestPrivileged {
return CreatePublicKeyCredentialRequestPrivileged(this.requestJson,
this.rp, this.clientDataHash, this.allowHybrid)
}
}
companion object {
const val BUNDLE_KEY_RP = "androidx.credentials.BUNDLE_KEY_RP"
const val BUNDLE_KEY_CLIENT_DATA_HASH =
"androidx.credentials.BUNDLE_KEY_CLIENT_DATA_HASH"
const val BUNDLE_KEY_ALLOW_HYBRID = "androidx.credentials.BUNDLE_KEY_ALLOW_HYBRID"
const val BUNDLE_VALUE_SUBTYPE_CREATE_PUBLIC_KEY_CREDENTIAL_REQUEST_PRIVILEGED =
"androidx.credentials.BUNDLE_VALUE_SUBTYPE_CREATE_PUBLIC_KEY_CREDENTIAL_REQUEST_" +
"PRIVILEGED"
@JvmStatic
internal fun toBundle(
requestJson: String,
rp: String,
clientDataHash: String,
allowHybrid: Boolean
): Bundle {
val bundle = Bundle()
bundle.putString(BUNDLE_KEY_SUBTYPE,
BUNDLE_VALUE_SUBTYPE_CREATE_PUBLIC_KEY_CREDENTIAL_REQUEST_PRIVILEGED)
bundle.putString(BUNDLE_KEY_REQUEST_JSON, requestJson)
bundle.putString(BUNDLE_KEY_RP, rp)
bundle.putString(BUNDLE_KEY_CLIENT_DATA_HASH, clientDataHash)
bundle.putBoolean(BUNDLE_KEY_ALLOW_HYBRID, allowHybrid)
return bundle
}
@JvmStatic
fun createFrom(data: Bundle): CreatePublicKeyCredentialRequestPrivileged {
try {
val requestJson = data.getString(BUNDLE_KEY_REQUEST_JSON)
val rp = data.getString(BUNDLE_KEY_RP)
val clientDataHash = data.getString(BUNDLE_KEY_CLIENT_DATA_HASH)
val allowHybrid = data.get(BUNDLE_KEY_ALLOW_HYBRID)
return CreatePublicKeyCredentialRequestPrivileged(
requestJson!!,
rp!!,
clientDataHash!!,
(allowHybrid!!) as Boolean,
)
} catch (e: Exception) {
throw FrameworkClassParsingException()
}
}
}
}

View File

@@ -0,0 +1,27 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* 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.android.credentialmanager.jetpack.developer
import android.os.Bundle
/**
* Base class for a credential with which the user consented to authenticate to the app.
*
* @property type the credential type
* @property data the credential data in the [Bundle] format.
*/
open class Credential(val type: String, val data: Bundle)

View File

@@ -0,0 +1,25 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* 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.android.credentialmanager.jetpack.developer
/**
* Internal exception used to indicate a parsing error while converting from a framework type to
* a jetpack type.
*
* @hide
*/
internal class FrameworkClassParsingException : Exception()

View File

@@ -0,0 +1,52 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* 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.android.credentialmanager.jetpack.developer
import android.credentials.Credential
import android.os.Bundle
/**
* Base request class for getting a registered credential.
*
* @property type the credential type
* @property data the request data in the [Bundle] format
* @property requireSystemProvider true if must only be fulfilled by a system provider and false
* otherwise
*/
open class GetCredentialOption(
val type: String,
val data: Bundle,
val requireSystemProvider: Boolean,
) {
companion object {
@JvmStatic
fun createFrom(from: android.credentials.GetCredentialOption): GetCredentialOption {
return try {
when (from.type) {
Credential.TYPE_PASSWORD_CREDENTIAL ->
GetPasswordOption.createFrom(from.data)
PublicKeyCredential.TYPE_PUBLIC_KEY_CREDENTIAL ->
GetPublicKeyCredentialBaseOption.createFrom(from.data)
else ->
GetCredentialOption(from.type, from.data, from.requireSystemProvider())
}
} catch (e: FrameworkClassParsingException) {
GetCredentialOption(from.type, from.data, from.requireSystemProvider())
}
}
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* 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.android.credentialmanager.jetpack.developer
/**
* Encapsulates a request to get a user credential.
*
* @property getCredentialOptions the list of [GetCredentialOption] from which the user can choose
* one to authenticate to the app
* @throws IllegalArgumentException If [getCredentialOptions] is empty
*/
class GetCredentialRequest constructor(
val getCredentialOptions: List<GetCredentialOption>,
) {
init {
require(getCredentialOptions.isNotEmpty()) { "credentialRequests should not be empty" }
}
/** A builder for [GetCredentialRequest]. */
class Builder {
private var getCredentialOptions: MutableList<GetCredentialOption> = mutableListOf()
/** Adds a specific type of [GetCredentialOption]. */
fun addGetCredentialOption(getCredentialOption: GetCredentialOption): Builder {
getCredentialOptions.add(getCredentialOption)
return this
}
/** Sets the list of [GetCredentialOption]. */
fun setGetCredentialOptions(getCredentialOptions: List<GetCredentialOption>): Builder {
this.getCredentialOptions = getCredentialOptions.toMutableList()
return this
}
/**
* Builds a [GetCredentialRequest].
*
* @throws IllegalArgumentException If [getCredentialOptions] is empty
*/
fun build(): GetCredentialRequest {
return GetCredentialRequest(getCredentialOptions.toList())
}
}
companion object {
@JvmStatic
fun createFrom(from: android.credentials.GetCredentialRequest): GetCredentialRequest {
return GetCredentialRequest(
from.getCredentialOptions.map {GetCredentialOption.createFrom(it)}
)
}
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* 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.android.credentialmanager.jetpack.developer
import android.credentials.Credential
import android.os.Bundle
/** A request to retrieve the user's saved application password from their password provider. */
class GetPasswordOption : GetCredentialOption(
Credential.TYPE_PASSWORD_CREDENTIAL,
Bundle(),
false,
) {
companion object {
@JvmStatic
fun createFrom(data: Bundle): GetPasswordOption {
return GetPasswordOption()
}
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* 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.android.credentialmanager.jetpack.developer
import android.os.Bundle
/**
* Base request class for getting a registered public key credential.
*
* @property requestJson the request in JSON format
* @throws NullPointerException If [requestJson] is null - auto handled by the
* Kotlin runtime
* @throws IllegalArgumentException If [requestJson] is empty
*
* @hide
*/
abstract class GetPublicKeyCredentialBaseOption constructor(
val requestJson: String,
type: String,
data: Bundle,
requireSystemProvider: Boolean,
) : GetCredentialOption(type, data, requireSystemProvider) {
init {
require(requestJson.isNotEmpty()) { "request json must not be empty" }
}
companion object {
const val BUNDLE_KEY_REQUEST_JSON = "androidx.credentials.BUNDLE_KEY_REQUEST_JSON"
const val BUNDLE_KEY_SUBTYPE = "androidx.credentials.BUNDLE_KEY_SUBTYPE"
@JvmStatic
fun createFrom(data: Bundle): GetPublicKeyCredentialBaseOption {
return when (data.getString(BUNDLE_KEY_SUBTYPE)) {
GetPublicKeyCredentialOption
.BUNDLE_VALUE_SUBTYPE_GET_PUBLIC_KEY_CREDENTIAL_OPTION ->
GetPublicKeyCredentialOption.createFrom(data)
GetPublicKeyCredentialOptionPrivileged
.BUNDLE_VALUE_SUBTYPE_GET_PUBLIC_KEY_CREDENTIAL_OPTION_PRIVILEGED ->
GetPublicKeyCredentialOptionPrivileged.createFrom(data)
else -> throw FrameworkClassParsingException()
}
}
}
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* 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.android.credentialmanager.jetpack.developer
import android.os.Bundle
/**
* A request to get passkeys from the user's public key credential provider.
*
* @property requestJson the request in JSON format
* @property allowHybrid defines whether hybrid credentials are allowed to fulfill this request,
* true by default
* @throws NullPointerException If [requestJson] or [allowHybrid] is null. It is handled by the
* Kotlin runtime
* @throws IllegalArgumentException If [requestJson] is empty
*
* @hide
*/
class GetPublicKeyCredentialOption @JvmOverloads constructor(
requestJson: String,
@get:JvmName("allowHybrid")
val allowHybrid: Boolean = true,
) : GetPublicKeyCredentialBaseOption(
requestJson,
PublicKeyCredential.TYPE_PUBLIC_KEY_CREDENTIAL,
toBundle(requestJson, allowHybrid),
false
) {
companion object {
const val BUNDLE_KEY_ALLOW_HYBRID = "androidx.credentials.BUNDLE_KEY_ALLOW_HYBRID"
const val BUNDLE_VALUE_SUBTYPE_GET_PUBLIC_KEY_CREDENTIAL_OPTION =
"androidx.credentials.BUNDLE_VALUE_SUBTYPE_GET_PUBLIC_KEY_CREDENTIAL_OPTION"
@JvmStatic
internal fun toBundle(requestJson: String, allowHybrid: Boolean): Bundle {
val bundle = Bundle()
bundle.putString(BUNDLE_KEY_REQUEST_JSON, requestJson)
bundle.putBoolean(BUNDLE_KEY_ALLOW_HYBRID, allowHybrid)
return bundle
}
@JvmStatic
fun createFrom(data: Bundle): GetPublicKeyCredentialOption {
try {
val requestJson = data.getString(BUNDLE_KEY_REQUEST_JSON)
val allowHybrid = data.get(BUNDLE_KEY_ALLOW_HYBRID)
return GetPublicKeyCredentialOption(requestJson!!, (allowHybrid!!) as Boolean)
} catch (e: Exception) {
throw FrameworkClassParsingException()
}
}
}
}

View File

@@ -0,0 +1,141 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* 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.android.credentialmanager.jetpack.developer
import android.os.Bundle
/**
* A privileged request to get passkeys from the user's public key credential provider. The caller
* can modify the RP. Only callers with privileged permission (e.g. user's public browser or caBLE)
* can use this.
*
* @property requestJson the privileged request in JSON format
* @property allowHybrid defines whether hybrid credentials are allowed to fulfill this request,
* true by default
* @property rp the expected true RP ID which will override the one in the [requestJson]
* @property clientDataHash a hash that is used to verify the [rp] Identity
* @throws NullPointerException If any of [allowHybrid], [requestJson], [rp], or [clientDataHash]
* is null. This is handled by the Kotlin runtime
* @throws IllegalArgumentException If any of [requestJson], [rp], or [clientDataHash] is empty
*
* @hide
*/
class GetPublicKeyCredentialOptionPrivileged @JvmOverloads constructor(
requestJson: String,
val rp: String,
val clientDataHash: String,
@get:JvmName("allowHybrid")
val allowHybrid: Boolean = true
) : GetPublicKeyCredentialBaseOption(
requestJson,
PublicKeyCredential.TYPE_PUBLIC_KEY_CREDENTIAL,
toBundle(requestJson, rp, clientDataHash, allowHybrid),
false,
) {
init {
require(rp.isNotEmpty()) { "rp must not be empty" }
require(clientDataHash.isNotEmpty()) { "clientDataHash must not be empty" }
}
/** A builder for [GetPublicKeyCredentialOptionPrivileged]. */
class Builder(var requestJson: String, var rp: String, var clientDataHash: String) {
private var allowHybrid: Boolean = true
/**
* Sets the privileged request in JSON format.
*/
fun setRequestJson(requestJson: String): Builder {
this.requestJson = requestJson
return this
}
/**
* Sets whether hybrid credentials are allowed to fulfill this request, true by default.
*/
fun setAllowHybrid(allowHybrid: Boolean): Builder {
this.allowHybrid = allowHybrid
return this
}
/**
* Sets the expected true RP ID which will override the one in the [requestJson].
*/
fun setRp(rp: String): Builder {
this.rp = rp
return this
}
/**
* Sets a hash that is used to verify the [rp] Identity.
*/
fun setClientDataHash(clientDataHash: String): Builder {
this.clientDataHash = clientDataHash
return this
}
/** Builds a [GetPublicKeyCredentialOptionPrivileged]. */
fun build(): GetPublicKeyCredentialOptionPrivileged {
return GetPublicKeyCredentialOptionPrivileged(this.requestJson,
this.rp, this.clientDataHash, this.allowHybrid)
}
}
companion object {
const val BUNDLE_KEY_RP = "androidx.credentials.BUNDLE_KEY_RP"
const val BUNDLE_KEY_CLIENT_DATA_HASH =
"androidx.credentials.BUNDLE_KEY_CLIENT_DATA_HASH"
const val BUNDLE_KEY_ALLOW_HYBRID = "androidx.credentials.BUNDLE_KEY_ALLOW_HYBRID"
const val BUNDLE_VALUE_SUBTYPE_GET_PUBLIC_KEY_CREDENTIAL_OPTION_PRIVILEGED =
"androidx.credentials.BUNDLE_VALUE_SUBTYPE_GET_PUBLIC_KEY_CREDENTIAL_OPTION" +
"_PRIVILEGED"
@JvmStatic
internal fun toBundle(
requestJson: String,
rp: String,
clientDataHash: String,
allowHybrid: Boolean
): Bundle {
val bundle = Bundle()
bundle.putString(BUNDLE_KEY_REQUEST_JSON, requestJson)
bundle.putString(BUNDLE_KEY_RP, rp)
bundle.putString(BUNDLE_KEY_CLIENT_DATA_HASH, clientDataHash)
bundle.putBoolean(BUNDLE_KEY_ALLOW_HYBRID, allowHybrid)
return bundle
}
@JvmStatic
fun createFrom(data: Bundle): GetPublicKeyCredentialOptionPrivileged {
try {
val requestJson = data.getString(BUNDLE_KEY_REQUEST_JSON)
val rp = data.getString(BUNDLE_KEY_RP)
val clientDataHash = data.getString(BUNDLE_KEY_CLIENT_DATA_HASH)
val allowHybrid = data.get(BUNDLE_KEY_ALLOW_HYBRID)
return GetPublicKeyCredentialOptionPrivileged(
requestJson!!,
rp!!,
clientDataHash!!,
(allowHybrid!!) as Boolean,
)
} catch (e: Exception) {
throw FrameworkClassParsingException()
}
}
}
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* 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.android.credentialmanager.jetpack.developer
import android.os.Bundle
/**
* Represents the user's passkey credential granted by the user for app sign-in.
*
* @property authenticationResponseJson the public key credential authentication response in
* JSON format that follows the standard webauthn json format shown at
* [this w3c link](https://w3c.github.io/webauthn/#dictdef-authenticationresponsejson)
* @throws NullPointerException If [authenticationResponseJson] is null. This is handled by the
* kotlin runtime
* @throws IllegalArgumentException If [authenticationResponseJson] is empty
*
* @hide
*/
class PublicKeyCredential constructor(
val authenticationResponseJson: String
) : Credential(
TYPE_PUBLIC_KEY_CREDENTIAL,
toBundle(authenticationResponseJson)
) {
init {
require(authenticationResponseJson.isNotEmpty()) {
"authentication response JSON must not be empty" }
}
companion object {
/** The type value for public key credential related operations. */
const val TYPE_PUBLIC_KEY_CREDENTIAL: String =
"androidx.credentials.TYPE_PUBLIC_KEY_CREDENTIAL"
const val BUNDLE_KEY_AUTHENTICATION_RESPONSE_JSON =
"androidx.credentials.BUNDLE_KEY_AUTHENTICATION_RESPONSE_JSON"
@JvmStatic
internal fun toBundle(authenticationResponseJson: String): Bundle {
val bundle = Bundle()
bundle.putString(BUNDLE_KEY_AUTHENTICATION_RESPONSE_JSON, authenticationResponseJson)
return bundle
}
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.credentialmanager.jetpack
package com.android.credentialmanager.jetpack.provider
import android.app.slice.Slice
import android.credentials.ui.Entry

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.credentialmanager.jetpack
package com.android.credentialmanager.jetpack.provider
import android.app.slice.Slice
import android.graphics.drawable.Icon

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.credentialmanager.jetpack
package com.android.credentialmanager.jetpack.provider
import android.app.slice.Slice
import android.credentials.ui.Entry

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.credentialmanager.jetpack
package com.android.credentialmanager.jetpack.provider
import android.app.slice.Slice
import android.credentials.ui.Entry

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.credentialmanager.jetpack
package com.android.credentialmanager.jetpack.provider
import android.app.slice.Slice
import android.credentials.ui.Entry