From b53b7c9ce060bb473de753dba66f5ab5ffb2a1ad Mon Sep 17 00:00:00 2001 From: Dhruv Pareek Date: Thu, 7 May 2026 15:45:05 -0700 Subject: [PATCH] Add passkey credentialId to auth challenge response --- mintlify/openapi.yaml | 11 ++++++----- openapi.yaml | 11 ++++++----- .../auth/AuthCredentialResponseOneOf.yaml | 7 ++++--- .../schemas/auth/PasskeyAuthChallenge.yaml | 15 +++++++-------- .../auth/auth_credentials_{id}_challenge.yaml | 19 +++++++++++-------- 5 files changed, 34 insertions(+), 29 deletions(-) diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml index b974a585..37b71608 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -4123,7 +4123,7 @@ paths: `OAUTH` credentials do not have a challenge step. To authenticate or reauthenticate an OAuth credential, call `POST /auth/credentials/{id}/verify` with a fresh OIDC token and a `clientPublicKey`. - For `PASSKEY` credentials, this issues a fresh Grid-generated WebAuthn challenge for reauthentication. The request body must carry the client's ephemeral `clientPublicKey` so Grid can bake it into the Turnkey session-creation payload the returned challenge is computed from — this seals the resulting session signing key to the client. The response is a `PasskeyAuthChallenge` — the base `AuthMethod` fields plus the new `challenge`, `requestId`, and `expiresAt`. The client passes the `challenge` into `navigator.credentials.get()` and submits the resulting assertion to `POST /auth/credentials/{id}/verify` with `Request-Id: ` to receive a session. + For `PASSKEY` credentials, this issues a fresh Grid-generated WebAuthn challenge for reauthentication. The request body must carry the client's ephemeral `clientPublicKey` so Grid can bake it into the Turnkey session-creation payload the returned challenge is computed from — this seals the resulting session signing key to the client. The response is a `PasskeyAuthChallenge` — the passkey auth method fields plus the WebAuthn `credentialId`, new `challenge`, `requestId`, and `expiresAt`. The client passes `credentialId` as `allowCredentials[].id` and `challenge` as the WebAuthn challenge in `navigator.credentials.get()`, then submits the resulting assertion to `POST /auth/credentials/{id}/verify` with `Request-Id: ` to receive a session. operationId: challengeAuthCredential tags: - Embedded Wallet Auth @@ -4153,7 +4153,7 @@ paths: value: {} responses: '200': - description: Challenge re-issued for the authentication credential. For `EMAIL_OTP` the body is a plain `AuthMethod` and a new OTP email has been sent. For `PASSKEY` the body is a `PasskeyAuthChallenge` carrying the freshly issued `challenge`, `requestId`, and `expiresAt` required to complete reauthentication via `POST /auth/credentials/{id}/verify`. + description: Challenge re-issued for the authentication credential. For `EMAIL_OTP` the body is a plain `AuthMethod` and a new OTP email has been sent. For `PASSKEY` the body is a `PasskeyAuthChallenge` carrying the passkey `credentialId`, freshly issued `challenge`, `requestId`, and `expiresAt` required to complete reauthentication via `POST /auth/credentials/{id}/verify`. content: application/json: schema: @@ -4174,6 +4174,7 @@ paths: id: AuthMethod:019542f5-b3e7-1d02-0000-000000000001 accountId: InternalAccount:019542f5-b3e7-1d02-0000-000000000002 type: PASSKEY + credentialId: KEbWNCc7NgaYnUyrNeFGX9_3Y-8oJ3KwzjnaiD1d1LVTxR7v3CaKfCz2Vy_g_MHSh7yJ8yL0Pxg6jo_o0hYiew nickname: iPhone Face-ID createdAt: '2026-04-08T15:30:01Z' updatedAt: '2026-04-08T15:35:00Z' @@ -15792,9 +15793,9 @@ components: example: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 PasskeyAuthChallenge: title: Passkey Auth Challenge - description: Extended `AuthMethod` shape returned for `PASSKEY` credentials from `POST /auth/credentials` (first-authentication case) and `POST /auth/credentials/{id}/challenge` (reauthentication case). Adds a Grid-issued `challenge`, the corresponding `requestId`, and the challenge's `expiresAt` to the base `AuthMethod` fields. The client signs the challenge with the passkey to produce the assertion submitted to `POST /auth/credentials/{id}/verify`. + description: Extended passkey auth method shape returned for `PASSKEY` credentials from `POST /auth/credentials/{id}/challenge`. Includes the WebAuthn `credentialId` needed to target the passkey, plus the Grid-issued `challenge`, corresponding `requestId`, and challenge `expiresAt`. The client signs the challenge with the passkey to produce the assertion submitted to `POST /auth/credentials/{id}/verify`. allOf: - - $ref: '#/components/schemas/AuthMethod' + - $ref: '#/components/schemas/PasskeyAuthMethod' - type: object required: - challenge @@ -15816,7 +15817,7 @@ components: example: '2026-04-08T15:35:00Z' AuthCredentialResponseOneOf: title: Auth Credential Response - description: Discriminated response shape returned from `POST /auth/credentials/{id}/challenge`. For `EMAIL_OTP` credentials the body is a plain `AuthMethod` (wrapped as `AuthMethodResponse` to disambiguate the oneOf). For `PASSKEY` credentials the body is a `PasskeyAuthChallenge` — the base `AuthMethod` fields plus the Grid-issued `challenge`, `requestId`, and `expiresAt` that drive the subsequent assertion. OAuth credentials do not use the challenge endpoint. Registration responses from `POST /auth/credentials` use the simpler `AuthMethodResponse` shape directly for all three credential types. + description: Discriminated response shape returned from `POST /auth/credentials/{id}/challenge`. For `EMAIL_OTP` credentials the body is a plain `AuthMethod` (wrapped as `AuthMethodResponse` to disambiguate the oneOf). For `PASSKEY` credentials the body is a `PasskeyAuthChallenge` — the passkey auth method fields plus the WebAuthn `credentialId`, Grid-issued `challenge`, `requestId`, and `expiresAt` that drive the subsequent assertion. OAuth credentials do not use the challenge endpoint. Registration responses from `POST /auth/credentials` use the simpler `AuthMethodResponse` shape directly for all three credential types. oneOf: - $ref: '#/components/schemas/AuthMethodResponse' - $ref: '#/components/schemas/PasskeyAuthChallenge' diff --git a/openapi.yaml b/openapi.yaml index b974a585..37b71608 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -4123,7 +4123,7 @@ paths: `OAUTH` credentials do not have a challenge step. To authenticate or reauthenticate an OAuth credential, call `POST /auth/credentials/{id}/verify` with a fresh OIDC token and a `clientPublicKey`. - For `PASSKEY` credentials, this issues a fresh Grid-generated WebAuthn challenge for reauthentication. The request body must carry the client's ephemeral `clientPublicKey` so Grid can bake it into the Turnkey session-creation payload the returned challenge is computed from — this seals the resulting session signing key to the client. The response is a `PasskeyAuthChallenge` — the base `AuthMethod` fields plus the new `challenge`, `requestId`, and `expiresAt`. The client passes the `challenge` into `navigator.credentials.get()` and submits the resulting assertion to `POST /auth/credentials/{id}/verify` with `Request-Id: ` to receive a session. + For `PASSKEY` credentials, this issues a fresh Grid-generated WebAuthn challenge for reauthentication. The request body must carry the client's ephemeral `clientPublicKey` so Grid can bake it into the Turnkey session-creation payload the returned challenge is computed from — this seals the resulting session signing key to the client. The response is a `PasskeyAuthChallenge` — the passkey auth method fields plus the WebAuthn `credentialId`, new `challenge`, `requestId`, and `expiresAt`. The client passes `credentialId` as `allowCredentials[].id` and `challenge` as the WebAuthn challenge in `navigator.credentials.get()`, then submits the resulting assertion to `POST /auth/credentials/{id}/verify` with `Request-Id: ` to receive a session. operationId: challengeAuthCredential tags: - Embedded Wallet Auth @@ -4153,7 +4153,7 @@ paths: value: {} responses: '200': - description: Challenge re-issued for the authentication credential. For `EMAIL_OTP` the body is a plain `AuthMethod` and a new OTP email has been sent. For `PASSKEY` the body is a `PasskeyAuthChallenge` carrying the freshly issued `challenge`, `requestId`, and `expiresAt` required to complete reauthentication via `POST /auth/credentials/{id}/verify`. + description: Challenge re-issued for the authentication credential. For `EMAIL_OTP` the body is a plain `AuthMethod` and a new OTP email has been sent. For `PASSKEY` the body is a `PasskeyAuthChallenge` carrying the passkey `credentialId`, freshly issued `challenge`, `requestId`, and `expiresAt` required to complete reauthentication via `POST /auth/credentials/{id}/verify`. content: application/json: schema: @@ -4174,6 +4174,7 @@ paths: id: AuthMethod:019542f5-b3e7-1d02-0000-000000000001 accountId: InternalAccount:019542f5-b3e7-1d02-0000-000000000002 type: PASSKEY + credentialId: KEbWNCc7NgaYnUyrNeFGX9_3Y-8oJ3KwzjnaiD1d1LVTxR7v3CaKfCz2Vy_g_MHSh7yJ8yL0Pxg6jo_o0hYiew nickname: iPhone Face-ID createdAt: '2026-04-08T15:30:01Z' updatedAt: '2026-04-08T15:35:00Z' @@ -15792,9 +15793,9 @@ components: example: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 PasskeyAuthChallenge: title: Passkey Auth Challenge - description: Extended `AuthMethod` shape returned for `PASSKEY` credentials from `POST /auth/credentials` (first-authentication case) and `POST /auth/credentials/{id}/challenge` (reauthentication case). Adds a Grid-issued `challenge`, the corresponding `requestId`, and the challenge's `expiresAt` to the base `AuthMethod` fields. The client signs the challenge with the passkey to produce the assertion submitted to `POST /auth/credentials/{id}/verify`. + description: Extended passkey auth method shape returned for `PASSKEY` credentials from `POST /auth/credentials/{id}/challenge`. Includes the WebAuthn `credentialId` needed to target the passkey, plus the Grid-issued `challenge`, corresponding `requestId`, and challenge `expiresAt`. The client signs the challenge with the passkey to produce the assertion submitted to `POST /auth/credentials/{id}/verify`. allOf: - - $ref: '#/components/schemas/AuthMethod' + - $ref: '#/components/schemas/PasskeyAuthMethod' - type: object required: - challenge @@ -15816,7 +15817,7 @@ components: example: '2026-04-08T15:35:00Z' AuthCredentialResponseOneOf: title: Auth Credential Response - description: Discriminated response shape returned from `POST /auth/credentials/{id}/challenge`. For `EMAIL_OTP` credentials the body is a plain `AuthMethod` (wrapped as `AuthMethodResponse` to disambiguate the oneOf). For `PASSKEY` credentials the body is a `PasskeyAuthChallenge` — the base `AuthMethod` fields plus the Grid-issued `challenge`, `requestId`, and `expiresAt` that drive the subsequent assertion. OAuth credentials do not use the challenge endpoint. Registration responses from `POST /auth/credentials` use the simpler `AuthMethodResponse` shape directly for all three credential types. + description: Discriminated response shape returned from `POST /auth/credentials/{id}/challenge`. For `EMAIL_OTP` credentials the body is a plain `AuthMethod` (wrapped as `AuthMethodResponse` to disambiguate the oneOf). For `PASSKEY` credentials the body is a `PasskeyAuthChallenge` — the passkey auth method fields plus the WebAuthn `credentialId`, Grid-issued `challenge`, `requestId`, and `expiresAt` that drive the subsequent assertion. OAuth credentials do not use the challenge endpoint. Registration responses from `POST /auth/credentials` use the simpler `AuthMethodResponse` shape directly for all three credential types. oneOf: - $ref: '#/components/schemas/AuthMethodResponse' - $ref: '#/components/schemas/PasskeyAuthChallenge' diff --git a/openapi/components/schemas/auth/AuthCredentialResponseOneOf.yaml b/openapi/components/schemas/auth/AuthCredentialResponseOneOf.yaml index 5c80aba3..21a0b8f6 100644 --- a/openapi/components/schemas/auth/AuthCredentialResponseOneOf.yaml +++ b/openapi/components/schemas/auth/AuthCredentialResponseOneOf.yaml @@ -4,9 +4,10 @@ description: >- `POST /auth/credentials/{id}/challenge`. For `EMAIL_OTP` credentials the body is a plain `AuthMethod` (wrapped as `AuthMethodResponse` to disambiguate the oneOf). For `PASSKEY` credentials the body is a - `PasskeyAuthChallenge` — the base `AuthMethod` fields plus the - Grid-issued `challenge`, `requestId`, and `expiresAt` that drive the - subsequent assertion. OAuth credentials do not use the challenge endpoint. + `PasskeyAuthChallenge` — the passkey auth method fields plus the + WebAuthn `credentialId`, Grid-issued `challenge`, `requestId`, and + `expiresAt` that drive the subsequent assertion. OAuth credentials do not + use the challenge endpoint. Registration responses from `POST /auth/credentials` use the simpler `AuthMethodResponse` shape directly for all three credential types. oneOf: diff --git a/openapi/components/schemas/auth/PasskeyAuthChallenge.yaml b/openapi/components/schemas/auth/PasskeyAuthChallenge.yaml index 500acd17..ce8b23e1 100644 --- a/openapi/components/schemas/auth/PasskeyAuthChallenge.yaml +++ b/openapi/components/schemas/auth/PasskeyAuthChallenge.yaml @@ -1,14 +1,13 @@ title: Passkey Auth Challenge description: >- - Extended `AuthMethod` shape returned for `PASSKEY` credentials from - `POST /auth/credentials` (first-authentication case) and - `POST /auth/credentials/{id}/challenge` (reauthentication case). Adds a - Grid-issued `challenge`, the corresponding `requestId`, and the - challenge's `expiresAt` to the base `AuthMethod` fields. The client signs - the challenge with the passkey to produce the assertion submitted to - `POST /auth/credentials/{id}/verify`. + Extended passkey auth method shape returned for `PASSKEY` credentials from + `POST /auth/credentials/{id}/challenge`. Includes the WebAuthn + `credentialId` needed to target the passkey, plus the Grid-issued + `challenge`, corresponding `requestId`, and challenge `expiresAt`. The + client signs the challenge with the passkey to produce the assertion + submitted to `POST /auth/credentials/{id}/verify`. allOf: - - $ref: ./AuthMethod.yaml + - $ref: ./PasskeyAuthMethod.yaml - type: object required: - challenge diff --git a/openapi/paths/auth/auth_credentials_{id}_challenge.yaml b/openapi/paths/auth/auth_credentials_{id}_challenge.yaml index 2d89c2f9..e537e4c2 100644 --- a/openapi/paths/auth/auth_credentials_{id}_challenge.yaml +++ b/openapi/paths/auth/auth_credentials_{id}_challenge.yaml @@ -23,11 +23,13 @@ post: client's ephemeral `clientPublicKey` so Grid can bake it into the Turnkey session-creation payload the returned challenge is computed from — this seals the resulting session signing key to the client. - The response is a `PasskeyAuthChallenge` — the base `AuthMethod` - fields plus the new `challenge`, `requestId`, and `expiresAt`. The - client passes the `challenge` into `navigator.credentials.get()` and - submits the resulting assertion to `POST /auth/credentials/{id}/verify` - with `Request-Id: ` to receive a session. + The response is a `PasskeyAuthChallenge` — the passkey auth method + fields plus the WebAuthn `credentialId`, new `challenge`, `requestId`, + and `expiresAt`. The client passes `credentialId` as + `allowCredentials[].id` and `challenge` as the WebAuthn challenge in + `navigator.credentials.get()`, then submits the resulting assertion to + `POST /auth/credentials/{id}/verify` with `Request-Id: ` to + receive a session. operationId: challengeAuthCredential tags: - Embedded Wallet Auth @@ -67,9 +69,9 @@ post: Challenge re-issued for the authentication credential. For `EMAIL_OTP` the body is a plain `AuthMethod` and a new OTP email has been sent. For `PASSKEY` the body is a `PasskeyAuthChallenge` - carrying the freshly issued `challenge`, `requestId`, and - `expiresAt` required to complete reauthentication via - `POST /auth/credentials/{id}/verify`. + carrying the passkey `credentialId`, freshly issued `challenge`, + `requestId`, and `expiresAt` required to complete reauthentication + via `POST /auth/credentials/{id}/verify`. content: application/json: schema: @@ -90,6 +92,7 @@ post: id: AuthMethod:019542f5-b3e7-1d02-0000-000000000001 accountId: InternalAccount:019542f5-b3e7-1d02-0000-000000000002 type: PASSKEY + credentialId: KEbWNCc7NgaYnUyrNeFGX9_3Y-8oJ3KwzjnaiD1d1LVTxR7v3CaKfCz2Vy_g_MHSh7yJ8yL0Pxg6jo_o0hYiew nickname: iPhone Face-ID createdAt: '2026-04-08T15:30:01Z' updatedAt: '2026-04-08T15:35:00Z'