Skip to content

feat(auth): add biometric authentication support#897

Draft
grdsdev wants to merge 11 commits intomainfrom
grdsdev/auth-biometrics
Draft

feat(auth): add biometric authentication support#897
grdsdev wants to merge 11 commits intomainfrom
grdsdev/auth-biometrics

Conversation

@grdsdev
Copy link
Contributor

@grdsdev grdsdev commented Feb 2, 2026

Summary

Add biometric authentication (Face ID/Touch ID) support to the Auth module. Features include configurable policies (.default, .always, .session(timeout:), .appLifecycle), automatic integration with session retrieval, and full Swift 6/Sendable conformance.

Usage

// Check biometric availability
let availability = client.auth.biometricsAvailability()
if availability.isAvailable {
    // Enable biometrics with custom policy
    try await client.auth.enableBiometrics(
        title: "Unlock with Face ID",
        policy: .session(timeoutInSeconds: 300)
    )
}

// Get session - automatically prompts for biometrics when enabled
let session = try await client.auth.session

// Check if auth would be required (useful for UI hints)
if client.auth.isBiometricAuthenticationRequired() {
    // Show "unlock" UI
}

// Force re-authentication on next access
client.auth.invalidateBiometricSession()

// Disable biometrics
client.auth.disableBiometrics()

Policies:

  • .default - Authenticate on first access only
  • .always - Authenticate every time
  • .session(timeoutInSeconds:) - Authenticate after timeout expires
  • .appLifecycle - Authenticate when returning from background

Changes

  • New types: BiometricTypes, BiometricAuthenticator, BiometricSession, BiometricStorage
  • Internal helper: withBiometrics() for protecting sensitive operations
  • AuthClient API: enableBiometrics(), disableBiometrics(), biometricsAvailability(), isBiometricAuthenticationRequired()
  • SessionManager integration: automatic biometric checks via withBiometrics guard
  • Platform support: iOS, macOS, tvOS, watchOS, visionOS via conditional compilation

Test Plan

  • Verify builds successfully on all platforms
  • Test biometrics availability detection
  • Test each policy type: .default, .always, .session(timeout:), .appLifecycle
  • Verify session() automatically prompts for biometrics when enabled
  • Test user cancellation returns .userCancelled error
  • Test disableBiometrics() removes biometric requirement

🤖 Generated with Claude Code

@coderabbitai
Copy link

coderabbitai bot commented Feb 2, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

  • 🔍 Trigger a full review
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch grdsdev/auth-biometrics

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added the auth label Feb 2, 2026
grdsdev and others added 11 commits February 4, 2026 05:33
Implement biometric authentication (Face ID/Touch ID) for session protection following the Auth0 CredentialsManager pattern. Features include:

- Configurable policies: .default, .always, .session(timeout:), .appLifecycle
- Flat API: enableBiometrics(), disableBiometrics(), biometricsAvailability()
- Automatic integration: session() automatically requires biometrics when enabled
- Internal withBiometrics() helper for protecting sensitive operations
- Full Swift 6/Sendable conformance
- Platform support: iOS, macOS, tvOS, watchOS, visionOS

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Add mock implementations for BiometricStorage and BiometricSession to
support testing. Update test files to use conditional compilation for
biometric dependencies.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Move all biometric-related files into Sources/Auth/Biometrics/ and
extract AuthClient biometric extension into its own file for better
organization.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
The BiometricStorage.live() was eagerly loading settings during
initialization, which accessed Dependencies before they were fully
set up. Changed to lazy loading that defers settings retrieval until
first access.

Also added comprehensive tests for the biometrics feature covering:
- BiometricStorage enable/disable with all policy types
- BiometricSession recording, reset, and policy evaluation
- BiometricAuthenticator mock behavior
- withBiometrics helper function
- AuthClient biometrics extension methods
- BiometricError and BiometricPolicy types

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Created AppLifecycle enum in Internal/ that provides cross-platform
notification names for app lifecycle events (active, resign active,
background, foreground). This consolidates the platform-specific
conditional compilation logic that was duplicated in AuthClient and
BiometricSession.

- AuthClient now uses AppLifecycle notification names with Combine
- BiometricSession uses AppLifecycle.observeBackgroundTransitions()
- Removed ~70 lines of duplicated platform-specific code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Removed 18 tests that were just testing mock implementations:
- BiometricStorage.mock tests
- BiometricSession inline mock tests
- BiometricAuthenticator.mock tests

Kept 17 tests that test real code:
- withBiometrics function tests (with injected dependencies)
- AuthClient extension tests (with injected dependencies)
- BiometricError, BiometricPolicy, BiometricEvaluationPolicy type tests

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add comprehensive biometrics examples to the Examples app:
- BiometricsExample.swift: Standalone example demonstrating all biometrics
  features including availability check, policy configuration, session
  access testing, and enable/disable flows
- ProfileView: Add biometrics configuration to the Security section,
  allowing users to enable/disable biometrics after login
- AuthExamplesView: Add navigation link to biometrics example

Also change BiometricPolicy from Equatable to Hashable for SwiftUI Picker
compatibility.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove BIOMETRICS_ENABLED and BIOMETRICS_DISABLED events from AuthChangeEvent
as biometric state changes are local-only and don't need to be part of the
auth state change stream.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove redundant error cases from BiometricError and BiometricUnavailableReason:
- Remove notEnabled from BiometricError (handled differently)
- Remove biometryNotEnrolled, biometryLockout, other from BiometricUnavailableReason
  (these are covered by notAvailable or other error paths)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove tests for removed error cases to match the simplified
BiometricError and BiometricUnavailableReason enums.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@grdsdev grdsdev force-pushed the grdsdev/auth-biometrics branch from cfd5f44 to 92821b3 Compare February 4, 2026 08:33
@kkarlsen06
Copy link
Contributor

This caught my eye and is a valued addition. This made it much easier to implement stable Face ID authentication in my iOS app using the Supabase-swift SDK.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants