fix(auth): add api key auth via sha256 hash lookup#4266
fix(auth): add api key auth via sha256 hash lookup#4266TheodoreSpeaks merged 5 commits intostagingfrom
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
|
@BugBot review |
PR SummaryMedium Risk Overview API key creation now persists Adds Reviewed by Cursor Bugbot for commit 8216bad. Bugbot is set up for automated code reviews on this repo. Configure here. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 335d662. Configure here.
Greptile SummaryThis PR replaces the inefficient full-table-scan + AES-GCM-decrypt-loop API key authentication with a single indexed Confidence Score: 5/5Safe to merge — all findings are P2 style/comment improvements with no correctness impact The auth logic is well-structured and the fast path, fallback, scope gates, and expiry checks are all correct. All remaining comments are P2 (misleading JSDoc comment, missing EOF newline, undocumented detection heuristic). No correctness, data-integrity, or security issues were found. No files require special attention — Important Files Changed
Sequence DiagramsequenceDiagram
participant C as Client
participant S as authenticateApiKeyFromHeader
participant DB as Database
participant L as Legacy Fallback
C->>S: API request with key header
S->>DB: getWorkspaceBillingSettings (if workspaceId)
DB-->>S: workspaceSettings
S->>DB: SELECT ... WHERE key_hash = sha256(header)
alt Hash row found
DB-->>S: HashCandidate row
S->>S: applyHashGates(record, options, workspaceSettings)
note right of S: Check userId, keyType,<br/>expiry, workspace scope,<br/>personal key permissions
S-->>C: ApiKeyAuthResult success
else No hash match (key not yet backfilled)
DB-->>S: []
S->>DB: SELECT ... WHERE userId/type conditions (full scan)
DB-->>S: Encrypted key rows
loop For each candidate
S->>L: authenticateApiKey(header, storedKey.key)
L-->>S: valid?
alt Valid match
S->>S: logger.warn matched via fallback decrypt loop
S-->>C: ApiKeyAuthResult success
end
end
S-->>C: success false error Invalid API key
end
Reviews (1): Last reviewed commit: "fix feature flag" | Re-trigger Greptile |

Summary
Our current api key validation logic is inefficient, storing every api key in memory and decrypting and comparing one at a time. This uses up db connections. Instead, we should validate based on a sha256 hash of the key.
This pr adds a new hashed api key column and tries to validate by hash before falling back on the older api key system. Once we've backfilled the old api keys, we can remove the hash.
This is a multi-step change:
Type of Change
Testing
Validated locally. First tested that existing api keys work via backup, then ran backfill and tested again and validated it used the hashed key. Also validated new api keys are created with hashed api key column.
Checklist
Screenshots/Videos