Skip to content

Commit f4308ab

Browse files
committed
Updated example docs
1 parent 69ea847 commit f4308ab

3 files changed

Lines changed: 8 additions & 67 deletions

File tree

examples/DPoP.md

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ This SDK supports DPoP for **passkey sign-in** (`ServerClient.signin_with_passke
1616
- [4. Generating a proof manually](#4-generating-a-proof-manually)
1717
- [Key lifecycle and security](#key-lifecycle-and-security)
1818
- [Error Handling](#error-handling)
19-
- [Additional Resources](#additional-resources)
2019

2120
## `dpop_key` vs `dpop_proof`
2221

@@ -125,9 +124,3 @@ except PasskeyError as e:
125124
```
126125

127126
On the My Account surface, a key mismatch or a DPoP-required endpoint reached without binding surfaces as `MyAccountApiError` (typically `status=401`). Catch `Auth0Error` for uniform handling.
128-
129-
## Additional Resources
130-
131-
- [Passkey Authentication](Passkeys.md)
132-
- [My Account — Authentication Methods](MyAccountAuthenticationMethods.md)
133-
- [RFC 9449 — OAuth 2.0 Demonstrating Proof of Possession (DPoP)](https://www.rfc-editor.org/rfc/rfc9449)

examples/MyAccountAuthenticationMethods.md

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ The [My Account API](https://auth0.com/docs/manage-users/my-account-api) lets a
2020
- [6. Delete an authentication method](#6-delete-an-authentication-method)
2121
- [DPoP](#dpop)
2222
- [Error Handling](#error-handling)
23-
- [Additional Resources](#additional-resources)
2423

2524
## Prerequisites
2625

@@ -231,10 +230,3 @@ except Auth0Error as e:
231230
- **`MyAccountApiError`**: My Account API errors with `status`, `detail`, optional `validation_errors`
232231
- **`MissingRequiredArgumentError`**: a required parameter (`access_token`, `authentication_method_id`, `request`) was not provided
233232
- **`ApiError`**: transport failure or a non-JSON error body
234-
235-
## Additional Resources
236-
237-
- [Connected Accounts (Token Vault)](ConnectedAccounts.md) — the other My Account surface, and shared My Account/MRRT setup
238-
- [Passkey Authentication](Passkeys.md) — signing in with a passkey
239-
- [DPoP](DPoP.md) — sender-constrained tokens
240-
- [Auth0 My Account API documentation](https://auth0.com/docs/manage-users/my-account-api)

examples/Passkeys.md

Lines changed: 8 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,8 @@ Passkeys let users sign up and log in with [WebAuthn](https://www.w3.org/TR/weba
1414
- [Prerequisites](#prerequisites)
1515
- [1. Passkey Signup](#1-passkey-signup)
1616
- [2. Passkey Login](#2-passkey-login)
17-
- [3. Organizations](#3-organizations)
18-
- [4. Step-up MFA during passkey login](#4-step-up-mfa-during-passkey-login)
19-
- [5. DPoP-bound passkey tokens](#5-dpop-bound-passkey-tokens)
17+
- [3. DPoP-bound passkey tokens (optional)](#3-dpop-bound-passkey-tokens-optional)
2018
- [Error Handling](#error-handling)
21-
- [Additional Resources](#additional-resources)
2219

2320
## How the flow works
2421

@@ -141,50 +138,14 @@ result = await server_client.signin_with_passkey(
141138
> [!NOTE]
142139
> The SDK is transparent to the signup-vs-login difference in the credential `response` — both flow through the same `PasskeyAuthResponse.response` dict. Send exactly the keys the browser produced.
143140
144-
## 3. Organizations
141+
## 3. DPoP-bound passkey tokens (optional)
145142

146-
Pass an `organization` (ID or name) on the challenge to scope the passkey ceremony to an organization. The resulting `id_token` carries the `org_id` claim, validated automatically at session creation.
147-
148-
```python
149-
challenge = await server_client.passkey_login_challenge(
150-
organization="org_abc123",
151-
store_options={"request": request, "response": response},
152-
)
153-
# ... signin_with_passkey(organization="org_abc123", ...)
154-
```
155-
156-
## 4. Step-up MFA during passkey login
157-
158-
If tenant policy requires a second factor, `signin_with_passkey` raises `MfaRequiredError` — the login does **not** complete silently. The raw MFA token is encrypted by the SDK before it reaches you, and stored server-side so your challenge/verify routes can retrieve it without a client round-trip.
159-
160-
```python
161-
from auth0_server_python.error import MfaRequiredError
162-
163-
try:
164-
result = await server_client.signin_with_passkey(
165-
auth_session=challenge.auth_session,
166-
authn_response=authn_response,
167-
store_options={"request": request, "response": response},
168-
)
169-
except MfaRequiredError as e:
170-
# e.mfa_token is ENCRYPTED — hand it straight to MfaClient.
171-
# See examples/MFA.md for the challenge/verify flow.
172-
...
173-
```
174-
175-
See [examples/MFA.md](MFA.md) for the full challenge → verify continuation.
176-
177-
> [!NOTE]
178-
> A passkey is supported as a **first** factor today. WebAuthn as a **second** factor is currently only available through Universal Login (hosted), not as a headless API a server SDK can drive — so this SDK does not implement it. The response models are forward-tolerant for when that capability ships.
179-
180-
## 5. DPoP-bound passkey tokens
181-
182-
Pass a `dpop_key` to bind the issued tokens to a key you hold (RFC 9449). When supplied, the SDK attaches a DPoP proof to the token exchange and Auth0 issues a DPoP-bound token; if the server returns an unbound (`Bearer`) token instead, `signin_with_passkey` raises rather than accept the downgrade.
143+
Pass an optional `dpop_key` to bind the issued tokens to a key your server holds ([RFC 9449](https://www.rfc-editor.org/rfc/rfc9449)), so a stolen token alone cannot be replayed. DPoP is **opt-in**: omit `dpop_key` and sign-in returns ordinary Bearer tokens with no behaviour change.
183144

184145
```python
185146
from jwcrypto import jwk
186147

187-
dpop_key = jwk.JWK.generate(kty="EC", crv="P-256") # you create and keep this key
148+
dpop_key = jwk.JWK.generate(kty="EC", crv="P-256") # you generate and keep this key (Tier 0)
188149

189150
result = await server_client.signin_with_passkey(
190151
auth_session=challenge.auth_session,
@@ -194,7 +155,10 @@ result = await server_client.signin_with_passkey(
194155
)
195156
```
196157

197-
Reuse the **same** `dpop_key` for any My Account API calls made with the resulting token. See [examples/DPoP.md](DPoP.md) for the full picture.
158+
When `dpop_key` is supplied, the SDK attaches a token-endpoint proof so Auth0 issues a DPoP-bound token, transparently handles the server-nonce challenge, and **rejects a Bearer downgrade** — if the server returns an unbound token, `signin_with_passkey` raises `PasskeyError` rather than silently accepting a token bound to a key it never used.
159+
160+
> [!TIP]
161+
> Reuse the **same** `dpop_key` for any subsequent My Account API calls made with the resulting token — the token is bound to that one key. See [examples/DPoP.md](DPoP.md) for the `dpop_key` vs `dpop_proof` distinction, key lifecycle, and nonce handling.
198162
199163
## Error Handling
200164

@@ -242,11 +206,3 @@ except Auth0Error as e:
242206

243207
> [!NOTE]
244208
> `auth_session` is a short-lived (typically ~5 min) Tier 1 credential. It is redacted in the SDK's model `repr()`, and you should never log or persist it. If the ceremony takes too long, re-request the challenge.
245-
246-
## Additional Resources
247-
248-
- [Managing passkeys via My Account API](MyAccountAuthenticationMethods.md) — enroll/list/delete a logged-in user's passkeys
249-
- [DPoP](DPoP.md) — sender-constrained tokens
250-
- [MFA](MFA.md) — handling `MfaRequiredError`
251-
- [Auth0 Passkey documentation](https://auth0.com/docs/authenticate/database-connections/passkeys)
252-
- [WebAuthn Level 2 (W3C)](https://www.w3.org/TR/webauthn-2/)

0 commit comments

Comments
 (0)