You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: examples/MFA.md
+6-5Lines changed: 6 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -545,15 +545,16 @@ The SDK does not store your private key, so you must re-supply it on the `verify
545
545
546
546
By default, `verify()` returns tokens without persisting them to the session store. However, you can automatically persist tokens by setting `persist=True`.
547
547
548
-
> [!WARNING]
549
-
> `persist=True`**updates an existing session** — it does not create one. On a passkey-firstlogin (`signin_with_passkey` → `MfaRequiredError`) no session exists yet, so `persist=True` raises `MfaVerifyError("No existing session found to update with MFA tokens")` and discards the tokens `verify()` just obtained. On that path, use `persist=False` (the default) and store the returned tokens yourself — see [Passkeys.md → Completing MFA on a passkey login](Passkeys.md#completing-mfa-on-a-passkey-login-and-where-the-session-comes-from).
548
+
> [!NOTE]
549
+
> `persist=True` updates an existing session when one is present. For first-login MFA flows where the SDK has not created a session yet, `ServerClient.mfa` can create the initial session from the final MFA token response when that response includes an ID token.
550
550
551
551
### Automatic Session Update
552
552
553
553
When you set `persist=True`, the SDK will:
554
-
1. Update the session's `access_token` for the specified audience
555
-
2. Update the session's `id_token` if present
556
-
3. Add the token to the `token_sets` array with expiration information
554
+
1. Update an existing session, or create the initial session when the MFA flow completed a first login
555
+
2. Persist the `access_token` for the specified audience
556
+
3. Persist the `id_token` if present
557
+
4. Add the token to the `token_sets` array with expiration information
Copy file name to clipboardExpand all lines: examples/Passwordless.md
+12-8Lines changed: 12 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -189,6 +189,9 @@ user = result["state_data"]["user"]
189
189
>
190
190
> This matters more than it looks: Auth0 treats magic-link `state` as a pure echo and does not validate it server-side, and the clicked link's query string can overwrite whatever the browser originally stored. The SDK's single-use, `state`-keyed transaction plus the exact-match `redirect_uri` are therefore the *entire* CSRF / authorization-code-interception defense on this flow — Auth0 will not catch a bypass for you.
191
191
192
+
> [!NOTE]
193
+
> If the callback fails (expired link, JWKS unavailable, a rejected ID token), have the user restart the flow from `start()` rather than retrying the same link — a failed callback does not guarantee the transaction was cleaned up, so re-submitting the same callback URL can produce a confusing error instead of a clear "session expired, please try again."
194
+
192
195
## 4. Custom scopes and audiences
193
196
194
197
For OTP flows, pass `scope` and `audience` to `verify()`. These become the `/oauth/token` request parameters.
@@ -206,6 +209,8 @@ result = await server_client.passwordless.verify(
206
209
)
207
210
```
208
211
212
+
A caller-supplied OTP `scope`**replaces** the default wholesale rather than merging with it. The SDK re-injects `openid` when your scope omits it, for the same reason as magic link below: without it, Auth0 returns no ID token and `verify()` fails.
213
+
209
214
For magic links, pass allowed authorization parameters through `auth_params` at `start()` time:
210
215
211
216
```python
@@ -258,7 +263,7 @@ result = await server_client.passwordless.verify(
258
263
259
264
## Completing MFA during passwordless login
260
265
261
-
Auth0 can require MFA during passwordless OTP verification. In that case, the SDK raises `MfaRequiredError` before it creates a session. Complete the MFA challenge with `server_client.mfa`, then persist the returned tokens according to your framework's session integration.
266
+
Auth0 can require MFA during passwordless OTP verification. In that case, the SDK raises `MfaRequiredError` before it creates a session. Complete the MFA challenge with `server_client.mfa` and pass `persist=True` on verification so the SDK creates the session from the final MFA token response.
262
267
263
268
```python
264
269
from auth0_server_python.error import MfaRequiredError
@@ -280,20 +285,19 @@ except MfaRequiredError as e:
> Passwordless OTP MFA is like passkey-first MFA: there is no existing application session yet. Use the returned MFA tokens to create the session in your framework layer rather than trying to update a session that does not exist.
300
+
> Passwordless OTP MFA is like passkey-first MFA: there is no existing application session until MFA verification succeeds. `persist=True` creates the initial SDK session when the MFA response includes an ID token.
0 commit comments