✨ server: add auth for wallet extensions#1070
Conversation
🦋 Changeset detectedLatest commit: 73aa075 The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughThis PR implements wallet-extension bearer token authentication for iOS card provisioning. It adds token creation/verification utilities, extends the authentication endpoint to conditionally generate tokens on iOS, introduces a multi-path cardAuth middleware supporting cookies, sessions, and bearer tokens, integrates the card endpoint with the new middleware, provides comprehensive test coverage for all auth flows, ensures the client sends platform headers, and publishes release notes. ChangesWallet Extension Authentication and Card Provisioning
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Suggested reviewers
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
This pull request introduces wallet extension authentication for iOS clients. It adds support for generating and verifying a wallet extension bearer token, updates the authentication endpoints to return this token for iOS platforms, and modifies the authentication middleware to support bearer token authentication for card provisioning. A review comment identifies an issue in the authentication middleware where the scope query parameter, which can be an array, is not correctly checked for the "provisioning" value, potentially causing valid requests to be rejected. A code suggestion is provided to handle both string and array types for scope.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
There was a problem hiding this comment.
Actionable comments posted: 3
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: b1dd2131-b28c-4f77-b7d7-30dd62e2c176
📒 Files selected for processing (10)
.changeset/brave-otters-serve.md.changeset/clever-ravens-send.mdserver/api/auth/authentication.tsserver/api/card.tsserver/middleware/auth.tsserver/test/api/auth.test.tsserver/test/api/card-wallet-extension.test.tsserver/test/middleware/auth-wallet-extension.test.tsserver/utils/walletExtensionToken.tssrc/utils/server.ts
81ae104 to
e9577a8
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1070 +/- ##
==========================================
+ Coverage 72.27% 72.60% +0.33%
==========================================
Files 248 249 +1
Lines 9827 10163 +336
Branches 3162 3310 +148
==========================================
+ Hits 7102 7379 +277
- Misses 2463 2507 +44
- Partials 262 277 +15
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
e9577a8 to
efad3c9
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: efad3c91db
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 9758bffd-2744-4676-a689-11cae77a0c40
📒 Files selected for processing (10)
.changeset/brave-otters-serve.md.changeset/clever-ravens-send.mdserver/api/auth/authentication.tsserver/api/card.tsserver/middleware/auth.tsserver/test/api/auth.test.tsserver/test/api/card-wallet-extension.test.tsserver/test/middleware/auth-wallet-extension.test.tsserver/utils/walletExtensionToken.tssrc/utils/server.ts
44dcd45 to
41ed27e
Compare
abf3473 to
7168e35
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
server/api/card.ts (1)
253-285:⚠️ Potential issue | 🟠 Major | ⚡ Quick winAdd the 401 response to this route contract.
cardAuth()can now return401 { code: "unauthorized", legacy: "unauthorized" }, but this operation still documents only 200/400/403/404. That leaves the generated OpenAPI out of sync with the new cookie/session/bearer auth behavior.Suggested contract update
responses: { + 401: { + description: "Unauthorized", + content: { + "application/json": { + schema: resolver( + object({ code: literal("unauthorized"), legacy: literal("unauthorized") }), + { errorMode: "ignore" }, + ), + }, + }, + }, description: "Card information", content: { "application/json": { schema: resolver(CardResponse, { errorMode: "ignore" }) } }, },
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: bcce92de-2a30-403f-8904-daba2945abd5
📒 Files selected for processing (13)
.changeset/brave-otters-serve.md.changeset/clever-ravens-send.mdserver/api/auth/authentication.tsserver/api/card.tsserver/middleware/cardAuth.tsserver/script/openapi.tsserver/test/api/auth.test.tsserver/test/api/card-better-auth.test.tsserver/test/api/card-wallet-extension.test.tsserver/test/middleware/cardAuth.test.tsserver/test/mocks/auth.tsserver/utils/walletExtension.tssrc/utils/server.ts
479f1fc to
bf7df95
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bf7df95467
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
bf7df95 to
f801bbf
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f801bbf97b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
0e8ae6a to
6511c9d
Compare
7ce203f to
8f4faed
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8f4faedaa6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
8f4faed to
f5b8840
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f5b8840869
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
f5b8840 to
b81e144
Compare
|
@coderabbitai update the PR's description |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
gh pr edit 1070 --repo exactly/exa --body "## ✨ Add Auth for Wallet Extensions
### Summary
This PR adds iOS Apple Wallet Extension authentication support to the server, allowing wallet extensions to obtain and use bearer tokens for provisioning access. It also updates the mobile client to send a \`Client-Platform\` header.
---
### Changes
#### Server
**New: Wallet Extension JWT Utilities** (\`server/utils/walletExtension.ts\`)
- \`createToken(credentialId, expires)\`: Signs an HS256 JWT (via \`jose\`) with audience \`\"wallet-extension\"\`, including \`credentialId\` and \`scope: \"card:provisioning\"\`.
- \`verifyToken(token)\`: Verifies the JWT, validates the payload with Valibot, and returns \`{ credentialId, scope }\` or \`null\` on failure.
**Updated: Authentication Endpoint** (\`server/api/auth/authentication.ts\`)
- Accepts an optional \`Client-Platform\` header (\`ios\` | \`android\`).
- On successful SIWE or WebAuthn authentication, if \`platform === \"ios\"\`, returns \`walletExtensionToken\` and \`walletExtensionTokenExpires\` in the response.
- The \`Authentication\` schema now includes optional \`walletExtensionToken?: string\` and \`walletExtensionTokenExpires?: number\` fields.
**New: Card Auth Middleware** (\`server/middleware/cardAuth.ts\`)
- Replaces \`auth()\` on \`GET /api/card\` to support three authentication paths:
1. **Signed cookie** (\`credential_id\`): reads and attaches \`credentialId\` directly.
2. **Better Auth session** (\`sessionid\` header): resolves the user's primary or single wallet address to a credential.
3. **Bearer token** (wallet extension): accepted only when \`scope=provisioning\` is the sole query parameter and no \`sessionid\` header is present; verifies via \`verifyToken\`.
- Returns \`401 { code: \"unauthorized\", legacy: \"unauthorized\" }\` on any auth failure.
**Updated: Card Endpoint** (\`server/api/card.ts\`)
- Uses \`cardAuth()\` middleware instead of \`auth()\`.
- OpenAPI security now includes \`walletExtensionAuth\` alongside \`credentialAuth\` and \`siweAuth\`.
- Documents that wallet-extension bearer access is accepted only when \`scope=provisioning\` is the only scope and \`sessionid\` is absent.
**Updated: OpenAPI Spec** (\`server/script/openapi.ts\`)
- Adds \`walletExtensionAuth\` HTTP bearer security scheme to \`components.securitySchemes\`.
#### Mobile
**Updated: Server Client** (\`src/utils/server.ts\`)
- The \`hc\` fetch override now always builds a \`Headers\` object and unconditionally sets \`Client-Platform\` for \`ios\`/\`android\` platforms before determining mini-app vs. native fetch path.
- Ensures \`Client-Platform\` is included in non-mini-app requests as well.
---
### Tests
| Test file | Coverage |
|-----------|----------|
| \`server/test/api/auth.test.ts\` | iOS WebAuthn/SIWE returns wallet extension token fields; Android omits them; missing header omits them |
| \`server/test/api/card-wallet-extension.test.ts\` | Bearer token grants provisioning access; correct JSON payload; \`getPIN\`/\`getSecrets\` not called |
| \`server/test/api/card-better-auth.test.ts\` | Session-based auth via \`sessionid\` returns full card data |
| \`server/test/middleware/cardAuth.test.ts\` | Cookie, better-auth, and bearer auth paths; all rejection cases (bad scope, expired token, mixed scopes, missing token, etc.) |
| \`server/test/mocks/auth.ts\` | Added \`cardAuth\` mock mirroring \`auth\` mock behavior |
---
### Testing Commands
\`\`\`bash
pnpm nx test:ts server
pnpm nx test:eslint server
pnpm nx test:vi server -- test/api/auth.test.ts test/api/card-wallet-extension.test.ts test/middleware/auth-wallet-extension.test.ts
\`\`\`
---
### Changesets
- \`@exactly/server\`: patch — ✨ add wallet extension auth
- \`@exactly/mobile\`: patch — ✨ send client platform header"Length of output: 4641 🏁 Script executed: #!/bin/bash
set -euo pipefail
cat > /tmp/pr_body.md << 'PREOF'
## ✨ Add Auth for Wallet Extensions
### Summary
This PR adds iOS Apple Wallet Extension authentication support to the server, allowing wallet extensions to obtain and use bearer tokens for provisioning access. It also updates the mobile client to send a `Client-Platform` header.
---
### Changes
#### Server
**New: Wallet Extension JWT Utilities** (`server/utils/walletExtension.ts`)
- `createToken(credentialId, expires)`: Signs an HS256 JWT (via `jose`) with audience `"wallet-extension"`, including `credentialId` and `scope: "card:provisioning"`.
- `verifyToken(token)`: Verifies the JWT, validates the payload with Valibot, and returns `{ credentialId, scope }` or `null` on failure.
**Updated: Authentication Endpoint** (`server/api/auth/authentication.ts`)
- Accepts an optional `Client-Platform` header (`ios` | `android`).
- On successful SIWE or WebAuthn authentication, if `platform === "ios"`, returns `walletExtensionToken` and `walletExtensionTokenExpires` in the response.
- The `Authentication` schema now includes optional `walletExtensionToken?: string` and `walletExtensionTokenExpires?: number` fields.
**New: Card Auth Middleware** (`server/middleware/cardAuth.ts`)
- Replaces `auth()` on `GET /api/card` to support three authentication paths:
1. **Signed cookie** (`credential_id`): reads and attaches `credentialId` directly.
2. **Better Auth session** (`sessionid` header): resolves the user's primary or single wallet address to a credential.
3. **Bearer token** (wallet extension): accepted only when `scope=provisioning` is the sole query parameter and no `sessionid` header is present; verifies via `verifyToken`.
- Returns `401 { code: "unauthorized", legacy: "unauthorized" }` on any auth failure.
**Updated: Card Endpoint** (`server/api/card.ts`)
- Uses `cardAuth()` middleware instead of `auth()`.
- OpenAPI security now includes `walletExtensionAuth` alongside `credentialAuth` and `siweAuth`.
- Documents that wallet-extension bearer access is accepted only when `scope=provisioning` is the only scope and `sessionid` is absent.
**Updated: OpenAPI Spec** (`server/script/openapi.ts`)
- Adds `walletExtensionAuth` HTTP bearer security scheme to `components.securitySchemes`.
#### Mobile
**Updated: Server Client** (`src/utils/server.ts`)
- The `hc` fetch override now always builds a `Headers` object and unconditionally sets `Client-Platform` for `ios`/`android` platforms before determining mini-app vs. native fetch path.
- Ensures `Client-Platform` is included in non-mini-app requests as well.
---
### Tests
| Test file | Coverage |
|-----------|----------|
| `server/test/api/auth.test.ts` | iOS WebAuthn/SIWE returns wallet extension token fields; Android omits them; missing header omits them |
| `server/test/api/card-wallet-extension.test.ts` | Bearer token grants provisioning access; correct JSON payload; `getPIN`/`getSecrets` not called |
| `server/test/api/card-better-auth.test.ts` | Session-based auth via `sessionid` returns full card data |
| `server/test/middleware/cardAuth.test.ts` | Cookie, better-auth, and bearer auth paths; all rejection cases (bad scope, expired token, mixed scopes, missing token, etc.) |
| `server/test/mocks/auth.ts` | Added `cardAuth` mock mirroring `auth` mock behavior |
---
### Testing Commands
```bash
pnpm nx test:ts server
pnpm nx test:eslint server
pnpm nx test:vi server -- test/api/auth.test.ts test/api/card-wallet-extension.test.ts test/middleware/auth-wallet-extension.test.tsChangesets
gh pr edit 1070 --repo exactly/exa --body-file /tmp/pr_body.md Changesets
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b81e1446d3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
e1c5ef3 to
8b803a2
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8b803a297a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
af9225a to
90480b7
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 90480b7c5e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
a151c1e to
9b8fb96
Compare
9b8fb96 to
c7efd7a
Compare
c7efd7a to
73aa075
Compare
Summary
GET /api/card?scope=provisioningClient-Platformheader from the mobile client while preserving existing miniappClient-FidbehaviorTesting
pnpm nx test:ts serverpnpm nx test:eslint serverpnpm nx test:vi server -- test/api/auth.test.ts test/api/card-wallet-extension.test.ts test/middleware/auth-wallet-extension.test.tsSummary by CodeRabbit
Release Notes
New Features
Tests