Skip to content

feat: accept compressed clientPublicKey on passkey challenge + oauth verify - #803

Closed
carsonp6 wants to merge 1 commit into
mainfrom
passkey-clientpublickey-accept-compressed
Closed

feat: accept compressed clientPublicKey on passkey challenge + oauth verify#803
carsonp6 wants to merge 1 commit into
mainfrom
passkey-clientpublickey-accept-compressed

Conversation

@carsonp6

@carsonp6 carsonp6 commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Why

Knob-ON passkey/oauth login (STAMP_LOGIN / OAUTH_LOGIN) registers the client-supplied clientPublicKey directly as the session signing key instead of sealing an encryptedSessionSigningKey back to it. That session key is stored and matched in compressed SEC1 form, so a client that sends the uncompressed key fails the first session-stamped call with 401 "Invalid wallet signature." against real infra. (Sandbox accepts both, so it only bit production; OTP login already sends compressed and works.)

The AuthCredentialChallengeRequest.clientPublicKey schema pins pattern: ^04[0-9a-fA-F]{128}$ + minLength/maxLength: 130, so the generated SDKs reject a compressed key outright for the passkey challenge.

What

  • AuthCredentialChallengeRequest.clientPublicKey: accept either encoding — pattern: ^(04[0-9a-fA-F]{128}|0[23][0-9a-fA-F]{64})$, minLength: 66. Description broadened to describe both encodings.
  • OauthCredentialVerifyRequestFields.clientPublicKey: description broadened to note the compressed encoding is accepted (no pattern was set, so this is doc-only).
  • The legacy HPKE-target bodies (InternalAccountExportRequest, AuthSessionRefreshRequest) are unchanged — they still require the uncompressed 65-byte point they seal credentials to.

Backwards-compatible: existing uncompressed clients stay valid.

Downstream

The webdev backend already accepts both encodings server-side (hand-rolled validator). After this merges, the vendored SDK in lightsparkdev/webdev (grid-api/) needs a regen (./update_schema.sh) so the generated model validators pick up the relaxed constraint. Left the info.version (2025-10-13) untouched — bump per the usual release process if required.

🤖 Generated with Claude Code

@vercel

vercel Bot commented Aug 5, 2026

Copy link
Copy Markdown

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

2 Skipped Deployments
Project Deployment Actions Updated (UTC)
grid-flow-builder Ignored Ignored Aug 5, 2026 10:13pm
grid-wallet-demo Ignored Ignored Aug 5, 2026 10:13pm

Request Review

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

✱ Stainless preview builds for grid

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

cli

docs(api): update client-public-key parameter description in auth credential challenge

go

docs(api): update clientPublicKey documentation in auth credential challenge

kotlin

docs(api): update clientPublicKey description in auth credentials

openapi

fix(types): support compressed P-256 keys in clientPublicKey fields

php

docs(api): update clientPublicKey parameter description in auth credentials

python

docs(api): update client_public_key parameter description in credentials challenge

ruby

docs(api): update client_public_key parameter description in auth credentials

typescript

docs(api): update clientPublicKey parameter description in auth credentials challenge

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

⚠️ grid-typescript studio · code · diff

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

npm install https://pkg.stainless.com/s/grid-typescript/cdf170292d9485c9875623ad4b55f2559b25cd0d/dist.tar.gz
grid-openapi studio · code · diff

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

grid-ruby studio · code · diff

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

grid-go studio · code · diff

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

go get github.com/stainless-sdks/grid-go@120338f55ed31fb9f53905114944de40cc893dae
grid-kotlin 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 a failure in the lint CI job, which is a regression from the base state.
generate ✅build ✅ (prev: build ⏭️) → lint ❗ (prev: lint ⏭️) → test ❗

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

Your SDK build had at least one "note" 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 ❗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-08-10 19:03:22 UTC

@carsonp6
carsonp6 marked this pull request as ready for review August 10, 2026 18:54
@greptile-apps

greptile-apps Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR broadens the passkey challenge contract to accept compressed or uncompressed P-256 public keys and updates OAuth verification documentation accordingly.

  • Allows 66-character compressed SEC1 keys in AuthCredentialChallengeRequest.
  • Broadens descriptions for passkey challenge and OAuth verification key handling.
  • Currently changes only the generated bundle rather than the modular OpenAPI sources.

Confidence Score: 4/5

The PR should not merge until the compressed-key changes are moved into the modular OpenAPI source and the generated artifacts are rebuilt.

The new validation itself accepts both intended encodings, but it was applied only to a generated artifact, so the repository build regenerates the old contract and detects an out-of-sync bundle.

Files Needing Attention: openapi.yaml and the corresponding auth schemas under openapi/components/schemas/auth/

Important Files Changed

Filename Overview
openapi.yaml Relaxes the bundled clientPublicKey schema correctly, but the generated file will be reverted by the unchanged modular sources and causes the OpenAPI synchronization check to fail.
Prompt To Fix All With AI
### Issue 1
openapi.yaml:22857-22858
**Generated schema source remains stale**

When the OpenAPI build or lint workflow regenerates this bundle, the unchanged modular auth schemas restore the old uncompressed-only definition, causing the consistency check to fail and preventing the compressed-key contract from surviving regeneration.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "feat: accept compressed clientPublicKey ..." | Re-trigger Greptile

Comment thread openapi.yaml
Comment on lines +22857 to +22858
pattern: ^(04[0-9a-fA-F]{128}|0[23][0-9a-fA-F]{64})$
minLength: 66

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 Generated schema source remains stale

When the OpenAPI build or lint workflow regenerates this bundle, the unchanged modular auth schemas restore the old uncompressed-only definition, causing the consistency check to fail and preventing the compressed-key contract from surviving regeneration.

Context Used: CLAUDE.md (source)

Knowledge Base Used: OpenAPI Spec Core: Structure, Build, and Shared Schemas

Prompt To Fix With AI
This is a comment left during a code review.
Path: openapi.yaml
Line: 22857-22858

Comment:
**Generated schema source remains stale**

When the OpenAPI build or lint workflow regenerates this bundle, the unchanged modular auth schemas restore the old uncompressed-only definition, causing the consistency check to fail and preventing the compressed-key contract from surviving regeneration.

**Context Used:** CLAUDE.md ([source](https://github.com/lightsparkdev/grid-api/blob/main/CLAUDE.md))

**Knowledge Base Used:** [OpenAPI Spec Core: Structure, Build, and Shared Schemas](https://app.greptile.com/lightspark/-/custom-context/knowledge-base/lightsparkdev/grid-api/-/docs/openapi-spec-core.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

…uth verify

The auth-credential challenge (`PASSKEY`) and oauth verify take
`clientPublicKey` as an ephemeral P-256 key. When Grid registers that key
directly as the session signing key (rather than sealing an
`encryptedSessionSigningKey` back to it), the key must be the compressed
SEC1 encoding — that is the form the session key is stored and matched in,
and an uncompressed key is rejected on the first session-stamped call.

Relax the challenge `clientPublicKey` to accept either encoding
(`^(04[0-9a-fA-F]{128}|0[23][0-9a-fA-F]{64})$`, minLength 66) and broaden
both descriptions. The legacy HPKE-target request bodies (export, session
refresh) keep requiring the uncompressed 65-byte point they seal to.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@carsonp6
carsonp6 force-pushed the passkey-clientpublickey-accept-compressed branch from 8eca11e to 7744316 Compare August 10, 2026 18:57

Copy link
Copy Markdown
Contributor Author

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

@carsonp6 carsonp6 closed this Aug 10, 2026
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.

1 participant