Skip to content

Commit b9871f4

Browse files
committed
feat: passkey added and authenticated events
1 parent 5c0c405 commit b9871f4

File tree

9 files changed

+64
-4
lines changed

9 files changed

+64
-4
lines changed

README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,31 @@ await ReactNativePasskeyAutofill.configureIntentActions(
6666
await ReactNativePasskeyAutofill.clearCredentials();
6767
```
6868

69+
## Events
70+
71+
You can listen for events emitted by the native module when a passkey is successfully added or authenticated.
72+
73+
```typescript
74+
import ReactNativePasskeyAutofill from '@algorandfoundation/react-native-passkey-autofill';
75+
import { useEffect } from 'react';
76+
77+
// ... inside a component or hook
78+
useEffect(() => {
79+
const addedSubscription = ReactNativePasskeyAutofill.addListener('onPasskeyAdded', (event) => {
80+
console.log('Passkey added successfully:', event.success);
81+
});
82+
83+
const authSubscription = ReactNativePasskeyAutofill.addListener('onPasskeyAuthenticated', (event) => {
84+
console.log('Passkey authenticated successfully:', event.success);
85+
});
86+
87+
return () => {
88+
addedSubscription.remove();
89+
authSubscription.remove();
90+
};
91+
}, []);
92+
```
93+
6994
## 🧪 Testing
7095

7196
The project is set up with a comprehensive testing approach covering both JavaScript and Native (Kotlin) sides.

android/src/main/java/co/algorand/passkeyautofill/CreatePasskeyActivity.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,9 @@ class CreatePasskeyActivity : AppCompatActivity() {
301301
)
302302

303303
setResult(Activity.RESULT_OK, resultIntent)
304+
ReactNativePasskeyAutofillModule.instance?.sendEvent("onPasskeyAdded", Bundle().apply {
305+
putBoolean("success", true)
306+
})
304307
} catch (e: Exception) {
305308
Log.e(TAG, "Error during passkey creation", e)
306309
setResult(Activity.RESULT_CANCELED)

android/src/main/java/co/algorand/passkeyautofill/GetPasskeyActivity.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,9 @@ class GetPasskeyActivity : AppCompatActivity() {
309309
)
310310

311311
setResult(Activity.RESULT_OK, resultIntent)
312+
ReactNativePasskeyAutofillModule.instance?.sendEvent("onPasskeyAuthenticated", Bundle().apply {
313+
putBoolean("success", true)
314+
})
312315
} catch (e: Exception) {
313316
Log.e(TAG, "Error during passkey assertion", e)
314317
setResult(Activity.RESULT_CANCELED)

android/src/main/java/co/algorand/passkeyautofill/ReactNativePasskeyAutofillModule.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ import java.security.Security
1212
class ReactNativePasskeyAutofillModule : Module() {
1313
private val credentialRepository = CredentialRepository()
1414

15+
companion object {
16+
var instance: ReactNativePasskeyAutofillModule? = null
17+
}
18+
1519
init {
1620
Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME)
1721
Security.addProvider(BouncyCastleProvider())
@@ -26,6 +30,16 @@ class ReactNativePasskeyAutofillModule : Module() {
2630
// The module will be accessible from `requireNativeModule('ReactNativeLiquidAuth')` in JavaScript.
2731
Name("ReactNativePasskeyAutofill")
2832

33+
OnCreate {
34+
instance = this@ReactNativePasskeyAutofillModule
35+
}
36+
37+
OnDestroy {
38+
instance = null
39+
}
40+
41+
Events("onPasskeyAdded", "onPasskeyAuthenticated")
42+
2943
AsyncFunction("setMasterKey") { secret: String ->
3044
val context = (appContext.reactContext ?: appContext.hostingRuntimeContext) as? Context
3145
if (context != null) {

app.plugin.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,13 +231,13 @@ const withPasskeyAutofill = (config, props = {}) => {
231231
if (config.modResults.contents.includes("dP256Android-release")) {
232232
return config;
233233
}
234-
const libsDir = path.join(__dirname, "android/libs");
234+
const libsDir = "../../android/libs";
235235
config.modResults.contents = config.modResults.contents.replace(
236236
/allprojects\s*{[\s\n]*repositories\s*{/,
237237
`allprojects {
238238
repositories {
239239
flatDir {
240-
dirs "${libsDir}"
240+
dirs "$rootDir/${libsDir}"
241241
}`
242242
);
243243
return config;

example/App.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { useEffect, useState } from 'react';
44
import { Passkey } from 'react-native-passkey';
55
import { install } from 'react-native-quick-crypto';
66
import Hook from "before-after-hook";
7+
import { useEventListener } from 'expo';
78

89
import { ReactNativeProvider, WalletProvider } from './providers/ReactNativeProvider';
910
import { useProvider } from './hooks/useProvider';
@@ -47,6 +48,17 @@ function AppContent() {
4748
const [xhdEd25519KeyId, setXhdEd25519KeyId] = useState<string | null>(null);
4849
const [activePasskeyId, setActivePasskeyId] = useState<string | null>(null);
4950

51+
useEventListener(ReactNativePasskeyAutofill, 'onPasskeyAdded', (event) => {
52+
console.log('onPasskeyAdded', event);
53+
alert('Passkey Added: ' + (event.success ? 'Successfully added passkey!' : 'Failed to add passkey.'));
54+
bootstrap();
55+
});
56+
57+
useEventListener(ReactNativePasskeyAutofill, 'onPasskeyAuthenticated', (event) => {
58+
console.log('onPasskeyAuthenticated', event);
59+
alert('Passkey Authenticated: ' + (event.success ? 'Successfully authenticated!' : 'Authentication failed.'));
60+
});
61+
5062
useEffect(() => {
5163
const ed25519 = keys.find(k => k.type === 'hd-derived-ed25519' || k.type === 'ed25519');
5264
setXhdEd25519KeyId(ed25519 ? ed25519.id : null);

example/package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ios/ReactNativePasskeyAutofillModule.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ public class ReactNativePasskeyAutofillModule: Module {
1010
// The module will be accessible from `requireNativeModule('ReactNativePasskeyAutofill')` in JavaScript.
1111
Name("ReactNativePasskeyAutofill")
1212

13+
Events("onPasskeyAdded", "onPasskeyAuthenticated")
14+
1315
AsyncFunction("setMasterKey") { (secret: String) in
1416
// TODO: Implement for iOS
1517
}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export type ReactNativePasskeyAutofillModuleEvents = {
2-
2+
onPasskeyAdded: (event: { success: boolean }) => void;
3+
onPasskeyAuthenticated: (event: { success: boolean }) => void;
34
};

0 commit comments

Comments
 (0)