@algorandfoundation/react-native-passkey-autofill 1.0.0-canary.1 → 1.0.0-canary.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -16,6 +16,29 @@ npm install react-native-passkey-autofill
16
16
 
17
17
  To use this module on Android, you need to configure the AutoFill service in your `AndroidManifest.xml` or via the Expo plugin.
18
18
 
19
+ #### Expo Plugin Configuration
20
+
21
+ If you are using Expo, you can configure the plugin in your `app.json` or `app.config.js`:
22
+
23
+ ```json
24
+ {
25
+ "expo": {
26
+ "plugins": [
27
+ [
28
+ "react-native-passkey-autofill",
29
+ {
30
+ "site": "https://your-fido-server.com",
31
+ "label": "My Custom Credential Provider"
32
+ }
33
+ ]
34
+ ]
35
+ }
36
+ }
37
+ ```
38
+
39
+ - `site`: The URL of your FIDO server (default: `https://fido.shore-tech.net`).
40
+ - `label`: The name of the credential provider as it appears in Android settings (default: `My Credential Provider`).
41
+
19
42
  ## Usage
20
43
 
21
44
  ```typescript
@@ -5,7 +5,7 @@
5
5
  android:name=".service.PasskeyAutofillCredentialProviderService"
6
6
  android:enabled="true"
7
7
  android:exported="true"
8
- android:label="My Credential Provider"
8
+ android:label="@string/passkey_autofill_label"
9
9
  android:icon="@mipmap/ic_launcher"
10
10
  android:permission="android.permission.BIND_CREDENTIAL_PROVIDER_SERVICE"
11
11
  tools:targetApi="upside_down_cake">
@@ -21,6 +21,7 @@ import androidx.credentials.webauthn.PublicKeyCredentialRequestOptions
21
21
  import co.algorand.passkeyautofill.credentials.CredentialRepository
22
22
  import co.algorand.passkeyautofill.credentials.Credential
23
23
  import java.security.KeyPair
24
+ import java.security.MessageDigest
24
25
  import android.util.Base64 as AndroidBase64
25
26
  import org.json.JSONObject
26
27
 
@@ -39,10 +40,10 @@ class GetPasskeyActivity : AppCompatActivity() {
39
40
 
40
41
  override fun onCreate(savedInstanceState: Bundle?) {
41
42
  super.onCreate(savedInstanceState)
42
-
43
+
43
44
  request = PendingIntentHandler.retrieveProviderGetCredentialRequest(intent)
44
45
  val credentialData = intent.getBundleExtra("CREDENTIAL_DATA")
45
-
46
+
46
47
  if (request != null && credentialData != null) {
47
48
  origin = credentialRepository.getOrigin(request!!.callingAppInfo)
48
49
  credentialIdEnc = credentialData.getString("credentialId")
@@ -54,7 +55,7 @@ class GetPasskeyActivity : AppCompatActivity() {
54
55
  orientation = android.widget.LinearLayout.VERTICAL
55
56
  setPadding(50, 50, 50, 50)
56
57
  }
57
-
58
+
58
59
  val title = TextView(this).apply {
59
60
  text = "Use Passkey"
60
61
  textSize = 24f
@@ -67,7 +68,7 @@ class GetPasskeyActivity : AppCompatActivity() {
67
68
  setPadding(0, 0, 0, 50)
68
69
  }
69
70
  layout.addView(info)
70
-
71
+
71
72
  val confirmButton = Button(this).apply {
72
73
  text = "Sign In"
73
74
  setOnClickListener {
@@ -85,11 +86,18 @@ class GetPasskeyActivity : AppCompatActivity() {
85
86
  val req = request ?: throw IllegalStateException("No request found")
86
87
  val option = req.credentialOptions[0] as GetPublicKeyCredentialOption
87
88
  val requestOptions = PublicKeyCredentialRequestOptions(option.requestJson)
88
-
89
+
89
90
  val credId = AndroidBase64.decode(credentialIdEnc!!, AndroidBase64.DEFAULT)
91
+
92
+ val requestJson = JSONObject(option.requestJson)
93
+ val challenge = requestJson.getString("challenge")
94
+ val sanitizedOrigin = origin.replace(Regex("/$"), "")
95
+
90
96
  val clientDataHash = option.requestData.getByteArray("androidx.credentials.BUNDLE_KEY_CLIENT_DATA_HASH")
91
- ?: throw IllegalStateException("Missing clientDataHash")
92
-
97
+ ?: MessageDigest.getInstance("SHA-256").digest(
98
+ "{\"type\":\"webauthn.get\",\"challenge\":\"$challenge\",\"origin\":\"$sanitizedOrigin\",\"crossOrigin\":false}".toByteArray(Charsets.UTF_8)
99
+ )
100
+
93
101
  val dbCred = credentialRepository.getCredential(this, credId)
94
102
  ?: throw IllegalStateException("Credential not found")
95
103
 
@@ -118,10 +126,8 @@ class GetPasskeyActivity : AppCompatActivity() {
118
126
  )
119
127
 
120
128
  // Manual addition of clientDataJSON if needed by some RPs, following reference
121
- val requestJson = JSONObject(option.requestJson)
122
- val challenge = requestJson.getString("challenge")
123
129
  val clientDataJSONb64 = getClientDataJSONb64(origin, challenge)
124
-
130
+
125
131
  val delimiter = "response\":{"
126
132
  val credentialJson = fidoCredential.json().substringBeforeLast(delimiter) + delimiter +
127
133
  "\"clientDataJSON\":\"$clientDataJSONb64\"," +
@@ -129,12 +135,12 @@ class GetPasskeyActivity : AppCompatActivity() {
129
135
 
130
136
  val resultIntent = Intent()
131
137
  val passkeyCredential = PublicKeyCredential(credentialJson)
132
-
138
+
133
139
  PendingIntentHandler.setGetCredentialResponse(
134
140
  resultIntent,
135
141
  GetCredentialResponse(passkeyCredential)
136
142
  )
137
-
143
+
138
144
  setResult(Activity.RESULT_OK, resultIntent)
139
145
  } catch (e: Exception) {
140
146
  Log.e(TAG, "Error during passkey assertion", e)
@@ -0,0 +1,3 @@
1
+ <resources>
2
+ <string name="passkey_autofill_label">My Credential Provider</string>
3
+ </resources>
package/app.plugin.js CHANGED
@@ -166,6 +166,7 @@ const withUserAgent = (config) => {
166
166
 
167
167
  const withPasskeyAutofill = (config, props = {}) => {
168
168
  const site = props.site || "https://fido.shore-tech.net";
169
+ const label = props.label || "My Credential Provider";
169
170
 
170
171
  config = withAndroidCookieModule(config);
171
172
  config = withUserAgent(config);
@@ -215,6 +216,10 @@ const withPasskeyAutofill = (config, props = {}) => {
215
216
  },
216
217
  ]),
217
218
  },
219
+ {
220
+ $: { name: "passkey_autofill_label", translatable: "true" },
221
+ _: label,
222
+ },
218
223
  ],
219
224
  config.modResults
220
225
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@algorandfoundation/react-native-passkey-autofill",
3
- "version": "1.0.0-canary.1",
3
+ "version": "1.0.0-canary.3",
4
4
  "description": "Passkey AutoFill React Native",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",