Skip to content

docs: explain realistic OIDC sandbox tokens#487

Open
DhruvPareek wants to merge 1 commit into
mainfrom
dp/docs-realistic-oidc-sandbox
Open

docs: explain realistic OIDC sandbox tokens#487
DhruvPareek wants to merge 1 commit into
mainfrom
dp/docs-realistic-oidc-sandbox

Conversation

@DhruvPareek
Copy link
Copy Markdown
Contributor

@DhruvPareek DhruvPareek commented May 21, 2026

Summary

  • Update Global Accounts sandbox docs to explain that OAuth no longer uses the fixed sandbox-valid-oidc-token value.
  • Document the realistic sandbox OIDC token requirements: JWT-shaped token, supported issuer, aud/sub, fresh iat/exp, stored iss/aud/sub identity matching, and nonce = sha256(clientPublicKey) on verify.
  • Add a copyable Node example for generating a sandbox OIDC token.
  • Update the auth OpenAPI descriptions and rebuild the bundled openapi.yaml and mintlify/openapi.yaml.

Stack

Context

This matches the Grid behavior from the OIDC auth-method identity stack:

  • dp/grid-oidc-auth-method-identity
  • dp/grid-realistic-oidc-sandbox
  • dp/grid-verify-oauth-oidc-identity

The important customer-facing change is that sandbox skips real IdP signature verification, but it now validates the same identity/freshness shape integrators need in production.

Test Plan

  • make lint
  • git diff --check

@vercel
Copy link
Copy Markdown

vercel Bot commented May 21, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
grid-flow-builder Ready Ready Preview, Comment May 21, 2026 10:02pm

Request Review

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 21, 2026

✱ Stainless preview builds for grid

This PR will update the grid SDKs with the following commit messages.

cli

chore(internal): regenerate SDK with no functional changes

csharp

docs(api): update OAuth credential verification documentation in auth

go

docs(api): clarify OAuth token verification in authcredential

kotlin

docs(api): update OAuth credential verification documentation

openapi

docs(api): clarify OAuth token validation requirements for auth credentials

php

docs(api): update OAuth credential verification documentation

python

docs(api): clarify OAuth token requirements in credentials methods

ruby

docs(api): update oidc_token documentation in OAuth credential models

typescript

docs(api): update OAuth token requirements in auth credentials

Edit this comment to update them. They will appear in their respective SDK's changelogs.

grid-openapi studio · code · diff

Your SDK build had at least one "note" diagnostic, but this did not represent a regression.
generate ✅

grid-ruby studio · code · diff

Your SDK build had at least one "warning" diagnostic, but this did not represent a regression.
generate ⚠️build ✅lint ❗test ✅

grid-python studio · code · diff

Your SDK build had at least one "note" diagnostic, but this did not represent a regression.
generate ✅build ✅lint ✅test ✅

pip install https://pkg.stainless.com/s/grid-python/f27d9f91ea32921bb83824930c13def80d1f686d/grid-0.0.1-py3-none-any.whl
grid-go studio · code · diff

Your SDK build had at least one "error" diagnostic, but this did not represent a regression.
generate ❗build ✅lint ❗test ❗

go get github.com/stainless-sdks/grid-go@37ff39bcf907bbc7250defad779b094d0898518f
⚠️ grid-kotlin studio · code · diff

Your SDK build had a failure in the test CI job, which is a regression from the base state.
generate ✅build ✅lint ✅test ❗ (prev: test ✅)

grid-csharp studio · code · diff

Your SDK build had at least one "error" diagnostic, but this did not represent a regression.
generate ❗build ❗lint ❗test ❗

grid-php studio · code · diff

Your SDK build had at least one "error" diagnostic, but this did not represent a regression.
generate ❗lint ❗test ✅

grid-cli studio · code · diff

Your SDK build had at least one "warning" diagnostic, but this did not represent a regression.
generate ⚠️build ⏭️ (prev: build ❗) → lint ⏭️ (prev: lint ❗) → test ❗

grid-typescript studio · code · diff

Your SDK build had at least one "note" diagnostic, but this did not represent a regression.
generate ✅build ❗lint ❗test ❗


This comment is auto-generated by GitHub Actions and is automatically kept up to date as you push.
If you push custom code to the preview branch, re-run this workflow to update the comment.
Last updated: 2026-05-21 21:01:46 UTC

@DhruvPareek DhruvPareek force-pushed the dp/docs-realistic-oidc-sandbox branch from 2c94a1c to 907c2cd Compare May 21, 2026 22:02
@DhruvPareek DhruvPareek changed the base branch from docs-auth-pdf-endpoint-followups to main May 21, 2026 22:02
Copy link
Copy Markdown
Contributor Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@DhruvPareek DhruvPareek marked this pull request as ready for review May 21, 2026 22:08
@DhruvPareek DhruvPareek requested a review from pengying May 21, 2026 22:08
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 21, 2026

Greptile Summary

This PR updates the Global Accounts sandbox and OpenAPI docs to replace the old fixed sandbox-valid-oidc-token magic value with the new realistic OIDC token model, where the sandbox validates JWT structure, claim freshness, credential identity, and (on verify) a nonce = sha256(clientPublicKey) binding — while skipping real IdP signature verification.

  • Sandbox testing page & magic snippet — rewrites the OAuth section to list all required claims for both create and verify, adds a copyable Node.js snippet that generates a compliant sandbox JWT with the correct nonce, and deprecates the old literal token.
  • OpenAPI source schemas and path files — updates oidcToken descriptions in OauthCredentialCreateRequestFields, OauthCredentialVerifyRequestFields, and both auth path files to document the production-vs-sandbox split and the new identity/nonce checks; regenerated bundles (openapi.yaml, mintlify/openapi.yaml) are included.
  • Authentication snippet — adds identity-matching prose and a <Note> callout pointing to the sandbox testing page.

Confidence Score: 3/5

Docs-only change; no application logic is touched. The main risk is integrators picking up the wrong example shape from the spec.

The OpenAPI example JWT for OauthCredentialVerifyRequestFields has no nonce field, directly contradicting the description text that sandbox requires one. An integrator who uses this schema example as a starting point in sandbox will receive a 401 nonce failure with no clear pointer to the cause. The nonce hash encoding (hex vs. base64) is also undocumented in prose — only visible in the Node.js code block — which could trip up developers writing equivalent code in other languages. Everything else in the PR is accurate and internally consistent.

openapi/components/schemas/auth/OauthCredentialVerifyRequestFields.yaml — the verify example JWT needs a nonce claim to match the documented sandbox requirement

Important Files Changed

Filename Overview
mintlify/snippets/sandbox-global-account-magic.mdx Core sandbox docs rewrite — replaces fixed magic token with JWT-shaped OIDC requirements and adds a Node.js code example; nonce hash encoding is unspecified in prose
openapi/components/schemas/auth/OauthCredentialVerifyRequestFields.yaml Updated oidcToken description adds sandbox nonce requirement; the static example JWT has no nonce claim, which contradicts the sandbox requirement for verify
openapi/components/schemas/auth/OauthCredentialCreateRequestFields.yaml Updated oidcToken description to document production vs sandbox validation rules; changes are accurate and no nonce is required here
openapi/paths/auth/auth_credentials_{id}_verify.yaml Operation description and 401 response updated to reflect identity/nonce checks; the OAuth verify example request still uses the non-nonce JWT example value
openapi/paths/auth/auth_credentials.yaml 400 and 401 response descriptions refined to clarify OAUTH-specific error cases; changes are accurate
mintlify/snippets/global-accounts/authentication.mdx Added identity-matching prose and a sandbox Note callout with a link to the sandbox testing page; clear and accurate
mintlify/global-accounts/platform-tools/sandbox-testing.mdx Minor description updates to reflect OIDC flow change; accurate
mintlify/global-accounts/index.mdx One-line card description update to reflect new OIDC sandbox behavior; accurate

Sequence Diagram

sequenceDiagram
    participant Dev as Integrator
    participant SB as Grid Sandbox

    Note over Dev,SB: OAuth Credential Registration (POST /auth/credentials)
    Dev->>Dev: "Generate JWT with iss, aud, sub, iat, exp (signature = dummy value)"
    Dev->>SB: "POST /auth/credentials { type: OAUTH, oidcToken }"
    SB->>SB: Validate JWT structure and iss support
    SB->>SB: Verify iat freshness (60s window)
    SB->>SB: Store iss + aud + sub as credential identity
    SB-->>Dev: "200 { id: AuthMethod:... }"

    Note over Dev,SB: OAuth Credential Verification (POST /auth/credentials/{id}/verify)
    Dev->>Dev: Generate ephemeral P-256 key pair
    Dev->>Dev: "Compute nonce = sha256(clientPublicKey) hex-encoded"
    Dev->>Dev: Generate fresh JWT with iss, aud, sub, iat, exp, nonce
    Dev->>SB: "POST /auth/credentials/{id}/verify { type: OAUTH, oidcToken, clientPublicKey }"
    SB->>SB: Validate JWT structure and iss support
    SB->>SB: Verify iat freshness (60s window)
    SB->>SB: Match iss + aud + sub against stored credential identity
    SB->>SB: "Verify nonce == sha256(clientPublicKey)"
    SB->>SB: Encrypt session signing key to clientPublicKey (HPKE)
    SB-->>Dev: "200 { encryptedSessionSigningKey, expiresAt }"
Loading

Fix All in Claude Code

Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
mintlify/snippets/sandbox-global-account-magic.mdx:68
**`nonce` hash encoding not specified — developers not using the Node.js example may compute it incorrectly**

The prose says `nonce` must equal `sha256(clientPublicKey)` but doesn't say the output is hex-encoded. The code example uses `.digest("hex")`, producing a lowercase hex string. A developer writing a Python or Go integration might reach for base64 or raw bytes instead, producing a nonce the backend won't match, and getting a 401 with no obvious pointer to the encoding mismatch. Specifying "(hex-encoded)" inline removes the ambiguity.

```suggestion
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)` (hex-encoded lowercase), where `clientPublicKey` is the exact hex public key sent in the verify request.
```

### Issue 2 of 2
openapi/components/schemas/auth/OauthCredentialVerifyRequestFields.yaml:24
**Verify example JWT is missing the `nonce` claim now required in sandbox**

The static `example` value shared between create and verify schemas has no `nonce` field in its payload. The description directly above it states that sandbox requires `nonce = sha256(clientPublicKey)` for verify. An integrator who models their token on this example and tests in sandbox will immediately get a 401 nonce-mismatch error with no obvious clue why, since the example shape itself passes no nonce. The same example is intentionally correct for the create operation (where nonce is not required), but a verify-specific example — or a note on the example — is needed to avoid this mismatch.

Reviews (1): Last reviewed commit: "docs: explain realistic OIDC sandbox tok..." | Re-trigger Greptile

- `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

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.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 nonce hash encoding not specified — developers not using the Node.js example may compute it incorrectly

The prose says nonce must equal sha256(clientPublicKey) but doesn't say the output is hex-encoded. The code example uses .digest("hex"), producing a lowercase hex string. A developer writing a Python or Go integration might reach for base64 or raw bytes instead, producing a nonce the backend won't match, and getting a 401 with no obvious pointer to the encoding mismatch. Specifying "(hex-encoded)" inline removes the ambiguity.

Suggested change
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.
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)` (hex-encoded lowercase), where `clientPublicKey` is the exact hex public key sent in the verify request.
Prompt To Fix With AI
This is a comment left during a code review.
Path: mintlify/snippets/sandbox-global-account-magic.mdx
Line: 68

Comment:
**`nonce` hash encoding not specified — developers not using the Node.js example may compute it incorrectly**

The prose says `nonce` must equal `sha256(clientPublicKey)` but doesn't say the output is hex-encoded. The code example uses `.digest("hex")`, producing a lowercase hex string. A developer writing a Python or Go integration might reach for base64 or raw bytes instead, producing a nonce the backend won't match, and getting a 401 with no obvious pointer to the encoding mismatch. Specifying "(hex-encoded)" inline removes the ambiguity.

```suggestion
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)` (hex-encoded lowercase), where `clientPublicKey` is the exact hex public key sent in the verify request.
```

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code

be JWT-shaped with supported `iss`, non-empty `aud` and `sub`, numeric
`iat` and `exp`, and a `nonce` equal to `sha256(clientPublicKey)`, but
the signature segment may be a dummy value.
example: eyJhbGciOiJSUzI1NiIsImtpZCI6ImFiYzEyMyIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJzdWIiOiIxMTIyMzM0NDU1IiwiYXVkIjoiMTIzNDU2Ny5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsImVtYWlsIjoidXNlckBleGFtcGxlLmNvbSIsImlhdCI6MTc0NjczNjUwOSwiZXhwIjoxNzQ2NzQwMTA5fQ.signature
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Verify example JWT is missing the nonce claim now required in sandbox

The static example value shared between create and verify schemas has no nonce field in its payload. The description directly above it states that sandbox requires nonce = sha256(clientPublicKey) for verify. An integrator who models their token on this example and tests in sandbox will immediately get a 401 nonce-mismatch error with no obvious clue why, since the example shape itself passes no nonce. The same example is intentionally correct for the create operation (where nonce is not required), but a verify-specific example — or a note on the example — is needed to avoid this mismatch.

Prompt To Fix With AI
This is a comment left during a code review.
Path: openapi/components/schemas/auth/OauthCredentialVerifyRequestFields.yaml
Line: 24

Comment:
**Verify example JWT is missing the `nonce` claim now required in sandbox**

The static `example` value shared between create and verify schemas has no `nonce` field in its payload. The description directly above it states that sandbox requires `nonce = sha256(clientPublicKey)` for verify. An integrator who models their token on this example and tests in sandbox will immediately get a 401 nonce-mismatch error with no obvious clue why, since the example shape itself passes no nonce. The same example is intentionally correct for the create operation (where nonce is not required), but a verify-specific example — or a note on the example — is needed to avoid this mismatch.

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants