Conversation
Reflects the API change in #407 — for PASSKEY credentials, clientPublicKey now goes on POST /auth/credentials/{id}/challenge instead of /verify. Grid bakes the public key into the Turnkey session-creation payload that the returned challenge is computed from, so the resulting session signing key is sealed to the device that requested the challenge. Knock-on flow change: registration response is now a plain AuthMethod (no inline PasskeyAuthChallenge). Both first-time activation and reauthentication for PASSKEY follow the same three-step shape: register → /challenge (with clientPublicKey) → /verify (with Request-Id, no clientPublicKey). EMAIL_OTP and OAUTH are unchanged — clientPublicKey stays on /verify for those types; /challenge takes an empty body. Updates: - snippets/global-accounts/authentication.mdx — overview, passkey registration sequence diagram + TS/Kotlin/Swift code samples, parameter map split into challenge + assertion tables, passkey reauth diagram, additional-credential activation prose - snippets/global-accounts/overview.mdx — Quickstart Step 7 now generates the keypair before calling /challenge with clientPublicKey, and the /verify body drops it - snippets/global-accounts/client-keys.mdx — clarifies which call carries clientPublicKey for each credential type - snippets/sandbox-global-account-magic.mdx — passkey example now shows the /challenge + /verify pair; verify body drops clientPublicKey Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Preview deployment for your docs. Learn more about Mintlify Previews.
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryThis PR updates four documentation snippets to reflect the API change introduced in #407: for Confidence Score: 4/5Safe to merge — one minor wording inaccuracy in the sandbox docs, all core content is consistent and correct. All four files are internally consistent and correctly reflect the API change. The single finding is a P2 wording issue in sandbox-global-account-magic.mdx where 'reauthentication' is used to describe a flow that applies equally to first-time activation. mintlify/snippets/sandbox-global-account-magic.mdx — the new prose scopes the /challenge → /verify two-step to 'reauthentication' only, which is inaccurate.
|
| Filename | Overview |
|---|---|
| mintlify/snippets/global-accounts/authentication.mdx | Accurately moves clientPublicKey from /verify to /challenge for PASSKEY across the overview prose, both sequence diagrams (registration + reauth), all three SDK code samples (TS/Kotlin/Swift), and the parameter tables. |
| mintlify/snippets/global-accounts/client-keys.mdx | Single-paragraph update correctly maps clientPublicKey placement per credential type (PASSKEY → /challenge, EMAIL_OTP/OAUTH → /verify, export → /export). |
| mintlify/snippets/global-accounts/overview.mdx | Quickstart Step 7 correctly reordered: keypair generation and /challenge (with clientPublicKey) now happen before the WebAuthn assertion, and /verify body drops clientPublicKey. |
| mintlify/snippets/sandbox-global-account-magic.mdx | Adds /challenge → /verify example pair for sandbox passkey, but the new prose scopes the two-step flow only to 'reauthentication' when first-time activation follows the same pattern. |
Sequence Diagram
sequenceDiagram
participant C as Client
participant IB as Integrator Backend
participant G as Grid
participant A as Authenticator
note over C,A: Registration
C->>A: navigator.credentials.create({ challenge })
A-->>C: attestation
C->>IB: POST /my-backend/passkey/register (attestation)
IB->>G: POST /auth/credentials { type: PASSKEY, … }
G-->>IB: 201 AuthMethod { id, type, accountId, … }
IB-->>C: { credentialId }
note over C,A: First Auth / Reauthentication (same shape)
C->>C: generateClientKeyPair()
C->>IB: POST /my-backend/passkey/challenge (credentialId, clientPublicKey)
IB->>G: POST /auth/credentials/{id}/challenge { clientPublicKey }
G-->>IB: 200 PasskeyAuthChallenge { challenge, requestId, expiresAt }
IB-->>C: { challenge, requestId }
C->>A: navigator.credentials.get({ challenge })
A-->>C: assertion
C->>IB: POST /my-backend/passkey/verify (assertion, requestId)
IB->>G: POST /auth/credentials/{id}/verify Request-Id: requestId { type: PASSKEY, assertion }
G-->>IB: 200 AuthSession { encryptedSessionSigningKey, expiresAt }
IB-->>C: { encryptedSessionSigningKey, expiresAt }
C->>C: decrypt with private key → session signing key
Prompt To Fix All With AI
This is a comment left during a code review.
Path: mintlify/snippets/sandbox-global-account-magic.mdx
Line: 27
Comment:
**"Reauthentication" scope is too narrow**
The new paragraph says "Passkey reauthentication is a two-step `/challenge` → `/verify` flow," but per the PR description and the updated `authentication.mdx`, both first-time activation *and* reauthentication now follow this same shape. A developer testing first-time passkey setup in sandbox might read this and not realise they need to call `/challenge` (with `clientPublicKey`) before the magic `/verify` call.
```suggestion
Passkey authentication (both first-time activation and reauthentication) is a two-step `/challenge` → `/verify` flow. The `clientPublicKey` is sent on `/challenge` (so Grid can seal the session signing key to your device) — the magic value bypasses the credential check, not the HPKE plumbing, so the public key is still required.
```
How can I resolve this? If you propose a fix, please make it concise.Reviews (1): Last reviewed commit: "docs: move passkey clientPublicKey from ..." | Re-trigger Greptile
|
|
||
| Pass `sandbox-valid-passkey-signature` as `assertion.signature` on `POST /auth/credentials/{id}/verify` when the credential type is `PASSKEY`. The sandbox accepts the rest of the assertion as-is and skips the WebAuthn signature check. | ||
|
|
||
| Passkey reauthentication is a two-step `/challenge` → `/verify` flow. The `clientPublicKey` is sent on `/challenge` (so Grid can seal the session signing key to your device) — the magic value bypasses the credential check, not the HPKE plumbing, so the public key is still required. |
There was a problem hiding this comment.
"Reauthentication" scope is too narrow
The new paragraph says "Passkey reauthentication is a two-step /challenge → /verify flow," but per the PR description and the updated authentication.mdx, both first-time activation and reauthentication now follow this same shape. A developer testing first-time passkey setup in sandbox might read this and not realise they need to call /challenge (with clientPublicKey) before the magic /verify call.
| Passkey reauthentication is a two-step `/challenge` → `/verify` flow. The `clientPublicKey` is sent on `/challenge` (so Grid can seal the session signing key to your device) — the magic value bypasses the credential check, not the HPKE plumbing, so the public key is still required. | |
| Passkey authentication (both first-time activation and reauthentication) is a two-step `/challenge` → `/verify` flow. The `clientPublicKey` is sent on `/challenge` (so Grid can seal the session signing key to your device) — the magic value bypasses the credential check, not the HPKE plumbing, so the public key is still required. |
Prompt To Fix With AI
This is a comment left during a code review.
Path: mintlify/snippets/sandbox-global-account-magic.mdx
Line: 27
Comment:
**"Reauthentication" scope is too narrow**
The new paragraph says "Passkey reauthentication is a two-step `/challenge` → `/verify` flow," but per the PR description and the updated `authentication.mdx`, both first-time activation *and* reauthentication now follow this same shape. A developer testing first-time passkey setup in sandbox might read this and not realise they need to call `/challenge` (with `clientPublicKey`) before the magic `/verify` call.
```suggestion
Passkey authentication (both first-time activation and reauthentication) is a two-step `/challenge` → `/verify` flow. The `clientPublicKey` is sent on `/challenge` (so Grid can seal the session signing key to your device) — the magic value bypasses the credential check, not the HPKE plumbing, so the public key is still required.
```
How can I resolve this? If you propose a fix, please make it concise.
Reflects the API change in #407 — for PASSKEY credentials,
clientPublicKey now goes on POST /auth/credentials/{id}/challenge
instead of /verify. Grid bakes the public key into the Turnkey
session-creation payload that the returned challenge is computed
from, so the resulting session signing key is sealed to the device
that requested the challenge.
Knock-on flow change: registration response is now a plain AuthMethod
(no inline PasskeyAuthChallenge). Both first-time activation and
reauthentication for PASSKEY follow the same three-step shape:
register → /challenge (with clientPublicKey) → /verify (with
Request-Id, no clientPublicKey).
EMAIL_OTP and OAUTH are unchanged — clientPublicKey stays on /verify
for those types; /challenge takes an empty body.
Updates:
registration sequence diagram + TS/Kotlin/Swift code samples,
parameter map split into challenge + assertion tables, passkey
reauth diagram, additional-credential activation prose
generates the keypair before calling /challenge with
clientPublicKey, and the /verify body drops it
carries clientPublicKey for each credential type
shows the /challenge + /verify pair; verify body drops
clientPublicKey
Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com