Skip to content

fix(auth): require lowercase, form-specific clientPublicKey hex - #1189

Draft
carsonp6 wants to merge 2 commits into
mainfrom
carson/client-public-key-patterns
Draft

carsonp6 wants to merge 2 commits into
mainfrom
carson/client-public-key-patterns

Conversation

@carsonp6

@carsonp6 carsonp6 commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Why

Grid's handlers already require a compressed clientPublicKey on passkey challenge, session refresh and OAuth verify, and an uncompressed one on wallet export. The spec disagreed. Challenge and refresh accepted either form. OAuth verify and export had no pattern. The docs still described a deprecated flow that sends an uncompressed key, which Grid now rejects.

The spec now also requires lowercase hex. The sandbox OAuth nonce is sha256 of the exact clientPublicKey string the client sends. Standard libraries emit lowercase, and Grid forwards its canonical lowercase encoding, so lowercase keeps the client's hash and Grid's matching.

What changed

Endpoint Schema clientPublicKey
POST /auth/credentials/{id}/challenge AuthCredentialChallengeRequest ^0[23][0-9a-f]{64}$, length 66
POST /auth/sessions/{id}/refresh AuthSessionRefreshRequest ^0[23][0-9a-f]{64}$, length 66
POST /auth/credentials/{id}/verify (OAuth) OauthCredentialVerifyRequestFields ^0[23][0-9a-f]{64}$, length 66
POST /internal-accounts/{id}/export InternalAccountExportRequest ^04[0-9a-f]{128}$, length 130
  • Field descriptions now say exactly what to send: lowercase hex, which form, and how long.
  • Removed the "send an uncompressed key for the deprecated legacy flow" wording from the challenge, refresh and verify schema and endpoint descriptions. Response schemas are unchanged, including encryptedSessionSigningKey.
  • The OAuth verify docs (spec plus the sandbox and authentication guides) now say the sandbox nonce is the lowercase hex SHA-256 of the clientPublicKey string exactly as sent. The OAuth verify curl examples now send a compressed key.
  • The Global Accounts guides no longer describe the uncompressed-key session flow. The client-keys guide now generates a signing key and sends it compressed; the old key-agreement samples moved to a wallet export section; the receive and decrypt steps are gone.
  • The passkey and refresh examples now send compressed lowercase keys, and the refresh payloadToSign examples show today's session-creation payload. The export examples keep the uncompressed key.
  • Regenerated openapi.yaml and mintlify/openapi.yaml with make build. make lint passes with 0 errors.

Compatibility

This is a stricter contract. An uppercase key, or the wrong form for the endpoint, now gets a 400 at request validation. Wrong-form keys were already rejected by the handlers, so the new behavior is the uppercase rejection.

🤖 Generated with Claude Code

Grid already rejects uncompressed keys on passkey challenge, session
refresh and OAuth verify, and needs an uncompressed key on wallet
export. The spec still accepted either form on challenge and refresh,
had no pattern on OAuth verify or export, and described a deprecated
uncompressed-key flow that no longer works.

Pin each request to the one form its endpoint accepts, in lowercase
hex. The sandbox OAuth nonce is sha256 of the exact clientPublicKey
string, so lowercase keeps the client's hash and Grid's matching.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@mintlify

mintlify Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
Grid 🟢 Ready View Preview Oct 15, 2026, 10:57 PM

@greptile-apps

greptile-apps Bot commented Oct 15, 2026

Copy link
Copy Markdown
Contributor

This PR does not match any of the 3 configured review trigger rules.

@vercel

vercel Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

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

3 Skipped Deployments
Project Deployment Actions Updated
grid-cards-demo Ignored Ignored Preview Oct 15, 2026 10:56pm UTC
grid-flow-builder Ignored Ignored Preview Oct 15, 2026 10:56pm UTC
grid-wallet-demo Ignored Ignored Preview Oct 15, 2026 10:56pm UTC

Request Review

@github-actions github-actions Bot added the breaking-change Introduces a breaking change to the OpenAPI spec label Oct 15, 2026
@github-actions

github-actions Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

⚠️ Breaking OpenAPI changes detected

oasdiff reports 6 error / 5 warning changes to openapi.yaml.
This PR will need approval from an API reviewer before merge.

