diff --git a/mintlify/global-accounts/platform-tools/sandbox-testing.mdx b/mintlify/global-accounts/platform-tools/sandbox-testing.mdx index b6b9be96..24b58063 100644 --- a/mintlify/global-accounts/platform-tools/sandbox-testing.mdx +++ b/mintlify/global-accounts/platform-tools/sandbox-testing.mdx @@ -7,7 +7,7 @@ icon: "/images/icons/hammer.svg" import SandboxGlobalAccountMagic from '/snippets/sandbox-global-account-magic.mdx'; -The Grid sandbox lets you exercise the full Global Accounts integration — customer creation, account lookup, credential registration, funding, and signed withdrawals — without moving real money or standing up real auth providers. All API endpoints work the same way as in production, but money movements are simulated. OTP, passkey, and wallet signatures use sandbox-only magic values, while OAuth uses JWT-shaped sandbox OIDC tokens with claim, freshness, identity, and nonce checks. +The Grid sandbox lets you exercise the full Global Accounts integration — customer creation, account lookup, credential registration, funding, and signed withdrawals — without moving real money or standing up real auth providers. All API endpoints work the same way as in production, but money movements are simulated. OTP, passkey, and wallet signatures use sandbox-only magic values, while OAuth uses `POST /sandbox/oidc/token` to mint JWT-shaped sandbox OIDC tokens with claim, freshness, identity, and nonce checks. ## Sandbox setup @@ -52,7 +52,7 @@ All webhook events fire normally in sandbox. Configure your webhook URL in the d When you're ready to go live: 1. Generate production API tokens in the dashboard and swap them for the sandbox credentials in your environment. -2. Remove sandbox magic values and unsigned sandbox OIDC tokens from your client and server code — production runs the real OTP, HPKE, WebAuthn, OIDC signature, and ECDSA flows. +2. Remove sandbox magic values and sandbox OIDC helper calls from your client and server code — production runs the real OTP, HPKE, WebAuthn, OIDC signature, and ECDSA flows. 3. Configure production webhook endpoints. 4. Test with small amounts first. diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml index d288fb73..f89a79df 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -2933,6 +2933,67 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' + /sandbox/oidc/token: + post: + summary: Create a sandbox OIDC token + description: | + Mint a JWT-shaped OIDC ID token for embedded-wallet OAuth sandbox flows. Use the returned `oidcToken` anywhere the OAuth auth credential endpoints expect an OIDC token. This endpoint only mints a mock token; it does not create auth methods, wallets, sessions, or Turnkey state. + This endpoint is only for the sandbox environment and will fail for production platforms/keys. + operationId: createSandboxOidcToken + tags: + - Sandbox + security: + - BasicAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/SandboxOidcTokenRequest' + examples: + credentialRegistration: + summary: Mint a token for OAuth credential registration + value: + provider: GOOGLE + subject: alice + credentialVerify: + summary: Mint a nonce-bound token for OAuth verification + value: + provider: GOOGLE + subject: alice + clientPublicKey: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 + email: alice@example.com + responses: + '200': + description: Sandbox OIDC token created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/SandboxOidcTokenResponse' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '403': + description: Forbidden - request was made with a production platform token + content: + application/json: + schema: + $ref: '#/components/schemas/Error403' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' /customers/bulk/csv: post: summary: Upload customers via CSV file @@ -15714,6 +15775,116 @@ components: response_body: type: string description: The raw body content returned by the webhook endpoint in response to the request + SandboxOidcProvider: + type: string + description: Sandbox OIDC provider to emulate. + enum: + - GOOGLE + - APPLE + example: GOOGLE + SandboxOidcTokenRequest: + type: object + required: + - provider + - subject + properties: + provider: + $ref: '#/components/schemas/SandboxOidcProvider' + subject: + type: string + minLength: 1 + maxLength: 256 + description: Fake identity-provider user ID. This becomes the OIDC token `sub` claim and is matched during OAuth credential verification. + example: alice + clientPublicKey: + type: string + minLength: 1 + description: Optional client-generated public key hex. Include this when minting a token for OAuth credential verification. When present, Grid adds a `nonce` claim equal to `sha256(clientPublicKey)`. + example: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 + email: + type: string + minLength: 1 + format: email + description: Optional email claim to include in the token. If omitted, Grid derives a deterministic sandbox email from `subject`. + example: alice@example.com + SandboxOidcTokenResponse: + type: object + required: + - oidcToken + - provider + - issuer + - audience + - subject + - email + - issuedAt + - expiresAt + properties: + oidcToken: + type: string + description: JWT-shaped OIDC ID token to pass as `oidcToken` to the OAuth auth credential endpoints. + example: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImdyaWQtc2FuZGJveC1vYXV0aCJ9.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJhdWQiOiJncmlkLXNhbmRib3gtb2F1dGgtY2xpZW50LWlkIiwic3ViIjoiYWxpY2UiLCJpYXQiOjE3NzkzOTM2MDAsImV4cCI6MTc3OTM5MzY2MCwiZW1haWwiOiJhbGljZUBleGFtcGxlLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlfQ.Z3JpZC1zYW5kYm94LXNpZ25hdHVyZQ + provider: + $ref: '#/components/schemas/SandboxOidcProvider' + issuer: + type: string + description: OIDC issuer derived from `provider`. + example: https://accounts.google.com + audience: + type: string + description: Fixed sandbox OAuth client ID used as the token `aud` claim. + example: grid-sandbox-oauth-client-id + subject: + type: string + description: Token `sub` claim. + example: alice + email: + type: string + format: email + description: Token `email` claim. + example: alice@example.com + issuedAt: + type: string + format: date-time + description: Token issue time matching the JWT `iat` claim. + example: '2026-05-21T20:00:00Z' + expiresAt: + type: string + format: date-time + description: Token expiration time matching the JWT `exp` claim. + example: '2026-05-21T20:01:00Z' + Error403: + type: object + required: + - message + - status + - code + properties: + status: + type: integer + enum: + - 403 + description: HTTP status code + code: + type: string + description: | + | Error Code | Description | + |------------|-------------| + | FORBIDDEN | Insufficient permissions | + | USER_NOT_READY | Customer exists but is not ready for operation | + | COUNTERPARTY_NOT_ALLOWED | Counterparty has not been enabled for your account | + | VELOCITY_LIMIT_EXCEEDED | Counterparty has exceeded velocity limits | + enum: + - FORBIDDEN + - USER_NOT_READY + - COUNTERPARTY_NOT_ALLOWED + - VELOCITY_LIMIT_EXCEEDED + message: + type: string + description: Error message + details: + type: object + description: Additional error details + additionalProperties: true BulkCustomerImportJobAccepted: type: object required: @@ -15904,39 +16075,6 @@ components: type: string description: The UMA address of the customer claiming the invitation example: $invitee@uma.domain - Error403: - type: object - required: - - message - - status - - code - properties: - status: - type: integer - enum: - - 403 - description: HTTP status code - code: - type: string - description: | - | Error Code | Description | - |------------|-------------| - | FORBIDDEN | Insufficient permissions | - | USER_NOT_READY | Customer exists but is not ready for operation | - | COUNTERPARTY_NOT_ALLOWED | Counterparty has not been enabled for your account | - | VELOCITY_LIMIT_EXCEEDED | Counterparty has exceeded velocity limits | - enum: - - FORBIDDEN - - USER_NOT_READY - - COUNTERPARTY_NOT_ALLOWED - - VELOCITY_LIMIT_EXCEEDED - message: - type: string - description: Error message - details: - type: object - description: Additional error details - additionalProperties: true SandboxSendRequest: type: object required: diff --git a/mintlify/snippets/sandbox-global-account-magic.mdx b/mintlify/snippets/sandbox-global-account-magic.mdx index cbd2aff1..0b6c1751 100644 --- a/mintlify/snippets/sandbox-global-account-magic.mdx +++ b/mintlify/snippets/sandbox-global-account-magic.mdx @@ -1,4 +1,4 @@ -The Grid sandbox accepts a small set of magic values for Global Account flows, so you can exercise the full request shape without standing up Turnkey, WebAuthn, or an OIDC provider. OTP, passkey, and wallet signatures use fixed sandbox-only values. OAuth uses JWT-shaped sandbox OIDC tokens: sandbox skips real IdP signature verification, but still validates the token claims, freshness, credential identity, and verify-time nonce binding. +The Grid sandbox accepts a small set of magic values for Global Account flows, so you can exercise the full request shape without standing up Turnkey, WebAuthn, or an OIDC provider. OTP, passkey, and wallet signatures use fixed sandbox-only values. OAuth uses `POST /sandbox/oidc/token` to mint JWT-shaped sandbox OIDC tokens: sandbox skips real IdP signature verification, but still validates the token claims, freshness, credential identity, and verify-time nonce binding. A wrong magic value or sandbox OIDC authentication failure returns `401 UNAUTHORIZED` with a `reason` field that names the specific check that failed. A malformed OIDC JWT can return `400 INVALID_INPUT` before authentication starts. @@ -55,49 +55,48 @@ Any other signature returns `401 UNAUTHORIZED` with `reason: "Invalid passkey si ### OAuth (OIDC) token -OAuth does not use a fixed magic token in sandbox. Pass a JWT-shaped OIDC token as `oidcToken`. The JWT signature segment can be a dummy value, but the payload must look like a real ID token. +OAuth does not use a fixed magic token in sandbox. Call `POST /sandbox/oidc/token` to mint a fresh JWT-shaped OIDC token, then pass the returned `oidcToken` to the same auth endpoints you use in production. -For `POST /auth/credentials` with `type: "OAUTH"`, the sandbox token must include: +For `POST /auth/credentials` with `type: "OAUTH"`, omit `clientPublicKey`: -- `iss`: a supported issuer, such as `https://accounts.google.com`, `accounts.google.com`, or `https://appleid.apple.com` -- `aud`: a non-empty string, or a single-element string array -- `sub`: a non-empty subject identifier for the user -- `iat`: a numeric issued-at timestamp no more than 60 seconds before the request, with 5 seconds of clock skew allowed -- `exp`: a numeric expiration timestamp later than the request time +```bash +OIDC_TOKEN=$(curl -sS -X POST "$GRID_BASE_URL/sandbox/oidc/token" \ + -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \ + -H "Content-Type: application/json" \ + -d '{ + "provider": "GOOGLE", + "subject": "sandbox-user-123", + "email": "sandbox-user-123@example.com" + }' | jq -r '.oidcToken') -Grid stores the OAuth credential's registered identity from `iss`, `aud`, and `sub`. On `POST /auth/credentials/{id}/verify`, the fresh `oidcToken` must carry the same `iss`, `aud`, and `sub` as the credential being verified. It must also include `nonce` equal to `sha256(clientPublicKey)`, where `clientPublicKey` is the exact hex public key sent in the verify request. +curl -X POST "$GRID_BASE_URL/auth/credentials" \ + -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \ + -H "Content-Type: application/json" \ + -d '{ + "type": "OAUTH", + "accountId": "InternalAccount:abc123", + "oidcToken": "'"$OIDC_TOKEN"'" + }' +``` + +Grid stores the OAuth credential's registered identity from `iss`, `aud`, and `sub`. On `POST /auth/credentials/{id}/verify`, mint a new token with the same `provider` and `subject`, and include `clientPublicKey` so Grid adds `nonce = sha256(clientPublicKey)`: ```bash export PUBLIC_KEY="04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2" -OIDC_TOKEN=$(node - <<'NODE' -const crypto = require("crypto"); - -const publicKey = process.env.PUBLIC_KEY || "04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2"; -const now = Math.floor(Date.now() / 1000); -const b64url = (value) => - Buffer.from(JSON.stringify(value)).toString("base64url"); - -const payload = { - iss: "https://accounts.google.com", - sub: "sandbox-user-123", - aud: "grid-sandbox-oauth-client-id", - iat: now, - exp: now + 300, - nonce: crypto.createHash("sha256").update(publicKey).digest("hex"), - email: "sandbox-user-123@example.com", - email_verified: true -}; - -console.log( - `${b64url({ alg: "RS256", typ: "JWT" })}.${b64url(payload)}.sandbox-signature` -); -NODE -) -curl -X POST https://api.lightspark.com/grid/2025-10-13/auth/credentials/AuthMethod:abc123/verify \ +OIDC_TOKEN=$(curl -sS -X POST "$GRID_BASE_URL/sandbox/oidc/token" \ + -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \ + -H "Content-Type: application/json" \ + -d '{ + "provider": "GOOGLE", + "subject": "sandbox-user-123", + "clientPublicKey": "'"$PUBLIC_KEY"'", + "email": "sandbox-user-123@example.com" + }' | jq -r '.oidcToken') + +curl -X POST "$GRID_BASE_URL/auth/credentials/AuthMethod:abc123/verify" \ -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \ -H "Content-Type: application/json" \ - -H "Request-Id: 7c4a8d09-ca37-4e3e-9e0d-8c2b3e9a1f21" \ -d '{ "type": "OAUTH", "oidcToken": "'"$OIDC_TOKEN"'", @@ -106,7 +105,7 @@ curl -X POST https://api.lightspark.com/grid/2025-10-13/auth/credentials/AuthMet ``` - The old literal `sandbox-valid-oidc-token` is no longer accepted. Use a freshly generated sandbox JWT for both OAuth credential registration and OAuth verification. Production requires a real ID token from your provider and verifies the provider signature. + The old literal `sandbox-valid-oidc-token` is no longer accepted. Use `POST /sandbox/oidc/token` to mint a fresh sandbox token for both OAuth credential registration and OAuth verification. Production requires a real ID token from your provider and verifies the provider signature. ### Wallet signature header diff --git a/openapi.yaml b/openapi.yaml index d288fb73..f89a79df 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -2933,6 +2933,67 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' + /sandbox/oidc/token: + post: + summary: Create a sandbox OIDC token + description: | + Mint a JWT-shaped OIDC ID token for embedded-wallet OAuth sandbox flows. Use the returned `oidcToken` anywhere the OAuth auth credential endpoints expect an OIDC token. This endpoint only mints a mock token; it does not create auth methods, wallets, sessions, or Turnkey state. + This endpoint is only for the sandbox environment and will fail for production platforms/keys. + operationId: createSandboxOidcToken + tags: + - Sandbox + security: + - BasicAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/SandboxOidcTokenRequest' + examples: + credentialRegistration: + summary: Mint a token for OAuth credential registration + value: + provider: GOOGLE + subject: alice + credentialVerify: + summary: Mint a nonce-bound token for OAuth verification + value: + provider: GOOGLE + subject: alice + clientPublicKey: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 + email: alice@example.com + responses: + '200': + description: Sandbox OIDC token created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/SandboxOidcTokenResponse' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '403': + description: Forbidden - request was made with a production platform token + content: + application/json: + schema: + $ref: '#/components/schemas/Error403' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' /customers/bulk/csv: post: summary: Upload customers via CSV file @@ -15714,6 +15775,116 @@ components: response_body: type: string description: The raw body content returned by the webhook endpoint in response to the request + SandboxOidcProvider: + type: string + description: Sandbox OIDC provider to emulate. + enum: + - GOOGLE + - APPLE + example: GOOGLE + SandboxOidcTokenRequest: + type: object + required: + - provider + - subject + properties: + provider: + $ref: '#/components/schemas/SandboxOidcProvider' + subject: + type: string + minLength: 1 + maxLength: 256 + description: Fake identity-provider user ID. This becomes the OIDC token `sub` claim and is matched during OAuth credential verification. + example: alice + clientPublicKey: + type: string + minLength: 1 + description: Optional client-generated public key hex. Include this when minting a token for OAuth credential verification. When present, Grid adds a `nonce` claim equal to `sha256(clientPublicKey)`. + example: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 + email: + type: string + minLength: 1 + format: email + description: Optional email claim to include in the token. If omitted, Grid derives a deterministic sandbox email from `subject`. + example: alice@example.com + SandboxOidcTokenResponse: + type: object + required: + - oidcToken + - provider + - issuer + - audience + - subject + - email + - issuedAt + - expiresAt + properties: + oidcToken: + type: string + description: JWT-shaped OIDC ID token to pass as `oidcToken` to the OAuth auth credential endpoints. + example: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImdyaWQtc2FuZGJveC1vYXV0aCJ9.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJhdWQiOiJncmlkLXNhbmRib3gtb2F1dGgtY2xpZW50LWlkIiwic3ViIjoiYWxpY2UiLCJpYXQiOjE3NzkzOTM2MDAsImV4cCI6MTc3OTM5MzY2MCwiZW1haWwiOiJhbGljZUBleGFtcGxlLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlfQ.Z3JpZC1zYW5kYm94LXNpZ25hdHVyZQ + provider: + $ref: '#/components/schemas/SandboxOidcProvider' + issuer: + type: string + description: OIDC issuer derived from `provider`. + example: https://accounts.google.com + audience: + type: string + description: Fixed sandbox OAuth client ID used as the token `aud` claim. + example: grid-sandbox-oauth-client-id + subject: + type: string + description: Token `sub` claim. + example: alice + email: + type: string + format: email + description: Token `email` claim. + example: alice@example.com + issuedAt: + type: string + format: date-time + description: Token issue time matching the JWT `iat` claim. + example: '2026-05-21T20:00:00Z' + expiresAt: + type: string + format: date-time + description: Token expiration time matching the JWT `exp` claim. + example: '2026-05-21T20:01:00Z' + Error403: + type: object + required: + - message + - status + - code + properties: + status: + type: integer + enum: + - 403 + description: HTTP status code + code: + type: string + description: | + | Error Code | Description | + |------------|-------------| + | FORBIDDEN | Insufficient permissions | + | USER_NOT_READY | Customer exists but is not ready for operation | + | COUNTERPARTY_NOT_ALLOWED | Counterparty has not been enabled for your account | + | VELOCITY_LIMIT_EXCEEDED | Counterparty has exceeded velocity limits | + enum: + - FORBIDDEN + - USER_NOT_READY + - COUNTERPARTY_NOT_ALLOWED + - VELOCITY_LIMIT_EXCEEDED + message: + type: string + description: Error message + details: + type: object + description: Additional error details + additionalProperties: true BulkCustomerImportJobAccepted: type: object required: @@ -15904,39 +16075,6 @@ components: type: string description: The UMA address of the customer claiming the invitation example: $invitee@uma.domain - Error403: - type: object - required: - - message - - status - - code - properties: - status: - type: integer - enum: - - 403 - description: HTTP status code - code: - type: string - description: | - | Error Code | Description | - |------------|-------------| - | FORBIDDEN | Insufficient permissions | - | USER_NOT_READY | Customer exists but is not ready for operation | - | COUNTERPARTY_NOT_ALLOWED | Counterparty has not been enabled for your account | - | VELOCITY_LIMIT_EXCEEDED | Counterparty has exceeded velocity limits | - enum: - - FORBIDDEN - - USER_NOT_READY - - COUNTERPARTY_NOT_ALLOWED - - VELOCITY_LIMIT_EXCEEDED - message: - type: string - description: Error message - details: - type: object - description: Additional error details - additionalProperties: true SandboxSendRequest: type: object required: diff --git a/openapi/components/schemas/sandbox/SandboxOidcProvider.yaml b/openapi/components/schemas/sandbox/SandboxOidcProvider.yaml new file mode 100644 index 00000000..40edd45a --- /dev/null +++ b/openapi/components/schemas/sandbox/SandboxOidcProvider.yaml @@ -0,0 +1,6 @@ +type: string +description: Sandbox OIDC provider to emulate. +enum: + - GOOGLE + - APPLE +example: GOOGLE diff --git a/openapi/components/schemas/sandbox/SandboxOidcTokenRequest.yaml b/openapi/components/schemas/sandbox/SandboxOidcTokenRequest.yaml new file mode 100644 index 00000000..7b5fb3f6 --- /dev/null +++ b/openapi/components/schemas/sandbox/SandboxOidcTokenRequest.yaml @@ -0,0 +1,31 @@ +type: object +required: + - provider + - subject +properties: + provider: + $ref: ./SandboxOidcProvider.yaml + subject: + type: string + minLength: 1 + maxLength: 256 + description: >- + Fake identity-provider user ID. This becomes the OIDC token `sub` + claim and is matched during OAuth credential verification. + example: alice + clientPublicKey: + type: string + minLength: 1 + description: >- + Optional client-generated public key hex. Include this when minting a + token for OAuth credential verification. When present, Grid adds a + `nonce` claim equal to `sha256(clientPublicKey)`. + example: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 + email: + type: string + minLength: 1 + format: email + description: >- + Optional email claim to include in the token. If omitted, Grid derives + a deterministic sandbox email from `subject`. + example: alice@example.com diff --git a/openapi/components/schemas/sandbox/SandboxOidcTokenResponse.yaml b/openapi/components/schemas/sandbox/SandboxOidcTokenResponse.yaml new file mode 100644 index 00000000..6d592893 --- /dev/null +++ b/openapi/components/schemas/sandbox/SandboxOidcTokenResponse.yaml @@ -0,0 +1,46 @@ +type: object +required: + - oidcToken + - provider + - issuer + - audience + - subject + - email + - issuedAt + - expiresAt +properties: + oidcToken: + type: string + description: >- + JWT-shaped OIDC ID token to pass as `oidcToken` to the OAuth auth + credential endpoints. + example: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImdyaWQtc2FuZGJveC1vYXV0aCJ9.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJhdWQiOiJncmlkLXNhbmRib3gtb2F1dGgtY2xpZW50LWlkIiwic3ViIjoiYWxpY2UiLCJpYXQiOjE3NzkzOTM2MDAsImV4cCI6MTc3OTM5MzY2MCwiZW1haWwiOiJhbGljZUBleGFtcGxlLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlfQ.Z3JpZC1zYW5kYm94LXNpZ25hdHVyZQ + provider: + $ref: ./SandboxOidcProvider.yaml + issuer: + type: string + description: OIDC issuer derived from `provider`. + example: https://accounts.google.com + audience: + type: string + description: Fixed sandbox OAuth client ID used as the token `aud` claim. + example: grid-sandbox-oauth-client-id + subject: + type: string + description: Token `sub` claim. + example: alice + email: + type: string + format: email + description: Token `email` claim. + example: alice@example.com + issuedAt: + type: string + format: date-time + description: Token issue time matching the JWT `iat` claim. + example: '2026-05-21T20:00:00Z' + expiresAt: + type: string + format: date-time + description: Token expiration time matching the JWT `exp` claim. + example: '2026-05-21T20:01:00Z' diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index 19b26f8d..6b0fc3ec 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -175,6 +175,8 @@ paths: $ref: paths/crypto/crypto_estimate-withdrawal-fee.yaml /sandbox/webhooks/test: $ref: paths/sandbox/sandbox_webhooks_test.yaml + /sandbox/oidc/token: + $ref: paths/sandbox/sandbox_oidc_token.yaml /customers/bulk/csv: $ref: paths/customers/customers_bulk_csv.yaml /customers/bulk/jobs/{jobId}: diff --git a/openapi/paths/sandbox/sandbox_oidc_token.yaml b/openapi/paths/sandbox/sandbox_oidc_token.yaml new file mode 100644 index 00000000..acf99268 --- /dev/null +++ b/openapi/paths/sandbox/sandbox_oidc_token.yaml @@ -0,0 +1,65 @@ +post: + summary: Create a sandbox OIDC token + description: > + Mint a JWT-shaped OIDC ID token for embedded-wallet OAuth sandbox flows. + Use the returned `oidcToken` anywhere the OAuth auth credential endpoints + expect an OIDC token. This endpoint only mints a mock token; it does not + create auth methods, wallets, sessions, or Turnkey state. + + This endpoint is only for the sandbox environment and will fail for + production platforms/keys. + operationId: createSandboxOidcToken + tags: + - Sandbox + security: + - BasicAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: ../../components/schemas/sandbox/SandboxOidcTokenRequest.yaml + examples: + credentialRegistration: + summary: Mint a token for OAuth credential registration + value: + provider: GOOGLE + subject: alice + credentialVerify: + summary: Mint a nonce-bound token for OAuth verification + value: + provider: GOOGLE + subject: alice + clientPublicKey: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 + email: alice@example.com + responses: + '200': + description: Sandbox OIDC token created successfully + content: + application/json: + schema: + $ref: ../../components/schemas/sandbox/SandboxOidcTokenResponse.yaml + '400': + description: Bad request + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error400.yaml + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '403': + description: Forbidden - request was made with a production platform token + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error403.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml