diff --git a/A0Auth0.podspec b/A0Auth0.podspec index d5b7ee8e..0d8248e3 100644 --- a/A0Auth0.podspec +++ b/A0Auth0.podspec @@ -16,7 +16,7 @@ Pod::Spec.new do |s| s.source_files = 'ios/**/*.{h,m,mm,swift}' s.requires_arc = true - s.dependency 'Auth0', '2.19.0' + s.dependency 'Auth0', '2.21.1' install_modules_dependencies(s) end diff --git a/EXAMPLES.md b/EXAMPLES.md index 9fdac540..ae3e6ff6 100644 --- a/EXAMPLES.md +++ b/EXAMPLES.md @@ -49,6 +49,15 @@ - [Using Custom Token Exchange with Auth0 Class](#using-custom-token-exchange-with-auth0-class) - [With Organization Context](#with-organization-context) - [Subject Token Type Requirements](#subject-token-type-requirements) +- [Passkeys](#passkeys) + - [Overview](#passkeys-overview) + - [Prerequisites](#passkeys-prerequisites) + - [Signup with Passkey](#signup-with-passkey) + - [Signin with Passkey](#signin-with-passkey) + - [Advanced: Manual Credential Manager Handling](#advanced-manual-credential-manager-handling) + - [Using Passkeys with Auth0 Class](#using-passkeys-with-auth0-class) + - [Error Handling](#passkeys-error-handling) + - [Platform Support](#passkeys-platform-support) - [Native to Web SSO](#native-to-web-sso) - [Overview](#native-to-web-sso-overview) - [Prerequisites](#native-to-web-sso-prerequisites) @@ -1011,6 +1020,270 @@ For detailed examples of validating different token types in Actions, see: - Validate token expiration, issuer, and audience claims - Implement rate limiting for failed validations using `api.access.rejectInvalidSubjectToken()` +## Passkeys + + + +### Overview + +Passkeys provide a passwordless authentication experience using platform biometrics (Face ID, Touch ID, fingerprint) backed by public-key cryptography. The SDK provides the Auth0 challenge and token exchange steps, while you handle the platform credential manager interaction using native modules or libraries like `react-native-passkey`. + +The passkey flow has three steps: + +1. **Challenge** — Request a WebAuthn challenge from Auth0 (`passkeySignupChallenge` or `passkeyLoginChallenge`) +2. **Credential Manager** — Present the OS credential manager UI to create or assert a passkey (using your own native module or a library) +3. **Exchange** — Send the credential response back to Auth0 to get tokens (`getTokenByPasskey`) + +> **Platform Support:** Native only (iOS 16.6+ / Android). Not supported on Web. + + + +### Prerequisites + +Before using passkeys: + +1. **Enable the Passkey Grant Type** for your Auth0 application in the Auth0 Dashboard +2. **Configure a custom domain** on your Auth0 tenant (required for passkeys) +3. **iOS:** Requires iOS 16.6 or later. Add an Associated Domain with the `webcredentials` service pointing to your Auth0 custom domain +4. **Android:** Requires Android API 28+. Configure your app's Digital Asset Links for the Auth0 custom domain + +> **Important:** `passkeySignupChallenge` is for creating **new** user accounts with a passkey. It will fail if the email already exists in the database connection. Use `passkeyLoginChallenge` for existing users who have already registered a passkey. + +### Signup with Passkey + +The signup flow requests a registration challenge from Auth0, then you use the platform credential manager (via a native module or library like `react-native-passkey`) to create a new passkey, and finally exchange the credential for Auth0 tokens. + +```tsx +import { useAuth0, PasskeyError } from 'react-native-auth0'; + +function PasskeySignupScreen() { + const { passkeySignupChallenge, getTokenByPasskey } = useAuth0(); + + const handleSignup = async () => { + try { + // Step 1: Get the signup challenge from Auth0 + const challenge = await passkeySignupChallenge({ + email: 'user@example.com', + name: 'John Doe', + realm: 'Username-Password-Authentication', + }); + + // Step 2: Use the platform credential manager to create a passkey + // challenge.authParamsPublicKey contains the WebAuthn PublicKeyCredentialCreationOptions + // Use your preferred library (e.g., react-native-passkey) or native module + const credentialJson = await yourCredentialManagerCreate( + challenge.authParamsPublicKey + ); + + // Step 3: Exchange the credential response for Auth0 tokens + const credentials = await getTokenByPasskey({ + authSession: challenge.authSession, + authResponse: credentialJson, + realm: 'Username-Password-Authentication', + audience: 'https://api.example.com', + scope: 'openid profile email offline_access', + }); + + console.log('Signed up with passkey:', credentials.accessToken); + } catch (error) { + if (error instanceof PasskeyError) { + console.error('Passkey signup failed:', error.type, error.message); + } + } + }; + + return