From b7fc46c91f4b8d4f91ec2e1d337541667e1693e4 Mon Sep 17 00:00:00 2001 From: Dhruv Pareek Date: Thu, 7 May 2026 17:42:23 -0700 Subject: [PATCH 1/2] Add auth session refresh endpoints --- .stainless/stainless.yml | 9 + mintlify/openapi.yaml | 179 +++++++++++++++++- openapi.yaml | 179 +++++++++++++++++- .../components/schemas/auth/AuthSession.yaml | 14 +- .../auth/AuthSessionReauthRequest.yaml | 24 +++ openapi/openapi.yaml | 4 + .../auth/auth_sessions_{id}_challenge.yaml | 88 +++++++++ .../paths/auth/auth_sessions_{id}_verify.yaml | 108 +++++++++++ 8 files changed, 595 insertions(+), 10 deletions(-) create mode 100644 openapi/components/schemas/auth/AuthSessionReauthRequest.yaml create mode 100644 openapi/paths/auth/auth_sessions_{id}_challenge.yaml create mode 100644 openapi/paths/auth/auth_sessions_{id}_verify.yaml diff --git a/.stainless/stainless.yml b/.stainless/stainless.yml index 7345cc18..7cc44b6b 100644 --- a/.stainless/stainless.yml +++ b/.stainless/stainless.yml @@ -476,9 +476,18 @@ resources: list: endpoint: get /auth/sessions paginated: false + challenge: + endpoint: post /auth/sessions/{id}/challenge + body_param_name: AuthSessionReauthRequest + verify: + endpoint: post /auth/sessions/{id}/verify + body_param_name: AuthSessionReauthRequest delete: delete /auth/sessions/{id} models: session_list_response: '#/components/schemas/SessionListResponse' + auth_session_reauth_request: '#/components/schemas/AuthSessionReauthRequest' + auth_session: '#/components/schemas/AuthSession' + signed_request_challenge: "#/components/schemas/SignedRequestChallenge" agents: methods: diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml index bf6fdd7b..e6bf2c42 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -4437,6 +4437,167 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' + /auth/sessions/{id}/challenge: + post: + summary: Issue a session reauthentication challenge + description: | + Start mid-session reauthentication for an active Embedded Wallet auth session. + + Use this endpoint when a session is still active but close to expiry and the customer wants to extend access without re-running the underlying credential-specific authentication flow. Grid builds a Turnkey create-read-write-session payload, binds the supplied `clientPublicKey` into that payload, persists it as a pending request, and returns the canonical body as `payloadToSign`. + + The client signs `payloadToSign` with the current session signing key, then calls `POST /auth/sessions/{id}/verify` with `Grid-Wallet-Signature`, `Request-Id`, and the same `clientPublicKey`. If the original session has already expired, use the credential reauthentication flow instead. + operationId: challengeAuthSession + tags: + - Embedded Wallet Auth + security: + - BasicAuth: [] + parameters: + - name: id + in: path + description: The id of the active session to reauthenticate. + required: true + schema: + type: string + example: Session:019542f5-b3e7-1d02-0000-000000000003 + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AuthSessionReauthRequest' + examples: + reauth: + summary: Start mid-session reauthentication + value: + clientPublicKey: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 + responses: + '202': + description: Challenge issued. The response contains `payloadToSign` plus a `requestId`. Build an API-key stamp over `payloadToSign` with the current session API keypair, then echo `requestId` on `POST /auth/sessions/{id}/verify`. + content: + application/json: + schema: + $ref: '#/components/schemas/SignedRequestChallenge' + examples: + challenge: + summary: Session reauthentication challenge + value: + payloadToSign: '{"type":"ACTIVITY_TYPE_CREATE_READ_WRITE_SESSION_V2","timestampMs":"1746736509954","organizationId":"org_abc123","parameters":{"targetPublicKey":"04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2"}}' + requestId: Request:019542f5-b3e7-1d02-0000-000000000010 + expiresAt: '2026-04-08T15:35:00Z' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized. Returned when the `BasicAuth` credentials are missing or invalid, or when the target session is no longer active and cannot be used for mid-session reauthentication. + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Session not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /auth/sessions/{id}/verify: + post: + summary: Verify a session reauthentication challenge + description: | + Complete mid-session reauthentication for an active Embedded Wallet auth session and create a new session signing key. + + This is the signed retry for `POST /auth/sessions/{id}/challenge`. The request must include the full API-key stamp over the prior `payloadToSign` as `Grid-Wallet-Signature`, the challenge `requestId` as `Request-Id`, and the same `clientPublicKey` that was supplied on the challenge step. On success, Grid returns a new `AuthSession` with an `encryptedSessionSigningKey` sealed to that client public key. + + This endpoint requires the original session to still be active so it can authorize the refresh. If the session has already expired, use the credential reauthentication flow instead. + operationId: verifyAuthSession + tags: + - Embedded Wallet Auth + security: + - BasicAuth: [] + parameters: + - name: id + in: path + description: The id of the active session being reauthenticated. + required: true + schema: + type: string + example: Session:019542f5-b3e7-1d02-0000-000000000003 + - name: Grid-Wallet-Signature + in: header + required: true + description: Full API-key stamp built over the prior `payloadToSign` with the current session API keypair. + schema: + type: string + example: eyJwdWJsaWNLZXkiOiIwMmExYjIuLi4iLCJzaWduYXR1cmUiOiIzMDQ1MDIyMTAwLi4uIiwic2NoZW1lIjoiUDI1Nl9FQ0RTQV9TSEEyNTYifQ + - name: Request-Id + in: header + required: true + description: The `requestId` returned in the prior challenge response, echoed back so the server can correlate this signed retry with the issued challenge. + schema: + type: string + example: Request:019542f5-b3e7-1d02-0000-000000000010 + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AuthSessionReauthRequest' + examples: + reauth: + summary: Complete mid-session reauthentication + value: + clientPublicKey: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 + responses: + '201': + description: New authentication session created successfully. + content: + application/json: + schema: + $ref: '#/components/schemas/AuthSession' + examples: + session: + summary: Refreshed authentication session + value: + id: Session:019542f5-b3e7-1d02-0000-000000000011 + accountId: InternalAccount:019542f5-b3e7-1d02-0000-000000000002 + type: EMAIL_OTP + encryptedSessionSigningKey: w99a5xV6A75TfoAUkZn869fVyDYvgVsKrawMALZXmrauZd8hEv66EkPU1Z42CUaHESQjcA5bqd8dynTGBMLWB9ewtXWPEVbZvocB4Tw2K1vQVp7uwjf + nickname: example@lightspark.com + createdAt: '2026-04-08T15:30:01Z' + updatedAt: '2026-04-08T15:35:00Z' + expiresAt: '2026-04-08T15:50:00Z' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized. Returned when the provided `Grid-Wallet-Signature` is missing, malformed, or does not match the pending reauthentication challenge, when the `Request-Id` does not match an unexpired pending challenge, or when the retry's `clientPublicKey` does not match the one bound into `payloadToSign` on the challenge step. + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Session not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' /agents: post: summary: Create an agent @@ -15849,7 +16010,7 @@ components: PASSKEY: '#/components/schemas/PasskeyCredentialVerifyRequest' AuthSession: title: Authentication Session - description: An authentication session on an Embedded Wallet internal account. Returned from `GET /auth/sessions` (list) and `POST /auth/credentials/{id}/verify` (on credential verification). Only the verify response includes `encryptedSessionSigningKey` — it is delivered exactly once at the moment the session is issued and is never returned by the list endpoint. + description: An authentication session on an Embedded Wallet internal account. Returned from `GET /auth/sessions` (list) and `POST /auth/credentials/{id}/verify` (on credential verification) or `POST /auth/sessions/{id}/verify` (on mid-session reauthentication). Only the verify response includes `encryptedSessionSigningKey` — it is delivered exactly once at the moment the session is issued and is never returned by the list endpoint. allOf: - $ref: '#/components/schemas/AuthMethod' - type: object @@ -15866,7 +16027,7 @@ components: description: |- HPKE-encrypted session signing key, sealed to the `clientPublicKey` supplied on the verify request. Encoded as a base58check string: the decoded payload is a 33-byte compressed P-256 encapsulated public key followed by AES-256-GCM ciphertext. The client decrypts this key with its private key and uses it to sign subsequent Embedded Wallet requests until `expiresAt`. - Only returned from `POST /auth/credentials/{id}/verify` (where the session is first issued). Omitted from responses that simply surface existing sessions (e.g. `GET /auth/sessions`) — Grid does not retain the plaintext key after the client has decrypted it. + Only returned from session-issuing responses like `POST /auth/credentials/{id}/verify` and `POST /auth/sessions/{id}/verify`. Omitted from responses that simply surface existing sessions (e.g. `GET /auth/sessions`) — Grid does not retain the plaintext key after the client has decrypted it. example: w99a5xV6A75TfoAUkZn869fVyDYvgVsKrawMALZXmrauZd8hEv66EkPU1Z42CUaHESQjcA5bqd8dynTGBMLWB9ewtXWPEVbZvocB4Tw2K1vQVp7uwjf expiresAt: type: string @@ -15962,6 +16123,20 @@ components: description: List of active authentication sessions for the internal account. items: $ref: '#/components/schemas/AuthSession' + AuthSessionReauthRequest: + title: Auth Session Reauthentication Request + description: Request body for mid-session reauthentication. The `clientPublicKey` is required on both steps of the signed-retry flow. On the challenge step, Grid binds this key into the Turnkey session-creation payload returned as `payloadToSign`; on the verify step, the client echoes the same key back and Grid uses it to encrypt the newly issued session signing key. + type: object + required: + - clientPublicKey + properties: + clientPublicKey: + type: string + pattern: ^04[0-9a-fA-F]{128}$ + minLength: 130 + maxLength: 130 + description: Client-generated P-256 public key, hex-encoded in uncompressed SEC1 format (`04` prefix followed by the 32-byte X and 32-byte Y coordinates; 130 hex characters total). The matching private key must remain on the client. Grid binds this key into the session-creation payload on the challenge step and seals the returned `encryptedSessionSigningKey` to it on the verify step. + example: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 AgentPermission: type: string enum: diff --git a/openapi.yaml b/openapi.yaml index bf6fdd7b..e6bf2c42 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -4437,6 +4437,167 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' + /auth/sessions/{id}/challenge: + post: + summary: Issue a session reauthentication challenge + description: | + Start mid-session reauthentication for an active Embedded Wallet auth session. + + Use this endpoint when a session is still active but close to expiry and the customer wants to extend access without re-running the underlying credential-specific authentication flow. Grid builds a Turnkey create-read-write-session payload, binds the supplied `clientPublicKey` into that payload, persists it as a pending request, and returns the canonical body as `payloadToSign`. + + The client signs `payloadToSign` with the current session signing key, then calls `POST /auth/sessions/{id}/verify` with `Grid-Wallet-Signature`, `Request-Id`, and the same `clientPublicKey`. If the original session has already expired, use the credential reauthentication flow instead. + operationId: challengeAuthSession + tags: + - Embedded Wallet Auth + security: + - BasicAuth: [] + parameters: + - name: id + in: path + description: The id of the active session to reauthenticate. + required: true + schema: + type: string + example: Session:019542f5-b3e7-1d02-0000-000000000003 + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AuthSessionReauthRequest' + examples: + reauth: + summary: Start mid-session reauthentication + value: + clientPublicKey: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 + responses: + '202': + description: Challenge issued. The response contains `payloadToSign` plus a `requestId`. Build an API-key stamp over `payloadToSign` with the current session API keypair, then echo `requestId` on `POST /auth/sessions/{id}/verify`. + content: + application/json: + schema: + $ref: '#/components/schemas/SignedRequestChallenge' + examples: + challenge: + summary: Session reauthentication challenge + value: + payloadToSign: '{"type":"ACTIVITY_TYPE_CREATE_READ_WRITE_SESSION_V2","timestampMs":"1746736509954","organizationId":"org_abc123","parameters":{"targetPublicKey":"04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2"}}' + requestId: Request:019542f5-b3e7-1d02-0000-000000000010 + expiresAt: '2026-04-08T15:35:00Z' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized. Returned when the `BasicAuth` credentials are missing or invalid, or when the target session is no longer active and cannot be used for mid-session reauthentication. + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Session not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /auth/sessions/{id}/verify: + post: + summary: Verify a session reauthentication challenge + description: | + Complete mid-session reauthentication for an active Embedded Wallet auth session and create a new session signing key. + + This is the signed retry for `POST /auth/sessions/{id}/challenge`. The request must include the full API-key stamp over the prior `payloadToSign` as `Grid-Wallet-Signature`, the challenge `requestId` as `Request-Id`, and the same `clientPublicKey` that was supplied on the challenge step. On success, Grid returns a new `AuthSession` with an `encryptedSessionSigningKey` sealed to that client public key. + + This endpoint requires the original session to still be active so it can authorize the refresh. If the session has already expired, use the credential reauthentication flow instead. + operationId: verifyAuthSession + tags: + - Embedded Wallet Auth + security: + - BasicAuth: [] + parameters: + - name: id + in: path + description: The id of the active session being reauthenticated. + required: true + schema: + type: string + example: Session:019542f5-b3e7-1d02-0000-000000000003 + - name: Grid-Wallet-Signature + in: header + required: true + description: Full API-key stamp built over the prior `payloadToSign` with the current session API keypair. + schema: + type: string + example: eyJwdWJsaWNLZXkiOiIwMmExYjIuLi4iLCJzaWduYXR1cmUiOiIzMDQ1MDIyMTAwLi4uIiwic2NoZW1lIjoiUDI1Nl9FQ0RTQV9TSEEyNTYifQ + - name: Request-Id + in: header + required: true + description: The `requestId` returned in the prior challenge response, echoed back so the server can correlate this signed retry with the issued challenge. + schema: + type: string + example: Request:019542f5-b3e7-1d02-0000-000000000010 + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AuthSessionReauthRequest' + examples: + reauth: + summary: Complete mid-session reauthentication + value: + clientPublicKey: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 + responses: + '201': + description: New authentication session created successfully. + content: + application/json: + schema: + $ref: '#/components/schemas/AuthSession' + examples: + session: + summary: Refreshed authentication session + value: + id: Session:019542f5-b3e7-1d02-0000-000000000011 + accountId: InternalAccount:019542f5-b3e7-1d02-0000-000000000002 + type: EMAIL_OTP + encryptedSessionSigningKey: w99a5xV6A75TfoAUkZn869fVyDYvgVsKrawMALZXmrauZd8hEv66EkPU1Z42CUaHESQjcA5bqd8dynTGBMLWB9ewtXWPEVbZvocB4Tw2K1vQVp7uwjf + nickname: example@lightspark.com + createdAt: '2026-04-08T15:30:01Z' + updatedAt: '2026-04-08T15:35:00Z' + expiresAt: '2026-04-08T15:50:00Z' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized. Returned when the provided `Grid-Wallet-Signature` is missing, malformed, or does not match the pending reauthentication challenge, when the `Request-Id` does not match an unexpired pending challenge, or when the retry's `clientPublicKey` does not match the one bound into `payloadToSign` on the challenge step. + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Session not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' /agents: post: summary: Create an agent @@ -15849,7 +16010,7 @@ components: PASSKEY: '#/components/schemas/PasskeyCredentialVerifyRequest' AuthSession: title: Authentication Session - description: An authentication session on an Embedded Wallet internal account. Returned from `GET /auth/sessions` (list) and `POST /auth/credentials/{id}/verify` (on credential verification). Only the verify response includes `encryptedSessionSigningKey` — it is delivered exactly once at the moment the session is issued and is never returned by the list endpoint. + description: An authentication session on an Embedded Wallet internal account. Returned from `GET /auth/sessions` (list) and `POST /auth/credentials/{id}/verify` (on credential verification) or `POST /auth/sessions/{id}/verify` (on mid-session reauthentication). Only the verify response includes `encryptedSessionSigningKey` — it is delivered exactly once at the moment the session is issued and is never returned by the list endpoint. allOf: - $ref: '#/components/schemas/AuthMethod' - type: object @@ -15866,7 +16027,7 @@ components: description: |- HPKE-encrypted session signing key, sealed to the `clientPublicKey` supplied on the verify request. Encoded as a base58check string: the decoded payload is a 33-byte compressed P-256 encapsulated public key followed by AES-256-GCM ciphertext. The client decrypts this key with its private key and uses it to sign subsequent Embedded Wallet requests until `expiresAt`. - Only returned from `POST /auth/credentials/{id}/verify` (where the session is first issued). Omitted from responses that simply surface existing sessions (e.g. `GET /auth/sessions`) — Grid does not retain the plaintext key after the client has decrypted it. + Only returned from session-issuing responses like `POST /auth/credentials/{id}/verify` and `POST /auth/sessions/{id}/verify`. Omitted from responses that simply surface existing sessions (e.g. `GET /auth/sessions`) — Grid does not retain the plaintext key after the client has decrypted it. example: w99a5xV6A75TfoAUkZn869fVyDYvgVsKrawMALZXmrauZd8hEv66EkPU1Z42CUaHESQjcA5bqd8dynTGBMLWB9ewtXWPEVbZvocB4Tw2K1vQVp7uwjf expiresAt: type: string @@ -15962,6 +16123,20 @@ components: description: List of active authentication sessions for the internal account. items: $ref: '#/components/schemas/AuthSession' + AuthSessionReauthRequest: + title: Auth Session Reauthentication Request + description: Request body for mid-session reauthentication. The `clientPublicKey` is required on both steps of the signed-retry flow. On the challenge step, Grid binds this key into the Turnkey session-creation payload returned as `payloadToSign`; on the verify step, the client echoes the same key back and Grid uses it to encrypt the newly issued session signing key. + type: object + required: + - clientPublicKey + properties: + clientPublicKey: + type: string + pattern: ^04[0-9a-fA-F]{128}$ + minLength: 130 + maxLength: 130 + description: Client-generated P-256 public key, hex-encoded in uncompressed SEC1 format (`04` prefix followed by the 32-byte X and 32-byte Y coordinates; 130 hex characters total). The matching private key must remain on the client. Grid binds this key into the session-creation payload on the challenge step and seals the returned `encryptedSessionSigningKey` to it on the verify step. + example: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 AgentPermission: type: string enum: diff --git a/openapi/components/schemas/auth/AuthSession.yaml b/openapi/components/schemas/auth/AuthSession.yaml index 9c58bb75..061f545c 100644 --- a/openapi/components/schemas/auth/AuthSession.yaml +++ b/openapi/components/schemas/auth/AuthSession.yaml @@ -2,7 +2,8 @@ title: Authentication Session description: >- An authentication session on an Embedded Wallet internal account. Returned from `GET /auth/sessions` (list) and - `POST /auth/credentials/{id}/verify` (on credential verification). + `POST /auth/credentials/{id}/verify` (on credential verification) or + `POST /auth/sessions/{id}/verify` (on mid-session reauthentication). Only the verify response includes `encryptedSessionSigningKey` — it is delivered exactly once at the moment the session is issued and is never returned by the list endpoint. @@ -34,11 +35,12 @@ allOf: Wallet requests until `expiresAt`. - Only returned from `POST /auth/credentials/{id}/verify` - (where the session is first issued). Omitted from responses - that simply surface existing sessions (e.g. - `GET /auth/sessions`) — Grid does not retain the plaintext - key after the client has decrypted it. + Only returned from session-issuing responses like + `POST /auth/credentials/{id}/verify` and + `POST /auth/sessions/{id}/verify`. Omitted from responses that + simply surface existing sessions (e.g. `GET /auth/sessions`) — + Grid does not retain the plaintext key after the client has + decrypted it. example: w99a5xV6A75TfoAUkZn869fVyDYvgVsKrawMALZXmrauZd8hEv66EkPU1Z42CUaHESQjcA5bqd8dynTGBMLWB9ewtXWPEVbZvocB4Tw2K1vQVp7uwjf expiresAt: type: string diff --git a/openapi/components/schemas/auth/AuthSessionReauthRequest.yaml b/openapi/components/schemas/auth/AuthSessionReauthRequest.yaml new file mode 100644 index 00000000..65e7abd4 --- /dev/null +++ b/openapi/components/schemas/auth/AuthSessionReauthRequest.yaml @@ -0,0 +1,24 @@ +title: Auth Session Reauthentication Request +description: >- + Request body for mid-session reauthentication. The `clientPublicKey` is + required on both steps of the signed-retry flow. On the challenge step, Grid + binds this key into the Turnkey session-creation payload returned as + `payloadToSign`; on the verify step, the client echoes the same key back and + Grid uses it to encrypt the newly issued session signing key. +type: object +required: + - clientPublicKey +properties: + clientPublicKey: + type: string + pattern: "^04[0-9a-fA-F]{128}$" + minLength: 130 + maxLength: 130 + description: >- + Client-generated P-256 public key, hex-encoded in uncompressed SEC1 + format (`04` prefix followed by the 32-byte X and 32-byte Y coordinates; + 130 hex characters total). The matching private key must remain on the + client. Grid binds this key into the session-creation payload on the + challenge step and seals the returned `encryptedSessionSigningKey` to it + on the verify step. + example: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index 771b4131..a232a908 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -213,6 +213,10 @@ paths: $ref: paths/auth/auth_sessions.yaml /auth/sessions/{id}: $ref: paths/auth/auth_sessions_{id}.yaml + /auth/sessions/{id}/challenge: + $ref: paths/auth/auth_sessions_{id}_challenge.yaml + /auth/sessions/{id}/verify: + $ref: paths/auth/auth_sessions_{id}_verify.yaml /agents: $ref: paths/agents/agents.yaml /agents/approvals: diff --git a/openapi/paths/auth/auth_sessions_{id}_challenge.yaml b/openapi/paths/auth/auth_sessions_{id}_challenge.yaml new file mode 100644 index 00000000..50c981e1 --- /dev/null +++ b/openapi/paths/auth/auth_sessions_{id}_challenge.yaml @@ -0,0 +1,88 @@ +post: + summary: Issue a session reauthentication challenge + description: > + Start mid-session reauthentication for an active Embedded Wallet auth + session. + + + Use this endpoint when a session is still active but close to expiry and + the customer wants to extend access without re-running the underlying + credential-specific authentication flow. Grid builds a Turnkey + create-read-write-session payload, binds the supplied `clientPublicKey` into + that payload, persists it as a pending request, and returns the canonical + body as `payloadToSign`. + + + The client signs `payloadToSign` with the current session signing key, then + calls `POST /auth/sessions/{id}/verify` with `Grid-Wallet-Signature`, + `Request-Id`, and the same `clientPublicKey`. If the original session has + already expired, use the credential reauthentication flow instead. + operationId: challengeAuthSession + tags: + - Embedded Wallet Auth + security: + - BasicAuth: [] + parameters: + - name: id + in: path + description: The id of the active session to reauthenticate. + required: true + schema: + type: string + example: Session:019542f5-b3e7-1d02-0000-000000000003 + requestBody: + required: true + content: + application/json: + schema: + $ref: ../../components/schemas/auth/AuthSessionReauthRequest.yaml + examples: + reauth: + summary: Start mid-session reauthentication + value: + clientPublicKey: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 + responses: + '202': + description: >- + Challenge issued. The response contains `payloadToSign` plus a + `requestId`. Build an API-key stamp over `payloadToSign` with the + current session API keypair, then echo `requestId` on + `POST /auth/sessions/{id}/verify`. + content: + application/json: + schema: + $ref: ../../components/schemas/common/SignedRequestChallenge.yaml + examples: + challenge: + summary: Session reauthentication challenge + value: + payloadToSign: '{"type":"ACTIVITY_TYPE_CREATE_READ_WRITE_SESSION_V2","timestampMs":"1746736509954","organizationId":"org_abc123","parameters":{"targetPublicKey":"04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2"}}' + requestId: Request:019542f5-b3e7-1d02-0000-000000000010 + expiresAt: '2026-04-08T15:35:00Z' + '400': + description: Bad request + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error400.yaml + '401': + description: >- + Unauthorized. Returned when the `BasicAuth` credentials are missing or + invalid, or when the target session is no longer active and cannot be + used for mid-session reauthentication. + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '404': + description: Session not found + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error404.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml diff --git a/openapi/paths/auth/auth_sessions_{id}_verify.yaml b/openapi/paths/auth/auth_sessions_{id}_verify.yaml new file mode 100644 index 00000000..9d0a3d16 --- /dev/null +++ b/openapi/paths/auth/auth_sessions_{id}_verify.yaml @@ -0,0 +1,108 @@ +post: + summary: Verify a session reauthentication challenge + description: > + Complete mid-session reauthentication for an active Embedded Wallet auth + session and create a new session signing key. + + + This is the signed retry for `POST /auth/sessions/{id}/challenge`. The + request must include the full API-key stamp over the prior `payloadToSign` + as `Grid-Wallet-Signature`, the challenge `requestId` as `Request-Id`, and + the same `clientPublicKey` that was supplied on the challenge step. On + success, Grid returns a new `AuthSession` with an + `encryptedSessionSigningKey` sealed to that client public key. + + + This endpoint requires the original session to still be active so it can + authorize the refresh. If the session has already expired, use the + credential reauthentication flow instead. + operationId: verifyAuthSession + tags: + - Embedded Wallet Auth + security: + - BasicAuth: [] + parameters: + - name: id + in: path + description: The id of the active session being reauthenticated. + required: true + schema: + type: string + example: Session:019542f5-b3e7-1d02-0000-000000000003 + - name: Grid-Wallet-Signature + in: header + required: true + description: >- + Full API-key stamp built over the prior `payloadToSign` with the current + session API keypair. + schema: + type: string + example: eyJwdWJsaWNLZXkiOiIwMmExYjIuLi4iLCJzaWduYXR1cmUiOiIzMDQ1MDIyMTAwLi4uIiwic2NoZW1lIjoiUDI1Nl9FQ0RTQV9TSEEyNTYifQ + - name: Request-Id + in: header + required: true + description: >- + The `requestId` returned in the prior challenge response, echoed back so + the server can correlate this signed retry with the issued challenge. + schema: + type: string + example: Request:019542f5-b3e7-1d02-0000-000000000010 + requestBody: + required: true + content: + application/json: + schema: + $ref: ../../components/schemas/auth/AuthSessionReauthRequest.yaml + examples: + reauth: + summary: Complete mid-session reauthentication + value: + clientPublicKey: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 + responses: + '201': + description: New authentication session created successfully. + content: + application/json: + schema: + $ref: ../../components/schemas/auth/AuthSession.yaml + examples: + session: + summary: Refreshed authentication session + value: + id: Session:019542f5-b3e7-1d02-0000-000000000011 + accountId: InternalAccount:019542f5-b3e7-1d02-0000-000000000002 + type: EMAIL_OTP + encryptedSessionSigningKey: w99a5xV6A75TfoAUkZn869fVyDYvgVsKrawMALZXmrauZd8hEv66EkPU1Z42CUaHESQjcA5bqd8dynTGBMLWB9ewtXWPEVbZvocB4Tw2K1vQVp7uwjf + nickname: example@lightspark.com + createdAt: '2026-04-08T15:30:01Z' + updatedAt: '2026-04-08T15:35:00Z' + expiresAt: '2026-04-08T15:50:00Z' + '400': + description: Bad request + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error400.yaml + '401': + description: >- + Unauthorized. Returned when the provided `Grid-Wallet-Signature` is + missing, malformed, or does not match the pending reauthentication + challenge, when the `Request-Id` does not match an unexpired pending + challenge, or when the retry's `clientPublicKey` does not match the one + bound into `payloadToSign` on the challenge step. + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '404': + description: Session not found + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error404.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml From d56500e31286d9f74e63a00a953354eb886dc5c5 Mon Sep 17 00:00:00 2001 From: Dhruv Pareek Date: Mon, 11 May 2026 17:47:38 -0700 Subject: [PATCH 2/2] Use single auth session refresh endpoint --- .stainless/stainless.yml | 11 +- mintlify/openapi.yaml | 132 +++++------------ openapi.yaml | 132 +++++------------ .../components/schemas/auth/AuthSession.yaml | 13 +- ...st.yaml => AuthSessionRefreshRequest.yaml} | 18 ++- .../common/SignedRequestChallenge.yaml | 5 +- openapi/openapi.yaml | 6 +- .../auth/auth_sessions_{id}_challenge.yaml | 88 ------------ .../auth/auth_sessions_{id}_refresh.yaml | 136 ++++++++++++++++++ .../paths/auth/auth_sessions_{id}_verify.yaml | 108 -------------- 10 files changed, 234 insertions(+), 415 deletions(-) rename openapi/components/schemas/auth/{AuthSessionReauthRequest.yaml => AuthSessionRefreshRequest.yaml} (52%) delete mode 100644 openapi/paths/auth/auth_sessions_{id}_challenge.yaml create mode 100644 openapi/paths/auth/auth_sessions_{id}_refresh.yaml delete mode 100644 openapi/paths/auth/auth_sessions_{id}_verify.yaml diff --git a/.stainless/stainless.yml b/.stainless/stainless.yml index 7cc44b6b..600cd81e 100644 --- a/.stainless/stainless.yml +++ b/.stainless/stainless.yml @@ -476,16 +476,13 @@ resources: list: endpoint: get /auth/sessions paginated: false - challenge: - endpoint: post /auth/sessions/{id}/challenge - body_param_name: AuthSessionReauthRequest - verify: - endpoint: post /auth/sessions/{id}/verify - body_param_name: AuthSessionReauthRequest + refresh: + endpoint: post /auth/sessions/{id}/refresh + body_param_name: AuthSessionRefreshRequest delete: delete /auth/sessions/{id} models: session_list_response: '#/components/schemas/SessionListResponse' - auth_session_reauth_request: '#/components/schemas/AuthSessionReauthRequest' + auth_session_refresh_request: '#/components/schemas/AuthSessionRefreshRequest' auth_session: '#/components/schemas/AuthSession' signed_request_challenge: "#/components/schemas/SignedRequestChallenge" diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml index e6bf2c42..a2c5f0dc 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -4437,87 +4437,18 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' - /auth/sessions/{id}/challenge: + /auth/sessions/{id}/refresh: post: - summary: Issue a session reauthentication challenge + summary: Refresh an authentication session description: | - Start mid-session reauthentication for an active Embedded Wallet auth session. + Refresh an active Embedded Wallet auth session and create a new session signing key. Session refresh is a two-step signed-retry flow: - Use this endpoint when a session is still active but close to expiry and the customer wants to extend access without re-running the underlying credential-specific authentication flow. Grid builds a Turnkey create-read-write-session payload, binds the supplied `clientPublicKey` into that payload, persists it as a pending request, and returns the canonical body as `payloadToSign`. + 1. Call `POST /auth/sessions/{id}/refresh` with the request body `{ "clientPublicKey": "04..." }` and no signature headers. Grid builds a Turnkey create-read-write-session payload, binds the supplied `clientPublicKey` into that payload, persists it as a pending request, and returns `202` with `payloadToSign`, `requestId`, and `expiresAt`. - The client signs `payloadToSign` with the current session signing key, then calls `POST /auth/sessions/{id}/verify` with `Grid-Wallet-Signature`, `Request-Id`, and the same `clientPublicKey`. If the original session has already expired, use the credential reauthentication flow instead. - operationId: challengeAuthSession - tags: - - Embedded Wallet Auth - security: - - BasicAuth: [] - parameters: - - name: id - in: path - description: The id of the active session to reauthenticate. - required: true - schema: - type: string - example: Session:019542f5-b3e7-1d02-0000-000000000003 - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/AuthSessionReauthRequest' - examples: - reauth: - summary: Start mid-session reauthentication - value: - clientPublicKey: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 - responses: - '202': - description: Challenge issued. The response contains `payloadToSign` plus a `requestId`. Build an API-key stamp over `payloadToSign` with the current session API keypair, then echo `requestId` on `POST /auth/sessions/{id}/verify`. - content: - application/json: - schema: - $ref: '#/components/schemas/SignedRequestChallenge' - examples: - challenge: - summary: Session reauthentication challenge - value: - payloadToSign: '{"type":"ACTIVITY_TYPE_CREATE_READ_WRITE_SESSION_V2","timestampMs":"1746736509954","organizationId":"org_abc123","parameters":{"targetPublicKey":"04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2"}}' - requestId: Request:019542f5-b3e7-1d02-0000-000000000010 - expiresAt: '2026-04-08T15:35:00Z' - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/Error400' - '401': - description: Unauthorized. Returned when the `BasicAuth` credentials are missing or invalid, or when the target session is no longer active and cannot be used for mid-session reauthentication. - content: - application/json: - schema: - $ref: '#/components/schemas/Error401' - '404': - description: Session not found - content: - application/json: - schema: - $ref: '#/components/schemas/Error404' - '500': - description: Internal service error - content: - application/json: - schema: - $ref: '#/components/schemas/Error500' - /auth/sessions/{id}/verify: - post: - summary: Verify a session reauthentication challenge - description: | - Complete mid-session reauthentication for an active Embedded Wallet auth session and create a new session signing key. + 2. Sign `payloadToSign` with the current session signing key, then retry the same request with the full API-key stamp as `Grid-Wallet-Signature`, the `requestId` echoed back as `Request-Id`, and the same `clientPublicKey` in the request body. On success, Grid returns a new `AuthSession` with an `encryptedSessionSigningKey` sealed to that client public key. - This is the signed retry for `POST /auth/sessions/{id}/challenge`. The request must include the full API-key stamp over the prior `payloadToSign` as `Grid-Wallet-Signature`, the challenge `requestId` as `Request-Id`, and the same `clientPublicKey` that was supplied on the challenge step. On success, Grid returns a new `AuthSession` with an `encryptedSessionSigningKey` sealed to that client public key. - - This endpoint requires the original session to still be active so it can authorize the refresh. If the session has already expired, use the credential reauthentication flow instead. - operationId: verifyAuthSession + The original session must still be active on both steps so it can authorize the refresh. If the session has already expired, use the credential reauthentication flow instead. + operationId: refreshAuthSession tags: - Embedded Wallet Auth security: @@ -4525,22 +4456,22 @@ paths: parameters: - name: id in: path - description: The id of the active session being reauthenticated. + description: The id of the active session to refresh. required: true schema: type: string example: Session:019542f5-b3e7-1d02-0000-000000000003 - name: Grid-Wallet-Signature in: header - required: true - description: Full API-key stamp built over the prior `payloadToSign` with the current session API keypair. + required: false + description: Full API-key stamp built over the prior `payloadToSign` with the current session API keypair. Required on the signed retry; ignored on the initial call. schema: type: string example: eyJwdWJsaWNLZXkiOiIwMmExYjIuLi4iLCJzaWduYXR1cmUiOiIzMDQ1MDIyMTAwLi4uIiwic2NoZW1lIjoiUDI1Nl9FQ0RTQV9TSEEyNTYifQ - name: Request-Id in: header - required: true - description: The `requestId` returned in the prior challenge response, echoed back so the server can correlate this signed retry with the issued challenge. + required: false + description: The `requestId` returned in the prior `202` response, echoed back on the signed retry so the server can correlate it with the issued challenge. Required on the signed retry; must be paired with `Grid-Wallet-Signature`. schema: type: string example: Request:019542f5-b3e7-1d02-0000-000000000010 @@ -4549,10 +4480,10 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/AuthSessionReauthRequest' + $ref: '#/components/schemas/AuthSessionRefreshRequest' examples: - reauth: - summary: Complete mid-session reauthentication + refresh: + summary: Refresh an active session value: clientPublicKey: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 responses: @@ -4574,6 +4505,19 @@ paths: createdAt: '2026-04-08T15:30:01Z' updatedAt: '2026-04-08T15:35:00Z' expiresAt: '2026-04-08T15:50:00Z' + '202': + description: Challenge issued. The response contains `payloadToSign` plus a `requestId`. Build an API-key stamp over `payloadToSign` with the current session API keypair, then echo `requestId` on the signed retry. + content: + application/json: + schema: + $ref: '#/components/schemas/SignedRequestChallenge' + examples: + challenge: + summary: Session refresh challenge + value: + payloadToSign: '{"type":"ACTIVITY_TYPE_CREATE_READ_WRITE_SESSION_V2","timestampMs":"1746736509954","organizationId":"org_abc123","parameters":{"targetPublicKey":"04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2"}}' + requestId: Request:019542f5-b3e7-1d02-0000-000000000010 + expiresAt: '2026-04-08T15:35:00Z' '400': description: Bad request content: @@ -4581,7 +4525,7 @@ paths: schema: $ref: '#/components/schemas/Error400' '401': - description: Unauthorized. Returned when the provided `Grid-Wallet-Signature` is missing, malformed, or does not match the pending reauthentication challenge, when the `Request-Id` does not match an unexpired pending challenge, or when the retry's `clientPublicKey` does not match the one bound into `payloadToSign` on the challenge step. + description: Unauthorized. Returned when the `BasicAuth` credentials are missing or invalid, when the target session is no longer active and cannot be used for refresh, when the signed retry omits `Grid-Wallet-Signature`, when the provided signature is malformed or does not match the pending refresh challenge, when the `Request-Id` does not match an unexpired pending challenge, or when the retry's `clientPublicKey` does not match the one bound into `payloadToSign` on the initial call. content: application/json: schema: @@ -15671,7 +15615,7 @@ components: - payloadToSign - requestId - expiresAt - description: Common base for two-step signed-retry challenge responses on Embedded Wallet endpoints (credential revocation, session revocation, wallet export, and similar). Holds the signing fields shared across every challenge shape; each variant composes this base via `allOf` and adds its own resource `id` (and `type`, when applicable) with variant-specific description and example. + description: Common base for two-step signed-retry challenge responses on Embedded Wallet endpoints (credential registration or revocation, session refresh or revocation, wallet export, and similar). Holds the signing fields shared across every challenge shape; each variant composes this base via `allOf` and adds its own resource `id` (and `type`, when applicable) with variant-specific description and example. properties: payloadToSign: type: string @@ -16010,7 +15954,7 @@ components: PASSKEY: '#/components/schemas/PasskeyCredentialVerifyRequest' AuthSession: title: Authentication Session - description: An authentication session on an Embedded Wallet internal account. Returned from `GET /auth/sessions` (list) and `POST /auth/credentials/{id}/verify` (on credential verification) or `POST /auth/sessions/{id}/verify` (on mid-session reauthentication). Only the verify response includes `encryptedSessionSigningKey` — it is delivered exactly once at the moment the session is issued and is never returned by the list endpoint. + description: An authentication session on an Embedded Wallet internal account. Returned from `GET /auth/sessions` (list) and `POST /auth/credentials/{id}/verify` (on credential verification) or `POST /auth/sessions/{id}/refresh` (on mid-session refresh). Only session-issuing responses include `encryptedSessionSigningKey` — it is delivered exactly once at the moment the session is issued and is never returned by the list endpoint. allOf: - $ref: '#/components/schemas/AuthMethod' - type: object @@ -16025,9 +15969,9 @@ components: encryptedSessionSigningKey: type: string description: |- - HPKE-encrypted session signing key, sealed to the `clientPublicKey` supplied on the verify request. Encoded as a base58check string: the decoded payload is a 33-byte compressed P-256 encapsulated public key followed by AES-256-GCM ciphertext. The client decrypts this key with its private key and uses it to sign subsequent Embedded Wallet requests until `expiresAt`. + HPKE-encrypted session signing key, sealed to the `clientPublicKey` supplied on the verification or refresh request. Encoded as a base58check string: the decoded payload is a 33-byte compressed P-256 encapsulated public key followed by AES-256-GCM ciphertext. The client decrypts this key with its private key and uses it to sign subsequent Embedded Wallet requests until `expiresAt`. - Only returned from session-issuing responses like `POST /auth/credentials/{id}/verify` and `POST /auth/sessions/{id}/verify`. Omitted from responses that simply surface existing sessions (e.g. `GET /auth/sessions`) — Grid does not retain the plaintext key after the client has decrypted it. + Only returned from session-issuing responses like `POST /auth/credentials/{id}/verify` and `POST /auth/sessions/{id}/refresh`. Omitted from responses that simply surface existing sessions (e.g. `GET /auth/sessions`) — Grid does not retain the plaintext key after the client has decrypted it. example: w99a5xV6A75TfoAUkZn869fVyDYvgVsKrawMALZXmrauZd8hEv66EkPU1Z42CUaHESQjcA5bqd8dynTGBMLWB9ewtXWPEVbZvocB4Tw2K1vQVp7uwjf expiresAt: type: string @@ -16123,9 +16067,9 @@ components: description: List of active authentication sessions for the internal account. items: $ref: '#/components/schemas/AuthSession' - AuthSessionReauthRequest: - title: Auth Session Reauthentication Request - description: Request body for mid-session reauthentication. The `clientPublicKey` is required on both steps of the signed-retry flow. On the challenge step, Grid binds this key into the Turnkey session-creation payload returned as `payloadToSign`; on the verify step, the client echoes the same key back and Grid uses it to encrypt the newly issued session signing key. + AuthSessionRefreshRequest: + title: Auth Session Refresh Request + description: Request body for refreshing an active authentication session. The `clientPublicKey` is required on both steps of the signed-retry flow. On the initial call, Grid binds this key into the Turnkey session-creation payload returned as `payloadToSign`; on the signed retry, the client echoes the same key back and Grid uses it to encrypt the newly issued session signing key. type: object required: - clientPublicKey @@ -16133,9 +16077,7 @@ components: clientPublicKey: type: string pattern: ^04[0-9a-fA-F]{128}$ - minLength: 130 - maxLength: 130 - description: Client-generated P-256 public key, hex-encoded in uncompressed SEC1 format (`04` prefix followed by the 32-byte X and 32-byte Y coordinates; 130 hex characters total). The matching private key must remain on the client. Grid binds this key into the session-creation payload on the challenge step and seals the returned `encryptedSessionSigningKey` to it on the verify step. + description: Client-generated P-256 public key, hex-encoded in uncompressed SEC1 format (`04` prefix followed by the 32-byte X and 32-byte Y coordinates; 130 hex characters total). The matching private key must remain on the client. Grid binds this key into the session-creation payload on the initial call and seals the returned `encryptedSessionSigningKey` to it on the signed retry. example: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 AgentPermission: type: string diff --git a/openapi.yaml b/openapi.yaml index e6bf2c42..a2c5f0dc 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -4437,87 +4437,18 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' - /auth/sessions/{id}/challenge: + /auth/sessions/{id}/refresh: post: - summary: Issue a session reauthentication challenge + summary: Refresh an authentication session description: | - Start mid-session reauthentication for an active Embedded Wallet auth session. + Refresh an active Embedded Wallet auth session and create a new session signing key. Session refresh is a two-step signed-retry flow: - Use this endpoint when a session is still active but close to expiry and the customer wants to extend access without re-running the underlying credential-specific authentication flow. Grid builds a Turnkey create-read-write-session payload, binds the supplied `clientPublicKey` into that payload, persists it as a pending request, and returns the canonical body as `payloadToSign`. + 1. Call `POST /auth/sessions/{id}/refresh` with the request body `{ "clientPublicKey": "04..." }` and no signature headers. Grid builds a Turnkey create-read-write-session payload, binds the supplied `clientPublicKey` into that payload, persists it as a pending request, and returns `202` with `payloadToSign`, `requestId`, and `expiresAt`. - The client signs `payloadToSign` with the current session signing key, then calls `POST /auth/sessions/{id}/verify` with `Grid-Wallet-Signature`, `Request-Id`, and the same `clientPublicKey`. If the original session has already expired, use the credential reauthentication flow instead. - operationId: challengeAuthSession - tags: - - Embedded Wallet Auth - security: - - BasicAuth: [] - parameters: - - name: id - in: path - description: The id of the active session to reauthenticate. - required: true - schema: - type: string - example: Session:019542f5-b3e7-1d02-0000-000000000003 - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/AuthSessionReauthRequest' - examples: - reauth: - summary: Start mid-session reauthentication - value: - clientPublicKey: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 - responses: - '202': - description: Challenge issued. The response contains `payloadToSign` plus a `requestId`. Build an API-key stamp over `payloadToSign` with the current session API keypair, then echo `requestId` on `POST /auth/sessions/{id}/verify`. - content: - application/json: - schema: - $ref: '#/components/schemas/SignedRequestChallenge' - examples: - challenge: - summary: Session reauthentication challenge - value: - payloadToSign: '{"type":"ACTIVITY_TYPE_CREATE_READ_WRITE_SESSION_V2","timestampMs":"1746736509954","organizationId":"org_abc123","parameters":{"targetPublicKey":"04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2"}}' - requestId: Request:019542f5-b3e7-1d02-0000-000000000010 - expiresAt: '2026-04-08T15:35:00Z' - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/Error400' - '401': - description: Unauthorized. Returned when the `BasicAuth` credentials are missing or invalid, or when the target session is no longer active and cannot be used for mid-session reauthentication. - content: - application/json: - schema: - $ref: '#/components/schemas/Error401' - '404': - description: Session not found - content: - application/json: - schema: - $ref: '#/components/schemas/Error404' - '500': - description: Internal service error - content: - application/json: - schema: - $ref: '#/components/schemas/Error500' - /auth/sessions/{id}/verify: - post: - summary: Verify a session reauthentication challenge - description: | - Complete mid-session reauthentication for an active Embedded Wallet auth session and create a new session signing key. + 2. Sign `payloadToSign` with the current session signing key, then retry the same request with the full API-key stamp as `Grid-Wallet-Signature`, the `requestId` echoed back as `Request-Id`, and the same `clientPublicKey` in the request body. On success, Grid returns a new `AuthSession` with an `encryptedSessionSigningKey` sealed to that client public key. - This is the signed retry for `POST /auth/sessions/{id}/challenge`. The request must include the full API-key stamp over the prior `payloadToSign` as `Grid-Wallet-Signature`, the challenge `requestId` as `Request-Id`, and the same `clientPublicKey` that was supplied on the challenge step. On success, Grid returns a new `AuthSession` with an `encryptedSessionSigningKey` sealed to that client public key. - - This endpoint requires the original session to still be active so it can authorize the refresh. If the session has already expired, use the credential reauthentication flow instead. - operationId: verifyAuthSession + The original session must still be active on both steps so it can authorize the refresh. If the session has already expired, use the credential reauthentication flow instead. + operationId: refreshAuthSession tags: - Embedded Wallet Auth security: @@ -4525,22 +4456,22 @@ paths: parameters: - name: id in: path - description: The id of the active session being reauthenticated. + description: The id of the active session to refresh. required: true schema: type: string example: Session:019542f5-b3e7-1d02-0000-000000000003 - name: Grid-Wallet-Signature in: header - required: true - description: Full API-key stamp built over the prior `payloadToSign` with the current session API keypair. + required: false + description: Full API-key stamp built over the prior `payloadToSign` with the current session API keypair. Required on the signed retry; ignored on the initial call. schema: type: string example: eyJwdWJsaWNLZXkiOiIwMmExYjIuLi4iLCJzaWduYXR1cmUiOiIzMDQ1MDIyMTAwLi4uIiwic2NoZW1lIjoiUDI1Nl9FQ0RTQV9TSEEyNTYifQ - name: Request-Id in: header - required: true - description: The `requestId` returned in the prior challenge response, echoed back so the server can correlate this signed retry with the issued challenge. + required: false + description: The `requestId` returned in the prior `202` response, echoed back on the signed retry so the server can correlate it with the issued challenge. Required on the signed retry; must be paired with `Grid-Wallet-Signature`. schema: type: string example: Request:019542f5-b3e7-1d02-0000-000000000010 @@ -4549,10 +4480,10 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/AuthSessionReauthRequest' + $ref: '#/components/schemas/AuthSessionRefreshRequest' examples: - reauth: - summary: Complete mid-session reauthentication + refresh: + summary: Refresh an active session value: clientPublicKey: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 responses: @@ -4574,6 +4505,19 @@ paths: createdAt: '2026-04-08T15:30:01Z' updatedAt: '2026-04-08T15:35:00Z' expiresAt: '2026-04-08T15:50:00Z' + '202': + description: Challenge issued. The response contains `payloadToSign` plus a `requestId`. Build an API-key stamp over `payloadToSign` with the current session API keypair, then echo `requestId` on the signed retry. + content: + application/json: + schema: + $ref: '#/components/schemas/SignedRequestChallenge' + examples: + challenge: + summary: Session refresh challenge + value: + payloadToSign: '{"type":"ACTIVITY_TYPE_CREATE_READ_WRITE_SESSION_V2","timestampMs":"1746736509954","organizationId":"org_abc123","parameters":{"targetPublicKey":"04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2"}}' + requestId: Request:019542f5-b3e7-1d02-0000-000000000010 + expiresAt: '2026-04-08T15:35:00Z' '400': description: Bad request content: @@ -4581,7 +4525,7 @@ paths: schema: $ref: '#/components/schemas/Error400' '401': - description: Unauthorized. Returned when the provided `Grid-Wallet-Signature` is missing, malformed, or does not match the pending reauthentication challenge, when the `Request-Id` does not match an unexpired pending challenge, or when the retry's `clientPublicKey` does not match the one bound into `payloadToSign` on the challenge step. + description: Unauthorized. Returned when the `BasicAuth` credentials are missing or invalid, when the target session is no longer active and cannot be used for refresh, when the signed retry omits `Grid-Wallet-Signature`, when the provided signature is malformed or does not match the pending refresh challenge, when the `Request-Id` does not match an unexpired pending challenge, or when the retry's `clientPublicKey` does not match the one bound into `payloadToSign` on the initial call. content: application/json: schema: @@ -15671,7 +15615,7 @@ components: - payloadToSign - requestId - expiresAt - description: Common base for two-step signed-retry challenge responses on Embedded Wallet endpoints (credential revocation, session revocation, wallet export, and similar). Holds the signing fields shared across every challenge shape; each variant composes this base via `allOf` and adds its own resource `id` (and `type`, when applicable) with variant-specific description and example. + description: Common base for two-step signed-retry challenge responses on Embedded Wallet endpoints (credential registration or revocation, session refresh or revocation, wallet export, and similar). Holds the signing fields shared across every challenge shape; each variant composes this base via `allOf` and adds its own resource `id` (and `type`, when applicable) with variant-specific description and example. properties: payloadToSign: type: string @@ -16010,7 +15954,7 @@ components: PASSKEY: '#/components/schemas/PasskeyCredentialVerifyRequest' AuthSession: title: Authentication Session - description: An authentication session on an Embedded Wallet internal account. Returned from `GET /auth/sessions` (list) and `POST /auth/credentials/{id}/verify` (on credential verification) or `POST /auth/sessions/{id}/verify` (on mid-session reauthentication). Only the verify response includes `encryptedSessionSigningKey` — it is delivered exactly once at the moment the session is issued and is never returned by the list endpoint. + description: An authentication session on an Embedded Wallet internal account. Returned from `GET /auth/sessions` (list) and `POST /auth/credentials/{id}/verify` (on credential verification) or `POST /auth/sessions/{id}/refresh` (on mid-session refresh). Only session-issuing responses include `encryptedSessionSigningKey` — it is delivered exactly once at the moment the session is issued and is never returned by the list endpoint. allOf: - $ref: '#/components/schemas/AuthMethod' - type: object @@ -16025,9 +15969,9 @@ components: encryptedSessionSigningKey: type: string description: |- - HPKE-encrypted session signing key, sealed to the `clientPublicKey` supplied on the verify request. Encoded as a base58check string: the decoded payload is a 33-byte compressed P-256 encapsulated public key followed by AES-256-GCM ciphertext. The client decrypts this key with its private key and uses it to sign subsequent Embedded Wallet requests until `expiresAt`. + HPKE-encrypted session signing key, sealed to the `clientPublicKey` supplied on the verification or refresh request. Encoded as a base58check string: the decoded payload is a 33-byte compressed P-256 encapsulated public key followed by AES-256-GCM ciphertext. The client decrypts this key with its private key and uses it to sign subsequent Embedded Wallet requests until `expiresAt`. - Only returned from session-issuing responses like `POST /auth/credentials/{id}/verify` and `POST /auth/sessions/{id}/verify`. Omitted from responses that simply surface existing sessions (e.g. `GET /auth/sessions`) — Grid does not retain the plaintext key after the client has decrypted it. + Only returned from session-issuing responses like `POST /auth/credentials/{id}/verify` and `POST /auth/sessions/{id}/refresh`. Omitted from responses that simply surface existing sessions (e.g. `GET /auth/sessions`) — Grid does not retain the plaintext key after the client has decrypted it. example: w99a5xV6A75TfoAUkZn869fVyDYvgVsKrawMALZXmrauZd8hEv66EkPU1Z42CUaHESQjcA5bqd8dynTGBMLWB9ewtXWPEVbZvocB4Tw2K1vQVp7uwjf expiresAt: type: string @@ -16123,9 +16067,9 @@ components: description: List of active authentication sessions for the internal account. items: $ref: '#/components/schemas/AuthSession' - AuthSessionReauthRequest: - title: Auth Session Reauthentication Request - description: Request body for mid-session reauthentication. The `clientPublicKey` is required on both steps of the signed-retry flow. On the challenge step, Grid binds this key into the Turnkey session-creation payload returned as `payloadToSign`; on the verify step, the client echoes the same key back and Grid uses it to encrypt the newly issued session signing key. + AuthSessionRefreshRequest: + title: Auth Session Refresh Request + description: Request body for refreshing an active authentication session. The `clientPublicKey` is required on both steps of the signed-retry flow. On the initial call, Grid binds this key into the Turnkey session-creation payload returned as `payloadToSign`; on the signed retry, the client echoes the same key back and Grid uses it to encrypt the newly issued session signing key. type: object required: - clientPublicKey @@ -16133,9 +16077,7 @@ components: clientPublicKey: type: string pattern: ^04[0-9a-fA-F]{128}$ - minLength: 130 - maxLength: 130 - description: Client-generated P-256 public key, hex-encoded in uncompressed SEC1 format (`04` prefix followed by the 32-byte X and 32-byte Y coordinates; 130 hex characters total). The matching private key must remain on the client. Grid binds this key into the session-creation payload on the challenge step and seals the returned `encryptedSessionSigningKey` to it on the verify step. + description: Client-generated P-256 public key, hex-encoded in uncompressed SEC1 format (`04` prefix followed by the 32-byte X and 32-byte Y coordinates; 130 hex characters total). The matching private key must remain on the client. Grid binds this key into the session-creation payload on the initial call and seals the returned `encryptedSessionSigningKey` to it on the signed retry. example: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 AgentPermission: type: string diff --git a/openapi/components/schemas/auth/AuthSession.yaml b/openapi/components/schemas/auth/AuthSession.yaml index 061f545c..4781efc4 100644 --- a/openapi/components/schemas/auth/AuthSession.yaml +++ b/openapi/components/schemas/auth/AuthSession.yaml @@ -3,10 +3,10 @@ description: >- An authentication session on an Embedded Wallet internal account. Returned from `GET /auth/sessions` (list) and `POST /auth/credentials/{id}/verify` (on credential verification) or - `POST /auth/sessions/{id}/verify` (on mid-session reauthentication). - Only the verify response includes `encryptedSessionSigningKey` — it - is delivered exactly once at the moment the session is issued and - is never returned by the list endpoint. + `POST /auth/sessions/{id}/refresh` (on mid-session refresh). + Only session-issuing responses include `encryptedSessionSigningKey` — + it is delivered exactly once at the moment the session is issued and is + never returned by the list endpoint. allOf: - $ref: ./AuthMethod.yaml - type: object @@ -27,7 +27,8 @@ allOf: type: string description: >- HPKE-encrypted session signing key, sealed to the - `clientPublicKey` supplied on the verify request. Encoded as + `clientPublicKey` supplied on the verification or refresh request. + Encoded as a base58check string: the decoded payload is a 33-byte compressed P-256 encapsulated public key followed by AES-256-GCM ciphertext. The client decrypts this key with @@ -37,7 +38,7 @@ allOf: Only returned from session-issuing responses like `POST /auth/credentials/{id}/verify` and - `POST /auth/sessions/{id}/verify`. Omitted from responses that + `POST /auth/sessions/{id}/refresh`. Omitted from responses that simply surface existing sessions (e.g. `GET /auth/sessions`) — Grid does not retain the plaintext key after the client has decrypted it. diff --git a/openapi/components/schemas/auth/AuthSessionReauthRequest.yaml b/openapi/components/schemas/auth/AuthSessionRefreshRequest.yaml similarity index 52% rename from openapi/components/schemas/auth/AuthSessionReauthRequest.yaml rename to openapi/components/schemas/auth/AuthSessionRefreshRequest.yaml index 65e7abd4..d8f71107 100644 --- a/openapi/components/schemas/auth/AuthSessionReauthRequest.yaml +++ b/openapi/components/schemas/auth/AuthSessionRefreshRequest.yaml @@ -1,10 +1,10 @@ -title: Auth Session Reauthentication Request +title: Auth Session Refresh Request description: >- - Request body for mid-session reauthentication. The `clientPublicKey` is - required on both steps of the signed-retry flow. On the challenge step, Grid - binds this key into the Turnkey session-creation payload returned as - `payloadToSign`; on the verify step, the client echoes the same key back and - Grid uses it to encrypt the newly issued session signing key. + Request body for refreshing an active authentication session. The + `clientPublicKey` is required on both steps of the signed-retry flow. On the + initial call, Grid binds this key into the Turnkey session-creation payload + returned as `payloadToSign`; on the signed retry, the client echoes the same + key back and Grid uses it to encrypt the newly issued session signing key. type: object required: - clientPublicKey @@ -12,13 +12,11 @@ properties: clientPublicKey: type: string pattern: "^04[0-9a-fA-F]{128}$" - minLength: 130 - maxLength: 130 description: >- Client-generated P-256 public key, hex-encoded in uncompressed SEC1 format (`04` prefix followed by the 32-byte X and 32-byte Y coordinates; 130 hex characters total). The matching private key must remain on the client. Grid binds this key into the session-creation payload on the - challenge step and seals the returned `encryptedSessionSigningKey` to it - on the verify step. + initial call and seals the returned `encryptedSessionSigningKey` to it on + the signed retry. example: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 diff --git a/openapi/components/schemas/common/SignedRequestChallenge.yaml b/openapi/components/schemas/common/SignedRequestChallenge.yaml index d5b22268..f0bd054e 100644 --- a/openapi/components/schemas/common/SignedRequestChallenge.yaml +++ b/openapi/components/schemas/common/SignedRequestChallenge.yaml @@ -6,8 +6,9 @@ required: - expiresAt description: >- Common base for two-step signed-retry challenge responses on - Embedded Wallet endpoints (credential revocation, session revocation, - wallet export, and similar). Holds the signing fields shared across + Embedded Wallet endpoints (credential registration or revocation, + session refresh or revocation, wallet export, and similar). Holds the + signing fields shared across every challenge shape; each variant composes this base via `allOf` and adds its own resource `id` (and `type`, when applicable) with variant-specific description and example. diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index a232a908..65958246 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -213,10 +213,8 @@ paths: $ref: paths/auth/auth_sessions.yaml /auth/sessions/{id}: $ref: paths/auth/auth_sessions_{id}.yaml - /auth/sessions/{id}/challenge: - $ref: paths/auth/auth_sessions_{id}_challenge.yaml - /auth/sessions/{id}/verify: - $ref: paths/auth/auth_sessions_{id}_verify.yaml + /auth/sessions/{id}/refresh: + $ref: paths/auth/auth_sessions_{id}_refresh.yaml /agents: $ref: paths/agents/agents.yaml /agents/approvals: diff --git a/openapi/paths/auth/auth_sessions_{id}_challenge.yaml b/openapi/paths/auth/auth_sessions_{id}_challenge.yaml deleted file mode 100644 index 50c981e1..00000000 --- a/openapi/paths/auth/auth_sessions_{id}_challenge.yaml +++ /dev/null @@ -1,88 +0,0 @@ -post: - summary: Issue a session reauthentication challenge - description: > - Start mid-session reauthentication for an active Embedded Wallet auth - session. - - - Use this endpoint when a session is still active but close to expiry and - the customer wants to extend access without re-running the underlying - credential-specific authentication flow. Grid builds a Turnkey - create-read-write-session payload, binds the supplied `clientPublicKey` into - that payload, persists it as a pending request, and returns the canonical - body as `payloadToSign`. - - - The client signs `payloadToSign` with the current session signing key, then - calls `POST /auth/sessions/{id}/verify` with `Grid-Wallet-Signature`, - `Request-Id`, and the same `clientPublicKey`. If the original session has - already expired, use the credential reauthentication flow instead. - operationId: challengeAuthSession - tags: - - Embedded Wallet Auth - security: - - BasicAuth: [] - parameters: - - name: id - in: path - description: The id of the active session to reauthenticate. - required: true - schema: - type: string - example: Session:019542f5-b3e7-1d02-0000-000000000003 - requestBody: - required: true - content: - application/json: - schema: - $ref: ../../components/schemas/auth/AuthSessionReauthRequest.yaml - examples: - reauth: - summary: Start mid-session reauthentication - value: - clientPublicKey: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 - responses: - '202': - description: >- - Challenge issued. The response contains `payloadToSign` plus a - `requestId`. Build an API-key stamp over `payloadToSign` with the - current session API keypair, then echo `requestId` on - `POST /auth/sessions/{id}/verify`. - content: - application/json: - schema: - $ref: ../../components/schemas/common/SignedRequestChallenge.yaml - examples: - challenge: - summary: Session reauthentication challenge - value: - payloadToSign: '{"type":"ACTIVITY_TYPE_CREATE_READ_WRITE_SESSION_V2","timestampMs":"1746736509954","organizationId":"org_abc123","parameters":{"targetPublicKey":"04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2"}}' - requestId: Request:019542f5-b3e7-1d02-0000-000000000010 - expiresAt: '2026-04-08T15:35:00Z' - '400': - description: Bad request - content: - application/json: - schema: - $ref: ../../components/schemas/errors/Error400.yaml - '401': - description: >- - Unauthorized. Returned when the `BasicAuth` credentials are missing or - invalid, or when the target session is no longer active and cannot be - used for mid-session reauthentication. - content: - application/json: - schema: - $ref: ../../components/schemas/errors/Error401.yaml - '404': - description: Session not found - content: - application/json: - schema: - $ref: ../../components/schemas/errors/Error404.yaml - '500': - description: Internal service error - content: - application/json: - schema: - $ref: ../../components/schemas/errors/Error500.yaml diff --git a/openapi/paths/auth/auth_sessions_{id}_refresh.yaml b/openapi/paths/auth/auth_sessions_{id}_refresh.yaml new file mode 100644 index 00000000..cf4f4d44 --- /dev/null +++ b/openapi/paths/auth/auth_sessions_{id}_refresh.yaml @@ -0,0 +1,136 @@ +post: + summary: Refresh an authentication session + description: > + Refresh an active Embedded Wallet auth session and create a new session + signing key. Session refresh is a two-step signed-retry flow: + + + 1. Call `POST /auth/sessions/{id}/refresh` with the request body + `{ "clientPublicKey": "04..." }` and no signature headers. Grid builds a + Turnkey create-read-write-session payload, binds the supplied + `clientPublicKey` into that payload, persists it as a pending request, and + returns `202` with `payloadToSign`, `requestId`, and `expiresAt`. + + + 2. Sign `payloadToSign` with the current session signing key, then retry the + same request with the full API-key stamp as `Grid-Wallet-Signature`, the + `requestId` echoed back as `Request-Id`, and the same `clientPublicKey` in + the request body. On success, Grid returns a new `AuthSession` with an + `encryptedSessionSigningKey` sealed to that client public key. + + + The original session must still be active on both steps so it can authorize + the refresh. If the session has already expired, use the credential + reauthentication flow instead. + operationId: refreshAuthSession + tags: + - Embedded Wallet Auth + security: + - BasicAuth: [] + parameters: + - name: id + in: path + description: The id of the active session to refresh. + required: true + schema: + type: string + example: Session:019542f5-b3e7-1d02-0000-000000000003 + - name: Grid-Wallet-Signature + in: header + required: false + description: >- + Full API-key stamp built over the prior `payloadToSign` with the current + session API keypair. Required on the signed retry; ignored on the + initial call. + schema: + type: string + example: eyJwdWJsaWNLZXkiOiIwMmExYjIuLi4iLCJzaWduYXR1cmUiOiIzMDQ1MDIyMTAwLi4uIiwic2NoZW1lIjoiUDI1Nl9FQ0RTQV9TSEEyNTYifQ + - name: Request-Id + in: header + required: false + description: >- + The `requestId` returned in the prior `202` response, echoed back on the + signed retry so the server can correlate it with the issued challenge. + Required on the signed retry; must be paired with + `Grid-Wallet-Signature`. + schema: + type: string + example: Request:019542f5-b3e7-1d02-0000-000000000010 + requestBody: + required: true + content: + application/json: + schema: + $ref: ../../components/schemas/auth/AuthSessionRefreshRequest.yaml + examples: + refresh: + summary: Refresh an active session + value: + clientPublicKey: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 + responses: + '201': + description: New authentication session created successfully. + content: + application/json: + schema: + $ref: ../../components/schemas/auth/AuthSession.yaml + examples: + session: + summary: Refreshed authentication session + value: + id: Session:019542f5-b3e7-1d02-0000-000000000011 + accountId: InternalAccount:019542f5-b3e7-1d02-0000-000000000002 + type: EMAIL_OTP + encryptedSessionSigningKey: w99a5xV6A75TfoAUkZn869fVyDYvgVsKrawMALZXmrauZd8hEv66EkPU1Z42CUaHESQjcA5bqd8dynTGBMLWB9ewtXWPEVbZvocB4Tw2K1vQVp7uwjf + nickname: example@lightspark.com + createdAt: '2026-04-08T15:30:01Z' + updatedAt: '2026-04-08T15:35:00Z' + expiresAt: '2026-04-08T15:50:00Z' + '202': + description: >- + Challenge issued. The response contains `payloadToSign` plus a + `requestId`. Build an API-key stamp over `payloadToSign` with the + current session API keypair, then echo `requestId` on the signed retry. + content: + application/json: + schema: + $ref: ../../components/schemas/common/SignedRequestChallenge.yaml + examples: + challenge: + summary: Session refresh challenge + value: + payloadToSign: '{"type":"ACTIVITY_TYPE_CREATE_READ_WRITE_SESSION_V2","timestampMs":"1746736509954","organizationId":"org_abc123","parameters":{"targetPublicKey":"04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2"}}' + requestId: Request:019542f5-b3e7-1d02-0000-000000000010 + expiresAt: '2026-04-08T15:35:00Z' + '400': + description: Bad request + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error400.yaml + '401': + description: >- + Unauthorized. Returned when the `BasicAuth` credentials are missing or + invalid, when the target session is no longer active and cannot be used + for refresh, when the signed retry omits `Grid-Wallet-Signature`, when + the provided signature is malformed or does not match the pending + refresh challenge, when the `Request-Id` does not match an unexpired + pending challenge, or when the retry's `clientPublicKey` does not match + the one bound into + `payloadToSign` on the initial call. + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '404': + description: Session not found + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error404.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml diff --git a/openapi/paths/auth/auth_sessions_{id}_verify.yaml b/openapi/paths/auth/auth_sessions_{id}_verify.yaml deleted file mode 100644 index 9d0a3d16..00000000 --- a/openapi/paths/auth/auth_sessions_{id}_verify.yaml +++ /dev/null @@ -1,108 +0,0 @@ -post: - summary: Verify a session reauthentication challenge - description: > - Complete mid-session reauthentication for an active Embedded Wallet auth - session and create a new session signing key. - - - This is the signed retry for `POST /auth/sessions/{id}/challenge`. The - request must include the full API-key stamp over the prior `payloadToSign` - as `Grid-Wallet-Signature`, the challenge `requestId` as `Request-Id`, and - the same `clientPublicKey` that was supplied on the challenge step. On - success, Grid returns a new `AuthSession` with an - `encryptedSessionSigningKey` sealed to that client public key. - - - This endpoint requires the original session to still be active so it can - authorize the refresh. If the session has already expired, use the - credential reauthentication flow instead. - operationId: verifyAuthSession - tags: - - Embedded Wallet Auth - security: - - BasicAuth: [] - parameters: - - name: id - in: path - description: The id of the active session being reauthenticated. - required: true - schema: - type: string - example: Session:019542f5-b3e7-1d02-0000-000000000003 - - name: Grid-Wallet-Signature - in: header - required: true - description: >- - Full API-key stamp built over the prior `payloadToSign` with the current - session API keypair. - schema: - type: string - example: eyJwdWJsaWNLZXkiOiIwMmExYjIuLi4iLCJzaWduYXR1cmUiOiIzMDQ1MDIyMTAwLi4uIiwic2NoZW1lIjoiUDI1Nl9FQ0RTQV9TSEEyNTYifQ - - name: Request-Id - in: header - required: true - description: >- - The `requestId` returned in the prior challenge response, echoed back so - the server can correlate this signed retry with the issued challenge. - schema: - type: string - example: Request:019542f5-b3e7-1d02-0000-000000000010 - requestBody: - required: true - content: - application/json: - schema: - $ref: ../../components/schemas/auth/AuthSessionReauthRequest.yaml - examples: - reauth: - summary: Complete mid-session reauthentication - value: - clientPublicKey: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 - responses: - '201': - description: New authentication session created successfully. - content: - application/json: - schema: - $ref: ../../components/schemas/auth/AuthSession.yaml - examples: - session: - summary: Refreshed authentication session - value: - id: Session:019542f5-b3e7-1d02-0000-000000000011 - accountId: InternalAccount:019542f5-b3e7-1d02-0000-000000000002 - type: EMAIL_OTP - encryptedSessionSigningKey: w99a5xV6A75TfoAUkZn869fVyDYvgVsKrawMALZXmrauZd8hEv66EkPU1Z42CUaHESQjcA5bqd8dynTGBMLWB9ewtXWPEVbZvocB4Tw2K1vQVp7uwjf - nickname: example@lightspark.com - createdAt: '2026-04-08T15:30:01Z' - updatedAt: '2026-04-08T15:35:00Z' - expiresAt: '2026-04-08T15:50:00Z' - '400': - description: Bad request - content: - application/json: - schema: - $ref: ../../components/schemas/errors/Error400.yaml - '401': - description: >- - Unauthorized. Returned when the provided `Grid-Wallet-Signature` is - missing, malformed, or does not match the pending reauthentication - challenge, when the `Request-Id` does not match an unexpired pending - challenge, or when the retry's `clientPublicKey` does not match the one - bound into `payloadToSign` on the challenge step. - content: - application/json: - schema: - $ref: ../../components/schemas/errors/Error401.yaml - '404': - description: Session not found - content: - application/json: - schema: - $ref: ../../components/schemas/errors/Error404.yaml - '500': - description: Internal service error - content: - application/json: - schema: - $ref: ../../components/schemas/errors/Error500.yaml