@@ -22,6 +22,8 @@ import android.os.Build
22
22
import android.os.Bundle
23
23
import android.util.Log
24
24
import androidx.annotation.RequiresApi
25
+ import androidx.credentials.CreatePasswordRequest
26
+ import androidx.credentials.CreatePublicKeyCredentialRequest
25
27
import androidx.credentials.CredentialManager
26
28
import androidx.credentials.CustomCredential
27
29
import androidx.credentials.GetCredentialRequest
@@ -30,7 +32,14 @@ import androidx.credentials.GetPasswordOption
30
32
import androidx.credentials.GetPublicKeyCredentialOption
31
33
import androidx.credentials.PasswordCredential
32
34
import androidx.credentials.PublicKeyCredential
35
+ import androidx.credentials.exceptions.CreateCredentialCancellationException
36
+ import androidx.credentials.exceptions.CreateCredentialCustomException
37
+ import androidx.credentials.exceptions.CreateCredentialException
38
+ import androidx.credentials.exceptions.CreateCredentialInterruptedException
39
+ import androidx.credentials.exceptions.CreateCredentialProviderConfigurationException
40
+ import androidx.credentials.exceptions.CreateCredentialUnknownException
33
41
import androidx.credentials.exceptions.GetCredentialException
42
+ import androidx.credentials.exceptions.publickeycredential.CreatePublicKeyCredentialDomException
34
43
import kotlinx.coroutines.coroutineScope
35
44
import kotlinx.coroutines.runBlocking
36
45
import org.json.JSONObject
@@ -43,6 +52,7 @@ class PasskeyAndPasswordFunctions (
43
52
// CredentialManager.
44
53
private val credentialManager = CredentialManager .create(context)
45
54
// [END android_identity_initialize_credman]
55
+ private val activityContext = context
46
56
47
57
// Placeholder for TAG log value.
48
58
val TAG = " "
@@ -55,8 +65,7 @@ class PasskeyAndPasswordFunctions (
55
65
*/
56
66
@RequiresApi(Build .VERSION_CODES .UPSIDE_DOWN_CAKE )
57
67
fun signInFlow (
58
- creationResult : JSONObject ,
59
- activityContext : Context ,
68
+ creationResult : JSONObject
60
69
) {
61
70
val requestJson = creationResult.toString()
62
71
// [START android_identity_get_password_passkey_options]
@@ -166,6 +175,93 @@ class PasskeyAndPasswordFunctions (
166
175
}
167
176
}
168
177
// [END android_identity_launch_sign_in_flow_2]
178
+
179
+ // [START android_identity_create_passkey]
180
+ suspend fun createPasskey (requestJson : String , preferImmediatelyAvailableCredentials : Boolean ) {
181
+ val createPublicKeyCredentialRequest = CreatePublicKeyCredentialRequest (
182
+ // Contains the request in JSON format. Uses the standard WebAuthn
183
+ // web JSON spec.
184
+ requestJson = requestJson,
185
+ // Defines whether you prefer to use only immediately available
186
+ // credentials, not hybrid credentials, to fulfill this request.
187
+ // This value is false by default.
188
+ preferImmediatelyAvailableCredentials = preferImmediatelyAvailableCredentials,
189
+ )
190
+
191
+ // Execute CreateCredentialRequest asynchronously to register credentials
192
+ // for a user account. Handle success and failure cases with the result and
193
+ // exceptions, respectively.
194
+ coroutineScope {
195
+ try {
196
+ val result = credentialManager.createCredential(
197
+ // Use an activity-based context to avoid undefined system
198
+ // UI launching behavior
199
+ context = activityContext,
200
+ request = createPublicKeyCredentialRequest,
201
+ )
202
+ // Handle passkey creation result
203
+ } catch (e : CreateCredentialException ){
204
+ handleFailure(e)
205
+ }
206
+ }
207
+ }
208
+ // [END android_identity_create_passkey]
209
+
210
+ // [START android_identity_handle_create_passkey_failure]
211
+ fun handleFailure (e : CreateCredentialException ) {
212
+ when (e) {
213
+ is CreatePublicKeyCredentialDomException -> {
214
+ // Handle the passkey DOM errors thrown according to the
215
+ // WebAuthn spec.
216
+ }
217
+ is CreateCredentialCancellationException -> {
218
+ // The user intentionally canceled the operation and chose not
219
+ // to register the credential.
220
+ }
221
+ is CreateCredentialInterruptedException -> {
222
+ // Retry-able error. Consider retrying the call.
223
+ }
224
+ is CreateCredentialProviderConfigurationException -> {
225
+ // Your app is missing the provider configuration dependency.
226
+ // Most likely, you're missing the
227
+ // "credentials-play-services-auth" module.
228
+ }
229
+ is CreateCredentialCustomException -> {
230
+ // You have encountered an error from a 3rd-party SDK. If you
231
+ // make the API call with a request object that's a subclass of
232
+ // CreateCustomCredentialRequest using a 3rd-party SDK, then you
233
+ // should check for any custom exception type constants within
234
+ // that SDK to match with e.type. Otherwise, drop or log the
235
+ // exception.
236
+ }
237
+ else -> Log .w(TAG , " Unexpected exception type ${e::class .java.name} " )
238
+ }
239
+ }
240
+ // [END android_identity_handle_create_passkey_failure]
241
+
242
+ // [START android_identity_register_password]
243
+ suspend fun registerPassword (username : String , password : String ) {
244
+ // Initialize a CreatePasswordRequest object.
245
+ val createPasswordRequest =
246
+ CreatePasswordRequest (id = username, password = password)
247
+
248
+ // Create credential and handle result.
249
+ coroutineScope {
250
+ try {
251
+ val result =
252
+ credentialManager.createCredential(
253
+ // Use an activity based context to avoid undefined
254
+ // system UI launching behavior.
255
+ activityContext,
256
+ createPasswordRequest
257
+ )
258
+ // Handle register password result
259
+ } catch (e: CreateCredentialException ) {
260
+ handleFailure(e)
261
+ }
262
+ }
263
+ }
264
+ // [END android_identity_register_password]
169
265
}
170
266
171
267
sealed class ExampleCustomCredential {
0 commit comments