{"id":11790,"library":"react-native-passkey","title":"React Native Passkey Integration","description":"react-native-passkey provides native Passkey support for React Native applications targeting iOS 15.0+ and Android API 28+. It bridges WebAuthn API calls to the native platform credential managers, enabling secure, passwordless authentication. The package is currently at version 3.3.3 and maintains an active release cadence, with several minor and patch releases in the past year addressing fixes, updates, and new features like PRF extension support and improved error handling. A key differentiator is its direct native integration, abstracting away the platform-specific complexities of FIDO2 attestation and assertion, and offering support for advanced features like `largeBlob` and `authenticatorSelection` options. It ships with TypeScript types, facilitating safer development. The library works by taking FIDO2 attestation/assertion requests (typically from a backend) and handling the native UI and cryptographic operations, returning FIDO2 results for server verification.","status":"active","version":"3.3.3","language":"javascript","source_language":"en","source_url":"https://github.com/f-23/react-native-passkey","tags":["javascript","react-native","ios","android","passkey","authentication","auth","typescript"],"install":[{"cmd":"npm install react-native-passkey","lang":"bash","label":"npm"},{"cmd":"yarn add react-native-passkey","lang":"bash","label":"yarn"},{"cmd":"pnpm add react-native-passkey","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Peer dependency for React Native applications.","package":"react","optional":false},{"reason":"Peer dependency for React Native applications.","package":"react-native","optional":false}],"imports":[{"note":"The primary entry point for all Passkey operations. Use named import.","wrong":"const Passkey = require('react-native-passkey');","symbol":"Passkey","correct":"import { Passkey } from 'react-native-passkey';"},{"note":"This is a TypeScript type for the result of `Passkey.create()`. Use `import type` for type-only imports to prevent bundling issues in some environments.","wrong":"import { PasskeyCreateResult } from 'react-native-passkey';","symbol":"PasskeyCreateResult","correct":"import type { PasskeyCreateResult } from 'react-native-passkey';"},{"note":"This is a TypeScript type for the result of `Passkey.get()`. Similar to PasskeyCreateResult, use `import type`.","symbol":"PasskeyGetResult","correct":"import type { PasskeyGetResult } from 'react-native-passkey';"}],"quickstart":{"code":"import { Passkey } from 'react-native-passkey';\nimport React, { useState, useEffect } from 'react';\nimport { View, Text, Button, Alert, ActivityIndicator, StyleSheet } from 'react-native';\n\nconst EXAMPLE_BACKEND_URL = process.env.PASSKEY_SERVER_URL ?? 'https://your-passkey-server.com';\n\nconst PasskeyDemo = () => {\n  const [isSupported, setIsSupported] = useState<boolean | null>(null);\n  const [isLoading, setIsLoading] = useState(false);\n\n  useEffect(() => {\n    setIsSupported(Passkey.isSupported());\n  }, []);\n\n  const handleCreatePasskey = async () => {\n    if (!isSupported) {\n      Alert.alert('Not Supported', 'Passkeys are not supported on this device.');\n      return;\n    }\n    setIsLoading(true);\n    try {\n      // This request would typically come from your backend\n      // For demo, we'll simulate a simple registration request\n      const registrationChallengeResponse = await fetch(`${EXAMPLE_BACKEND_URL}/register/challenge`, {\n        method: 'POST',\n        headers: { 'Content-Type': 'application/json' },\n        body: JSON.stringify({ username: 'demoUser' + Date.now() })\n      });\n      const requestJson = await registrationChallengeResponse.json();\n\n      console.log('FIDO2 attestation request:', JSON.stringify(requestJson, null, 2));\n      const result = await Passkey.create(JSON.stringify(requestJson));\n      \n      // Send the result to your server for verification\n      const verificationResponse = await fetch(`${EXAMPLE_BACKEND_URL}/register/verify`, {\n        method: 'POST',\n        headers: { 'Content-Type': 'application/json' },\n        body: JSON.stringify(result)\n      });\n      const verificationResult = await verificationResponse.json();\n\n      if (verificationResult.verified) {\n        Alert.alert('Success', 'Passkey created and verified!');\n      } else {\n        Alert.alert('Error', 'Passkey creation failed verification.');\n      }\n    } catch (error: any) {\n      console.error('Passkey creation error:', error);\n      Alert.alert('Error', `Failed to create Passkey: ${error.message}`);\n    } finally {\n      setIsLoading(false);\n    }\n  };\n\n  return (\n    <View style={styles.container}>\n      <Text style={styles.title}>Passkey Demo</Text>\n      {isSupported === null ? (\n        <ActivityIndicator size=\"large\" />\n      ) : (\n        <Text style={styles.status}>Passkey Supported: {isSupported ? 'Yes' : 'No'}</Text>\n      )}\n      <Button\n        title=\"Create New Passkey\"\n        onPress={handleCreatePasskey}\n        disabled={isLoading || !isSupported}\n      />\n      {isLoading && <ActivityIndicator size=\"small\" style={styles.spinner} />}\n    </View>\n  );\n};\n\nconst styles = StyleSheet.create({\n  container: {\n    flex: 1,\n    justifyContent: 'center',\n    alignItems: 'center',\n    padding: 20,\n  },\n  title: {\n    fontSize: 24,\n    fontWeight: 'bold',\n    marginBottom: 20,\n  },\n  status: {\n    fontSize: 18,\n    marginBottom: 20,\n  },\n  spinner: {\n    marginTop: 10\n  }\n});\n\nexport default PasskeyDemo;","lang":"typescript","description":"This quickstart demonstrates how to check for Passkey support and initiate the creation of a new Passkey. It simulates fetching a FIDO2 attestation request from a backend and then uses `Passkey.create()` to prompt the user, subsequently sending the result back for verification. Replace `EXAMPLE_BACKEND_URL` with your actual FIDO2 server endpoint."},"warnings":[{"fix":"Review the official documentation and migration guides for v3.0.0. Ensure your FIDO2 request payloads align with the new supported options for `excludeCredentials`, `includeCredentials`, and `authenticatorSelection`.","message":"Version 3.0.0 introduced significant restructuring of the iOS native code for improved maintainability. While specific breaking API changes are not explicitly listed beyond 'Support for more request options', this indicates a major internal overhaul that might affect custom native module integrations or debugging if not purely using the JS API.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Update your application logic to expect `largeBlob.blob` as a plain array. Ensure your backend verification also handles this change correctly. Review the TypeScript type definitions for `largeBlob`.","message":"The return type for `largeBlob.blob` was changed in v3.3.3 from a string-keyed dictionary to a plain array. This directly impacts how applications process the `largeBlob` extension data if they rely on specific dictionary keys.","severity":"breaking","affected_versions":">=3.3.3"},{"fix":"Upgrade to v3.3.2 or newer to receive more accurate and descriptive error messages. Implement robust `try/catch` blocks around `Passkey.create()` and `Passkey.get()` to handle specific error strings or codes that now correctly propagate.","message":"Incorrect error handling was fixed in v3.3.2, which previously returned generic errors instead of specific FIDO2 error types like 'UserCancelled' or 'RequestFailed'. This means older versions might not provide sufficient detail for user-facing error messages or retry logic.","severity":"gotcha","affected_versions":"<3.3.2"},{"fix":"Follow the detailed setup instructions in the README for both iOS (Xcode 'Associated Domains' capability and `apple-app-site-association` file on your domain) and Android (AndroidManifest and `assetlinks.json` file on your domain). Ensure the `team id`, `bundle identifier`, and `SHA256_cert_fingerprints` are correct.","message":"Both iOS and Android require specific associated domain configurations (Apple App Site Association and Digital Asset Links respectively) on your web server and within your app's native project settings. Failing to configure these correctly will prevent Passkey functionality from working.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Avoid using pre-release beta versions, or upgrade to a stable 3.x.x release (e.g., 3.0.0 or later) which includes fixes for TypeScript types and return values.","message":"Early beta versions (e.g., 3.0.0-beta2) had issues with TypeScript type definitions and return types for `Passkey.create()` and `Passkey.get()`. While fixed in later RCs and stable releases, using very old beta versions might lead to type mismatches or runtime errors.","severity":"deprecated","affected_versions":"<3.0.0-rc"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Check `Passkey.isSupported()` before attempting Passkey operations. Inform the user if their device does not meet the requirements. Consider fallback authentication methods.","cause":"The device's operating system version is below the minimum requirement (iOS 15.0+ or Android API 28+), or the device does not have hardware support for FIDO2/Passkeys.","error":"Error: Passkeys are not supported on this device."},{"fix":"Verify that your `apple-app-site-association` (iOS) or `assetlinks.json` (Android) file is correctly served at `/.well-known/` on your domain, and that its content matches your app's bundle ID/team ID (iOS) or package name/certificate SHA256 fingerprints (Android). For iOS, ensure the 'Associated Domains' capability is added in Xcode with `webcredentials:yourdomain.com`.","cause":"The associated domain configuration (Apple App Site Association for iOS or Digital Asset Links for Android) is incorrect or missing on your web server or in your application's native project settings.","error":"Error: The given origin is not associated with this application."},{"fix":"For iOS, navigate to your `ios` directory and run `pod install`. For both platforms, try clearing React Native caches: `npx react-native start --reset-cache`, and then rebuild your application: `npx react-native run-ios` or `npx react-native run-android`.","cause":"The native module for react-native-passkey is not correctly linked or initialized. This can happen if `pod install` was not run for iOS, or if there are caching issues in React Native.","error":"Invariant Violation: `new NativeEventEmitter()` was called with a non-null argument without the native module."},{"fix":"Ensure the `allowCredentials` array in your FIDO2 assertion request contains valid `id` values for Passkeys previously registered by the user. If the user hasn't registered a Passkey on that device, this is expected. Guide the user to register a Passkey first or use a fallback authentication method.","cause":"During a Passkey assertion (login) request, the device could not find a previously registered Passkey that matches the criteria provided in the FIDO2 assertion request (e.g., `allowCredentials`).","error":"Error: No matching credentials found."}],"ecosystem":"npm"}