feat: add PASSKEY branch to auth credential verify#364
Conversation
Adds the PASSKEY branch to `AuthCredentialVerifyRequestOneOf`, completing the create + verify flow for WebAuthn-passkey-backed authentication credentials on Embedded Wallet internal accounts.
**Request shape**
- `POST /auth/credentials/{id}/verify` body: `{ type: "PASSKEY", assertion, clientPublicKey }` → 200 `AuthSession`.
- `{id}` is the `AuthMethod.id` returned from `POST /auth/credentials`.
**Schemas added**
- `PasskeyAssertion` — `{ credentialId, clientDataJson, authenticatorData, signature, userHandle? }`, all base64url-encoded strings. Shape mirrors the W3C `AuthenticatorAssertionResponse` plus the optional `userHandle`; pass-through to the downstream passkey provider.
- `PasskeyCredentialVerifyRequestFields` — `{ type: "PASSKEY", assertion, clientPublicKey }` (variant single-value enum on `type`).
- `PasskeyCredentialVerifyRequest` — `allOf(AuthCredentialVerifyRequest, PasskeyCredentialVerifyRequestFields)`.
**Wire-up**
- `AuthCredentialVerifyRequestOneOf.yaml` discriminator map extended with `PASSKEY → PasskeyCredentialVerifyRequest`.
- PASSKEY example added on `POST /auth/credentials/{id}/verify`.
- Endpoint description updated to cover the PASSKEY path: client runs `navigator.credentials.get()` against a platform-backend-issued challenge and submits the assertion; Grid verifies the WebAuthn signature against the stored credential.
- 401 response description extended to cover passkey-specific failures (assertion signature / challenge / credential mismatch).
- `.stainless/stainless.yml` registers the three new schemas and extends the "remove allOf $ref to AuthCredentialVerifyRequest" transform target list to include `PasskeyCredentialVerifyRequest.allOf[0]`.
**Design notes**
- The PDF verify-body shape on p.7 omits an explicit `type` field, but every other branch in `AuthCredentialVerifyRequestOneOf` carries one and the discriminator requires it. PASSKEY is modeled consistently with EMAIL_OTP and OAUTH — `type: "PASSKEY"` is required on the request body.
- `assertion` is a structured object at the Grid API surface (not an opaque stamp string). WebAuthn signature verification reconstructs from the individual base64url-encoded fields, so structured + pass-through preserves byte integrity without forcing clients to JSON-encode the stamp themselves.
- `clientPublicKey` format matches EMAIL_OTP/OAUTH verify: P-256 uncompressed SEC1 hex (130 chars, 0x04-prefixed).
**Notes**
- Pairs with `04-21-feat_add_passkey_branch_to_auth_credential_create`; together they make passkey credentials usable end-to-end. The additional-credential challenge flow gets its own PASSKEY branch in the next PR.
- Bundled `openapi.yaml` and `mintlify/openapi.yaml` regenerated via `make build`.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
✱ Stainless preview buildsThis PR will update the kotlin openapi python typescript Edit this comment to update them. They will appear in their respective SDK's changelogs. ✅ grid-openapi studio · code · diff
✅ grid-typescript studio · code · diff
✅ grid-python studio · code · diff
✅ grid-kotlin studio · code · diff
This comment is auto-generated by GitHub Actions and is automatically kept up to date as you push. |

Adds the PASSKEY branch to
AuthCredentialVerifyRequestOneOf, completing the create + verify flow for WebAuthn-passkey-backed authentication credentials on Embedded Wallet internal accounts.Request shape
POST /auth/credentials/{id}/verifybody:{ type: "PASSKEY", assertion, clientPublicKey }→ 200AuthSession.{id}is theAuthMethod.idreturned fromPOST /auth/credentials.Schemas added
PasskeyAssertion—{ credentialId, clientDataJson, authenticatorData, signature, userHandle? }, all base64url-encoded strings. Shape mirrors the W3CAuthenticatorAssertionResponseplus the optionaluserHandle; pass-through to the downstream passkey provider.PasskeyCredentialVerifyRequestFields—{ type: "PASSKEY", assertion, clientPublicKey }(variant single-value enum ontype).PasskeyCredentialVerifyRequest—allOf(AuthCredentialVerifyRequest, PasskeyCredentialVerifyRequestFields).Wire-up
AuthCredentialVerifyRequestOneOf.yamldiscriminator map extended withPASSKEY → PasskeyCredentialVerifyRequest.POST /auth/credentials/{id}/verify.navigator.credentials.get()against a platform-backend-issued challenge and submits the assertion; Grid verifies the WebAuthn signature against the stored credential..stainless/stainless.ymlregisters the three new schemas and extends the "remove allOf $ref to AuthCredentialVerifyRequest" transform target list to includePasskeyCredentialVerifyRequest.allOf[0].Design notes
typefield, but every other branch inAuthCredentialVerifyRequestOneOfcarries one and the discriminator requires it. PASSKEY is modeled consistently with EMAIL_OTP and OAUTH —type: "PASSKEY"is required on the request body.assertionis a structured object at the Grid API surface (not an opaque stamp string). WebAuthn signature verification reconstructs from the individual base64url-encoded fields, so structured + pass-through preserves byte integrity without forcing clients to JSON-encode the stamp themselves.clientPublicKeyformat matches EMAIL_OTP/OAUTH verify: P-256 uncompressed SEC1 hex (130 chars, 0x04-prefixed).Notes
04-21-feat_add_passkey_branch_to_auth_credential_create; together they make passkey credentials usable end-to-end. The additional-credential challenge flow gets its own PASSKEY branch in the next PR.openapi.yamlandmintlify/openapi.yamlregenerated viamake build.