Errors (6)

  • POST /auth/credentials/{id}/challenge — the clientPublicKey request property's maxLength was decreased to 66 [request-property-max-length-decreased].
  • POST /auth/credentials/{id}/verify — the oneOf[subschema #3: OAuth Credential Verify Request]/allOf[#/components/schemas/OauthCredentialVerifyRequestFields]/clientPublicKey request property's minLength was increased from 0 to 66 [request-property-min-length-increased].
  • POST /auth/credentials/{id}/verify — added the pattern ^0[23][0-9a-f]{64}$ to the request property oneOf[subschema #3: OAuth Credential Verify Request]/allOf[#/components/schemas/OauthCredentialVerifyRequestFields]/clientPublicKey [request-property-pattern-added]. This is a breaking change because adding a pattern restriction to a previously unrestricted parameter will reject values that were previously accepted, breaking existing clients
  • POST /auth/sessions/{id}/refresh — the clientPublicKey request property's minLength was increased from 0 to 66 [request-property-min-length-increased].
  • POST /internal-accounts/{id}/export — the clientPublicKey request property's minLength was increased from 0 to 130 [request-property-min-length-increased].
  • POST /internal-accounts/{id}/export — added the pattern ^04[0-9a-f]{128}$ to the request property clientPublicKey [request-property-pattern-added]. This is a breaking change because adding a pattern restriction to a previously unrestricted parameter will reject values that were previously accepted, breaking existing clients

Warnings (5)

Show sample
  • POST /auth/credentials/{id}/challenge — changed the pattern of the request property clientPublicKey from ^(0[23][0-9a-fA-F]{64}|04[0-9a-fA-F]{128})$ to ^0[23][0-9a-f]{64}$ [request-property-pattern-changed]. This is a warning because adding or changing a pattern may restrict the accepted values and break existing clients. For pattern changes, it is difficult to automatically analyze if the new pattern is a superset of the previous pattern (e.g. changed from '[0-9]+' to '[0-9]*')
  • POST /auth/credentials/{id}/verify — the oneOf[subschema #3: OAuth Credential Verify Request]/allOf[#/components/schemas/OauthCredentialVerifyRequestFields]/clientPublicKey request property's maxLength was set to 66 [request-property-max-length-set]. This is a warning because sometimes it is required to be set. But good clients should be checked to support this restriction before such change in specification.
  • POST /auth/sessions/{id}/refresh — the clientPublicKey request property's maxLength was set to 66 [request-property-max-length-set]. This is a warning because sometimes it is required to be set. But good clients should be checked to support this restriction before such change in specification.
  • POST /auth/sessions/{id}/refresh — changed the pattern of the request property clientPublicKey from ^(0[23][0-9a-fA-F]{64}|04[0-9a-fA-F]{128})$ to ^0[23][0-9a-f]{64}$ [request-property-pattern-changed]. This is a warning because adding or changing a pattern may restrict the accepted values and break existing clients. For pattern changes, it is difficult to automatically analyze if the new pattern is a superset of the previous pattern (e.g. changed from '[0-9]+' to '[0-9]*')
  • POST /internal-accounts/{id}/export — the clientPublicKey request property's maxLength was set to 130 [request-property-max-length-set]. This is a warning because sometimes it is required to be set. But good clients should be checked to support this restriction before such change in specification.

Detected by oasdiff. Full report: job summary or the oasdiff-report artifact.

…e guides

Grid no longer seals a session signing key to an uncompressed
clientPublicKey, so the guides' decrypt steps and 04-prefixed login
examples no longer work. The client key pair is now always a signing
key sent compressed in lowercase hex, and its private key is the
session signing key.

- client-keys: step 1 generates a signing key and emits the compressed
  form; the old ECDH samples move to a wallet export key pair section;
  the receive and decrypt steps are gone, so signing is now step 2.
- authentication, sessions, sandbox and concepts pages: session
  responses carry no key material; passkey and refresh examples send a
  compressed key.
- Refresh payloadToSign examples show the session-creation payload Grid
  returns today.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

This branch was successfully deployed

1 active deployment
staging - mintlify — 0ae5212a Deployed Oct 15, 2026 by mintlify[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking-change Introduces a breaking change to the OpenAPI spec

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant