Skip to content

Conversation

@lucasloisp
Copy link

@lucasloisp lucasloisp commented May 24, 2025

Summary

Adds a new configuration flag to both create and get enabling a more lenient policy (deviceOwnerAuthentication) if the strong version (deviceOwnerAuthenticationWithBiometrics) is not desired.

Closes #36

Implementation details

Defined a new configuration object (type PasskeysConfig) shared between the two calls (create/get) but extended by their own interfaces (PasskeysCreateOptions,PasskeysGetOptions) for if/when we want to add new properties specific to each. This config object is documented (via JSDoc) and the flag is specified under ios to make it clear it is platform-specific.

Because the option is relevant only to the iOS variant of the native module, Platform.OS is used in the src/ReactNativePasskeysModule.ts to differentiate which arguments need to be passed in. This is inspired by the pattern used by Expo, for example in their WebBrowser module, openAuthSessionAsync method.

Finally, in the iOS module itself, the core of the implementation change lives in the isAvailable method, now responsible for canEvaluatePolicy depending on the requireBiometrics option, and conditionally checking biometricType like before.

Testing

Tested in an iOS device with Face ID disabled, with the new option added to the test app:

  • Using 'create' (no arguments) throws due to biometrics not being available.
  • Using 'authenticate' (no arguments) throws due to biometrics not being available.
  • Using 'create' (biometrics not requires) performs as expected.
  • Using 'authenticate' (biometrics not requires) performs as expected.

Also tested in an Android device to validate other platforms were not affected.

Summary by CodeRabbit

  • New Features

    • Added an option to control whether biometric authentication is required for passkey operations on iOS devices.
    • Introduced new configuration options for passkey creation and authentication, allowing users to enable or disable biometric requirements.
    • Updated the app interface to provide buttons for both biometric-required and biometric-optional passkey flows.
  • Chores

    • Documented the new configuration option in the release notes.

@coderabbitai
Copy link

coderabbitai bot commented May 24, 2025

Walkthrough

The changes introduce a configurable option for iOS to relax the biometric authentication requirement when creating or authenticating passkeys. A new requireBiometrics flag is added, allowing applications to specify whether biometric authentication or general device owner authentication is required. The configuration is exposed through both TypeScript interfaces and native iOS code.

Changes

File(s) Change Summary
.changeset/afraid-points-brush.md Added a changeset entry describing the new ios.requireBiometrics flag for the package.
example/src/app/index.tsx Updated button handlers and function signatures to accept and pass the new config; added demo buttons for both flows.
ios/ReactNativePasskeysModule.swift Modified native methods to accept requireBiometrics, updated logic to check authentication policy accordingly.
src/ReactNativePasskeysModule.ts Added platform-specific handling for requireBiometrics in native calls; updated method signatures.
src/index.ts Introduced PasskeysConfig and related option interfaces; updated create and get to accept config and pass flag.

Sequence Diagram(s)

sequenceDiagram
    participant App
    participant JSModule as ReactNativePasskeysModule.ts
    participant Native as ReactNativePasskeysModule.swift
    participant iOSSystem

    App->>JSModule: create(request, { ios: { requireBiometrics: false } })
    JSModule->>Native: create(request, requireBiometrics=false)
    Native->>Native: isAvailable(requireBiometrics=false)
    Native->>iOSSystem: Evaluate deviceOwnerAuthentication
    iOSSystem-->>Native: Result
    Native-->>JSModule: RegistrationResponseJSON
    JSModule-->>App: RegistrationResponseJSON
Loading

Assessment against linked issues

Objective Addressed Explanation
Make iOS biometric policy configurable to allow deviceOwnerAuthentication (Issue #36)

Poem

A hop and a skip, a passkey anew,
Now FaceID or passcode—it's up to you!
With a twitch of my nose and a tap of my paw,
Configurable options—oh, what I saw!
No longer must biometrics be king,
Flexibility's here—let the passkeys sing!
🐇✨

Note

⚡️ AI Code Reviews for VS Code, Cursor, Windsurf

CodeRabbit now has a plugin for VS Code, Cursor and Windsurf. This brings AI code reviews directly in the code editor. Each commit is reviewed immediately, finding bugs before the PR is raised. Seamless context handoff to your AI code agent ensures that you can easily incorporate review feedback.
Learn more here.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3c6dea2 and 6dc2901.

📒 Files selected for processing (5)
  • .changeset/afraid-points-brush.md (1 hunks)
  • example/src/app/index.tsx (4 hunks)
  • ios/ReactNativePasskeysModule.swift (4 hunks)
  • src/ReactNativePasskeysModule.ts (2 hunks)
  • src/index.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
example/src/app/index.tsx (2)
src/index.ts (1)
  • PasskeysConfig (25-41)
android/src/main/java/expo/modules/passkeys/PasskeyOptions.kt (1)
  • rp (10-36)
src/ReactNativePasskeysModule.ts (2)
src/ReactNativePasskeys.types.ts (4)
  • PublicKeyCredentialRequestOptionsJSON (66-73)
  • AuthenticationResponseJSON (96-103)
  • PublicKeyCredentialCreationOptionsJSON (51-61)
  • RegistrationResponseJSON (81-88)
src/errors.ts (1)
  • NotSupportedError (16-20)
src/index.ts (2)
src/ReactNativePasskeysModule.ts (2)
  • create (26-46)
  • get (17-24)
src/ReactNativePasskeys.types.ts (5)
  • PublicKeyCredentialCreationOptionsJSON (51-61)
  • AuthenticationExtensionsLargeBlobInputs (135-145)
  • RegistrationResponseJSON (81-88)
  • PublicKeyCredentialRequestOptionsJSON (66-73)
  • AuthenticationResponseJSON (96-103)
🔇 Additional comments (14)
.changeset/afraid-points-brush.md (1)

1-6: LGTM! Proper changeset documentation.

The changeset correctly documents this as a minor version update with an appropriate description of the new ios.requireBiometrics flag functionality.

example/src/app/index.tsx (4)

82-82: Good API design with optional configuration.

The function signature change is backwards compatible and properly typed with the optional PasskeysConfig parameter.


93-93: Proper parameter forwarding to native module.

The config parameter is correctly passed through to the underlying passkey.create call.


106-106: Consistent implementation across create and get functions.

Both authentication functions follow the same pattern for accepting and forwarding the configuration parameter.

Also applies to: 113-113


182-184: Excellent demonstration of the new feature.

The additional buttons clearly demonstrate the biometric requirement functionality, making it easy for developers to understand how to use the new ios.requireBiometrics flag.

Also applies to: 188-190

src/index.ts (3)

25-41: Excellent API design and documentation.

The PasskeysConfig interface is well-designed with:

  • Clear platform scoping under the ios property
  • Comprehensive JSDoc documentation with links to Apple's documentation
  • Sensible default behavior (true for biometric requirement)
  • Future extensibility for other platforms/options

The documentation clearly explains the difference between the two authentication policies.


43-43: Good use of interface extension for future flexibility.

The separate PasskeysCreateOptions and PasskeysGetOptions interfaces allow for future platform-specific or operation-specific configuration options while maintaining a clean base configuration.

Also applies to: 59-59


51-56: Proper implementation with backwards compatibility.

The optional parameter and nullish coalescing operator (??) ensure backwards compatibility while providing the new functionality. The default value of true maintains the existing biometric requirement behavior.

Also applies to: 67-72

src/ReactNativePasskeysModule.ts (3)

1-1: Appropriate platform import for conditional logic.

Adding the Platform import from expo-modules-core enables the necessary platform-specific behavior for iOS biometric requirements.


17-24: Well-implemented platform-specific method.

The new get method properly:

  • Uses correct TypeScript types for parameters and return value
  • Implements platform-specific logic (iOS gets the requireBiometrics parameter)
  • Maintains consistency with the existing create method pattern

28-28: Consistent platform-specific implementation.

The create method update follows the same pattern as the get method:

  • Added requireBiometrics parameter to signature
  • Platform-conditional native module calls
  • Maintains existing error handling and response transformation

This ensures consistent behavior across both passkey operations.

Also applies to: 32-35

ios/ReactNativePasskeysModule.swift (3)

28-32: LGTM! Function signature correctly updated.

The get function properly accepts the new requireBiometrics parameter and passes it to the isAvailable method. The implementation maintains the existing error handling pattern.


52-56: LGTM! Function signature correctly updated.

The create function properly accepts the new requireBiometrics parameter and passes it to the isAvailable method, mirroring the pattern used in the get function.


101-123: LGTM! Well-implemented authentication policy logic.

The isAvailable method correctly implements the conditional authentication policy:

  • Uses .deviceOwnerAuthenticationWithBiometrics when biometrics are required (stronger security)
  • Uses .deviceOwnerAuthentication when biometrics are not required (more lenient)
  • Maintains defensive programming by checking biometric type availability when required
  • Preserves backward compatibility with the default parameter value

The error handling is consistent and appropriate for both scenarios.

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@Only1MrAnderson
Copy link

@peterferguson any thoughts on getting this merged in? Would love to use it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Relax policy requirements on iOS to deviceOwnerAuthentication

2 participants