-
Notifications
You must be signed in to change notification settings - Fork 105
better keypair auth error message #913
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughRefactors body hash validation in handleKeypairAuth to compute the request body hash once for POST requests when a bodyHash is present, compares it to the token’s bodyHash, and throws a detailed error on mismatch with updated documentation link. Other logic remains unchanged. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant C as Client
participant S as Server
participant A as Auth Middleware
participant H as BodyHash Calculator
participant T as Token (bodyHash)
C->>S: HTTP Request (may be POST)
S->>A: Invoke handleKeypairAuth
alt POST with bodyHash in payload
A->>H: Compute request body hash
H-->>A: bodyHash(request)
A->>T: Compare bodyHash(request) vs token.bodyHash
alt Hash mismatch
A-->>S: Throw error (includes both hashes, v2 docs URL)
S-->>C: 4xx Error
else Hash match
A-->>S: Auth continues
S-->>C: Proceed
end
else Non-POST or no bodyHash
A-->>S: Skip body hash validation
S-->>C: Proceed
end
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes ✨ Finishing Touches
🧪 Generate unit tests
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/server/middleware/auth.ts (1)
513-517: Make hashing robust and stable (handle undefined/raw body, avoid stringify pitfalls)JSON.stringify(req.body) can be undefined or reorder keys; prefer raw bytes when available and fall back safely to strings/JSON. Consider:
// Replace implementation of hashRequestBody: const hashRequestBody = (req: FastifyRequest): string => { const rawBody = (req as any).rawBody; // if using fastify-raw-body or equivalent if (Buffer.isBuffer(rawBody)) { return createHash("sha256").update(rawBody).digest("hex"); } const bodyStr = typeof rawBody === "string" ? rawBody : typeof req.body === "string" ? req.body : JSON.stringify(req.body ?? {}); return createHash("sha256").update(bodyStr, "utf8").digest("hex"); };
🧹 Nitpick comments (1)
src/server/middleware/auth.ts (1)
334-340: Optional: use constant‑time comparison for hashesMitigate timing side-channels when comparing hashes.
- Add import:
import { createHash, timingSafeEqual } from "node:crypto";- Compare using Buffers:
const a = Buffer.from(computedBodyHash, "hex"); const b = Buffer.from(payload.bodyHash, "hex"); const equal = a.length === b.length && timingSafeEqual(a, b); if (!equal) { error = "The request body does not match the hash in the token. See: https://portal.thirdweb.com/engine/v2/features/keypair-authentication"; throw new Error(error); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
src/server/middleware/auth.ts(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: build
- GitHub Check: lint
🔇 Additional comments (1)
src/server/middleware/auth.ts (1)
334-340: Docs URL Verified
The v2 docs page exists and includes the bodyHash validation section as expected.
| if (req.method === "POST" && payload?.bodyHash) { | ||
| const computedBodyHash = hashRequestBody(req); | ||
| if (computedBodyHash !== payload.bodyHash) { | ||
| error = `The request body does not match the hash in the access token. See: https://portal.thirdweb.com/engine/v2/features/keypair-authentication. [hash in access token: ${payload.bodyHash}, hash computed from request: ${computedBodyHash}]`; | ||
| throw error; | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Harden bodyHash validation: handle empty bodies, avoid echoing hashes, support more HTTP methods, and throw Error objects
- JSON.stringify(undefined) can throw via createHash.update; guard for missing/empty body.
- Returning both hashes in the client-visible error leaks unnecessary detail.
- Restricting to POST misses PUT/PATCH/DELETE with bodies.
- Prefer throwing Error objects over strings for consistency.
Apply this diff within this block:
- // If `bodyHash` is provided, it must match a hash of the POST request body.
- if (req.method === "POST" && payload?.bodyHash) {
- const computedBodyHash = hashRequestBody(req);
- if (computedBodyHash !== payload.bodyHash) {
- error = `The request body does not match the hash in the access token. See: https://portal.thirdweb.com/engine/v2/features/keypair-authentication. [hash in access token: ${payload.bodyHash}, hash computed from request: ${computedBodyHash}]`;
- throw error;
- }
- }
+ // If `bodyHash` is provided, it must match a hash of the request body.
+ if (payload?.bodyHash && ["POST", "PUT", "PATCH", "DELETE"].includes(req.method)) {
+ const hasBody =
+ typeof req.body === "string" ||
+ (req.body !== null &&
+ typeof req.body === "object" &&
+ Object.keys(req.body as Record<string, unknown>).length > 0);
+ if (!hasBody) {
+ error =
+ 'Request body is missing or empty while the token includes a "bodyHash". See: https://portal.thirdweb.com/engine/v2/features/keypair-authentication';
+ throw new Error(error);
+ }
+ const computedBodyHash = hashRequestBody(req);
+ if (computedBodyHash !== payload.bodyHash) {
+ error =
+ "The request body does not match the hash in the token. See: https://portal.thirdweb.com/engine/v2/features/keypair-authentication";
+ throw new Error(error);
+ }
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (req.method === "POST" && payload?.bodyHash) { | |
| const computedBodyHash = hashRequestBody(req); | |
| if (computedBodyHash !== payload.bodyHash) { | |
| error = `The request body does not match the hash in the access token. See: https://portal.thirdweb.com/engine/v2/features/keypair-authentication. [hash in access token: ${payload.bodyHash}, hash computed from request: ${computedBodyHash}]`; | |
| throw error; | |
| } | |
| } | |
| // If `bodyHash` is provided, it must match a hash of the request body. | |
| if (payload?.bodyHash && ["POST", "PUT", "PATCH", "DELETE"].includes(req.method)) { | |
| const hasBody = | |
| typeof req.body === "string" || | |
| (req.body !== null && | |
| typeof req.body === "object" && | |
| Object.keys(req.body as Record<string, unknown>).length > 0); | |
| if (!hasBody) { | |
| error = | |
| 'Request body is missing or empty while the token includes a "bodyHash". See: https://portal.thirdweb.com/engine/v2/features/keypair-authentication'; | |
| throw new Error(error); | |
| } | |
| const computedBodyHash = hashRequestBody(req); | |
| if (computedBodyHash !== payload.bodyHash) { | |
| error = | |
| "The request body does not match the hash in the token. See: https://portal.thirdweb.com/engine/v2/features/keypair-authentication"; | |
| throw new Error(error); | |
| } | |
| } |
PR-Codex overview
This PR improves error handling in the
auth.tsmiddleware by refining the hash comparison logic for POST requests. It adds detailed information to the error message, including both the hash from the access token and the computed hash from the request.Detailed summary
bodyHash.computedBodyHashto store the hash of the request body.Summary by CodeRabbit