1
+ package com.sap.cdc.bitsnbytes.cdc
2
+
3
+ import android.annotation.SuppressLint
4
+ import androidx.activity.ComponentActivity
5
+ import androidx.credentials.CreateCredentialResponse
6
+ import androidx.credentials.CreatePublicKeyCredentialRequest
7
+ import androidx.credentials.CreatePublicKeyCredentialResponse
8
+ import androidx.credentials.CredentialManager
9
+ import androidx.credentials.GetCredentialRequest
10
+ import androidx.credentials.GetCredentialResponse
11
+ import androidx.credentials.GetPublicKeyCredentialOption
12
+ import androidx.credentials.PublicKeyCredential
13
+ import com.sap.cdc.android.sdk.CDCDebuggable
14
+ import com.sap.cdc.android.sdk.auth.provider.IPasskeysAuthenticationProvider
15
+ import java.lang.ref.WeakReference
16
+
17
+ class PasskeysAuthenticationProvider (
18
+ private val weakActivity : WeakReference <ComponentActivity >? = null
19
+ ) : IPasskeysAuthenticationProvider {
20
+
21
+ companion object {
22
+
23
+ const val LOG_TAG = " PasskeysAuthenticationProvider"
24
+ }
25
+
26
+ private val credentialManager by lazy(LazyThreadSafetyMode .PUBLICATION ) {
27
+ weakActivity?.get()?.let {
28
+ CredentialManager .create(it)
29
+ }
30
+ }
31
+
32
+ @SuppressLint(" PublicKeyCredential" )
33
+ override suspend fun createPasskey (requestJson : String ): String? {
34
+ if (weakActivity?.get() == null ) {
35
+ return null
36
+ }
37
+ try {
38
+ val createPublicKeyCredentialRequest = CreatePublicKeyCredentialRequest (
39
+ // Contains the request in JSON format. Uses the standard WebAuthn
40
+ // web JSON spec.
41
+ requestJson = requestJson,
42
+ // Defines whether you prefer to use only immediately available credentials,
43
+ // not hybrid credentials, to fulfill this request. This value is false
44
+ // by default.
45
+ preferImmediatelyAvailableCredentials = false ,
46
+ )
47
+ // Use the createCredential method to create the passkey.
48
+ val result: CreateCredentialResponse ? = credentialManager?.createCredential(
49
+ request = createPublicKeyCredentialRequest,
50
+ context = weakActivity.get()!! ,
51
+ )
52
+ return if (result is CreatePublicKeyCredentialResponse ) {
53
+ result.registrationResponseJson
54
+ } else {
55
+ null
56
+ }
57
+ } catch (e: Exception ) {
58
+ CDCDebuggable .log(LOG_TAG , e.message ? : " Error creating passkey" )
59
+ return null
60
+ }
61
+ }
62
+
63
+ override suspend fun getPasskey (requestJson : String ): String? {
64
+ if (weakActivity?.get() == null ) {
65
+ return null
66
+ }
67
+ try {
68
+ // Get passkeys from the user's public key credential provider.
69
+ val getPublicKeyCredentialOption = GetPublicKeyCredentialOption (
70
+ requestJson = requestJson,
71
+ )
72
+
73
+ val getCredRequest = GetCredentialRequest (
74
+ listOf (getPublicKeyCredentialOption)
75
+ )
76
+
77
+ val result: GetCredentialResponse ? = credentialManager?.getCredential(
78
+ // Use an activity-based context to avoid undefined system UI
79
+ // launching behavior.
80
+ context = weakActivity.get()!! ,
81
+ request = getCredRequest
82
+ )
83
+
84
+ val credential = result?.credential
85
+ return if (credential is PublicKeyCredential ) {
86
+ credential.authenticationResponseJson
87
+ } else {
88
+ null
89
+ }
90
+ } catch (e: Exception ) {
91
+ CDCDebuggable .log(LOG_TAG , e.message ? : " Error getting passkey" )
92
+ return null
93
+ }
94
+ }
95
+
96
+ }
0 commit comments