|
35 | 35 | - [Retrieve stored credentials](#retrieve-stored-credentials-1) |
36 | 36 | - [📱 Authentication API](#-authentication-api) |
37 | 37 | - [Login with database connection](#login-with-database-connection) |
| 38 | + - [Log in with passkeys](#log-in-with-passkeys) |
38 | 39 | - [Sign up with database connection](#sign-up-with-database-connection) |
39 | 40 | - [Passwordless Login](#passwordless-login) |
40 | 41 | - [Retrieve user information](#retrieve-user-information) |
@@ -1031,6 +1032,7 @@ final credentials = await auth0Web.credentials(); |
1031 | 1032 | > This feature is mobile/macOS only; the [SPA SDK](https://github.com/auth0/auth0-spa-js) used by auth0_flutter does not include an API client. |
1032 | 1033 |
|
1033 | 1034 | - [Login with database connection](#login-with-database-connection) |
| 1035 | +- [Log in with passkeys](#log-in-with-passkeys) |
1034 | 1036 | - [Sign up with database connection](#sign-up-with-database-connection) |
1035 | 1037 | - [Retrieve user information](#retrieve-user-information) |
1036 | 1038 | - [Renew credentials](#renew-credentials) |
@@ -1088,6 +1090,67 @@ final credentials = await auth0.api.login( |
1088 | 1090 |
|
1089 | 1091 | </details> |
1090 | 1092 |
|
| 1093 | +### Log in with passkeys |
| 1094 | + |
| 1095 | +> This feature is available on **iOS 16.6+** and **Android 9+ (API 28)** only. |
| 1096 | +
|
| 1097 | +[Passkeys](https://auth0.com/docs/authenticate/database-connections/passkeys) let an existing user log in with a biometric or device PIN instead of a password, using the platform authenticator (Face ID / Touch ID on iOS, the Credential Manager on Android). |
| 1098 | + |
| 1099 | +> ⚠️ Passkeys require additional configuration on both your Auth0 tenant and your app: |
| 1100 | +> - Set up a [custom domain](https://auth0.com/docs/customize/custom-domains) for your tenant. Passkeys will **not** work without one, since the relying-party domain must be a domain you own and can host the associated domain / Digital Asset Links file on. |
| 1101 | +> - Enable passkeys for your database connection and the **Passkey** grant type for your application. See [Configure passkeys](https://auth0.com/docs/authenticate/database-connections/passkeys/configure-passkeys). |
| 1102 | +> - Configure the [associated domain (iOS/macOS)](README.md#iosmacos-configure-the-associated-domain) and the equivalent [Digital Asset Links file](https://developer.android.com/identity/sign-in/credential-manager#add-support-dal) (Android) so the OS associates your app with the relying-party domain. |
| 1103 | +
|
| 1104 | +The SDK exposes **two** methods for passkey login — `passkeyLoginChallenge` and `passkeyLogin` — and leaves presenting the OS passkey UI to your app. The flow is: |
| 1105 | + |
| 1106 | +1. Request a login challenge from Auth0 with `passkeyLoginChallenge`. |
| 1107 | +2. **In your app**, present the platform authenticator using that challenge and obtain a WebAuthn assertion. The SDK does **not** do this step — call the OS APIs directly (for example, [`ASAuthorizationController`](https://developer.apple.com/documentation/authenticationservices/asauthorizationcontroller) on iOS/macOS or [Credential Manager](https://developer.android.com/identity/sign-in/credential-manager) on Android, typically over your own platform channel), then map the result into a `PasskeyLoginCredential`. |
| 1108 | +3. Exchange that credential for Auth0 tokens with `passkeyLogin`. |
| 1109 | + |
| 1110 | +```dart |
| 1111 | +// 1. Request a login challenge from Auth0. |
| 1112 | +final challenge = await auth0.api.passkeyLoginChallenge( |
| 1113 | + connection: 'Username-Password-Authentication'); |
| 1114 | +
|
| 1115 | +// 2. Present the OS passkey UI in your app (not provided by the SDK) using |
| 1116 | +// `challenge.authParamsPublicKey`, then build a PasskeyLoginCredential from |
| 1117 | +// the resulting WebAuthn assertion. All values are base64url-encoded. |
| 1118 | +final credential = PasskeyLoginCredential( |
| 1119 | + id: '<base64url credentialId>', |
| 1120 | + rawId: '<base64url credentialId>', |
| 1121 | + type: 'public-key', |
| 1122 | + authenticatorAttachment: 'platform', |
| 1123 | + response: PasskeyAuthenticatorAssertionResponse( |
| 1124 | + clientDataJSON: '<base64url clientDataJSON>', |
| 1125 | + authenticatorData: '<base64url authenticatorData>', |
| 1126 | + signature: '<base64url signature>', |
| 1127 | + userHandle: '<base64url userHandle>')); |
| 1128 | +
|
| 1129 | +// 3. Exchange the credential for Auth0 tokens. |
| 1130 | +final credentials = await auth0.api.passkeyLogin( |
| 1131 | + challenge: challenge, |
| 1132 | + credential: credential, |
| 1133 | + connection: 'Username-Password-Authentication'); |
| 1134 | +
|
| 1135 | +// Store the credentials afterward |
| 1136 | +final didStore = |
| 1137 | + await auth0.credentialsManager.storeCredentials(credentials); |
| 1138 | +``` |
| 1139 | + |
| 1140 | +<details> |
| 1141 | + <summary>Add an audience and scope values</summary> |
| 1142 | + |
| 1143 | +```dart |
| 1144 | +final credentials = await auth0.api.passkeyLogin( |
| 1145 | + challenge: challenge, |
| 1146 | + credential: credential, |
| 1147 | + connection: 'Username-Password-Authentication', |
| 1148 | + audience: 'YOUR_AUTH0_API_IDENTIFIER', |
| 1149 | + scopes: {'profile', 'email', 'offline_access', 'read:todos'}); |
| 1150 | +``` |
| 1151 | + |
| 1152 | +</details> |
| 1153 | + |
1091 | 1154 | ### Sign up with database connection |
1092 | 1155 |
|
1093 | 1156 | ```dart |
|
0 commit comments