Repository navigation
fix(auth): bind native Apple sign-in to a single-use nonce - #8051
Conversation
Every native Apple sign-in request now carries a nonce whose SHA-256 digest matches the identity token's nonce claim, and each digest is accepted once: the server records it atomically with a set-if-absent store write that expires after ten minutes, and a second use of the same digest is refused. A store write that cannot complete refuses the sign-in, keeping the acceptance rule uniform. Local verification runs can serve a fixture key set through a JWKS URL override that applies only outside production deployments.
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Executive SummaryThe only incremental change since Assumptions: Files Reviewed (1 file, incremental)
Previous Review Summaries (9 snapshots, latest commit 474d17a)Current summary above is authoritative. Previous snapshots are kept for context only. Previous review (commit 474d17a)Status: No Issues Found | Recommendation: Merge Executive SummaryThe incremental change since Assumptions: Files Reviewed (6 files)
Previous review (commit 776cea9)Status: No Issues Found | Recommendation: Merge Executive SummaryThe only incremental change removes the unrelated Files Reviewed (1 file, incremental)
Previous review (commit 6c79fb8)Status: 1 Issue Found | Recommendation: Address before merge Executive SummaryThe incremental AGENTS.md cleanup is harmless, but the newly added gateway guidance points to a Overview
Issue Details (click to expand)SUGGESTION
Files Reviewed (1 file, incremental)
Previously reported findings remain resolved at HEAD and are not repeated here. No memory leaks are introduced by this documentation-only change. Fix these issues in Kilo Cloud Previous review (commit 22d461d)Status: No Issues Found | Recommendation: Merge Executive SummaryThe incremental change correctly deletes Files Reviewed (1 file, incremental)
Previously reported findings remain resolved at HEAD: the nonce-store outage maps to 503 via Previous review (commit aa0fd77)Status: 1 Issue Found | Recommendation: Address before merge Executive SummaryThe newly added local opt-in tests close the previously reported coverage gap, but their env restoration writes the string Overview
Issue Details (click to expand)SUGGESTION
Files Reviewed (2 files, incremental)
Previously reported findings resolved at HEAD: the nonce-store outage now maps to 503 via Fix these issues in Kilo Cloud Previous review (commit 635aaa7)Status: 1 Issue Found | Recommendation: Address before merge Executive SummaryThe incremental commits fix the earlier toggle-naming, development-bypass, test-isolation, and env-catalog findings; one suggestion remains: the newly gated local bypass is untested. Overview
Issue Details (click to expand)SUGGESTION
Files Reviewed (3 files, incremental)
Previously reported issues that are now resolved at HEAD: the inverted toggle name ( Fix these issues in Kilo Cloud Previous review (commit a5e3480)Status: 4 Issues Found | Recommendation: Address before merge Executive SummaryThe incremental change adds a development-mode bypass that ignores the nonce-transition flag; the remaining findings are one carried-forward toggle-naming hazard, a missing env-catalog entry, and fragile test isolation. Overview
Issue Details (click to expand)WARNING
SUGGESTION
Files Reviewed (2 files, incremental)
No memory leaks introduced: the Redis nonce record TTL is bounded at 600 s, and the new code adds no listeners, timers, or unbounded caches. Fix these issues in Kilo Cloud Previous review (commit 45a3dec)Status: 2 Issues Found | Recommendation: Address before merge Executive SummaryThe transition window that tolerates nonce-less Apple sign-ins is gated by a PostHog flag whose name describes the opposite effect, risking an accidental security bypass; the remaining finding is a missing env-catalog entry. Overview
Issue Details (click to expand)WARNING
SUGGESTION
Files Reviewed (4 files, incremental)
No memory leaks introduced: the Redis nonce record TTL is bounded at 600 s, and no listeners, timers, or unbounded caches were added. Fix these issues in Kilo Cloud Previous review (commit f92118c)Status: 3 Issues Found | Recommendation: Address before merge Overview
Issue Details (click to expand)WARNING
SUGGESTION
Files Reviewed (6 files)
No memory leaks introduced: the new Redis records carry a TTL, and no listeners, timers, or unbounded caches were added. Reviewed by deepseek-flash-latest · Input: 58.3K · Output: 5.4K · Cached: 486.7K Review guidance: REVIEW.md from base branch |
The single-use record now expires with the identity token it binds, bounded by the longest Apple ID-token lifetime. A record write that cannot complete returns a distinct retryable error instead of an invalid-credential error, so infrastructure faults stay distinguishable from failed verification. Requests without a nonce follow a deployment-controlled transition: they are accepted only strictly before a configured end instant and only while a runtime toggle is on, both checks fail closed, and the transition path keeps its counter.
|
bot: Fixed in 635aaa7:
The earlier two threads (TTL derivation, 503 mapping) were addressed in 45a3dec: the record TTL is derived from the verified token's |
|
bot: Fixed in aa0fd77:
|
|
bot: Fixed in 22d461d — the |
|
bot: Final state: CI 93/93 green on 22d461d, kilobot review recommends merge, all review threads resolved, no merge conflict. The PR is merge-by-human. |
Evidence
Evidence: demonstrated — exercised
POST /api/auth/native/tokenagainst the running local web application with PostgreSQL, Redis, and a loopback Apple key-set fixture. The route returned its documented responses across the accepted exchange, the refusal path, and the storage-availability branch, and the accepted exchange produced the credential response with the expected persisted records.194bb0f301.pnpm dev:start --no-attach nextjs(app onlocalhost:3000,dev-postgres,dev-redis,dev-redis-http) with migrations applied bypnpm test:db.APPLE_JWKS_URL_OVERRIDE; assertions signed with an RS256 fixture key for issuerhttps://appleid.apple.comand the app bundle audience. Device admission used the existing non-production sentinel; the local Stripe switch was on.Observations, each a real HTTP request to the route:
Accepted exchange:
200with a credential; the user row carried the Apple provider association, and the expiring acceptance record existed in Redis.Refusal path: the endpoint's documented refusal response.
Storage-availability branch: its documented retryable response while the Redis endpoint was stopped, and the accepted response after the endpoint returned.
Key-set refresh: one refresh after the cooldown, then the accepted response; the fetch count at the fixture endpoint matched.
NODE_ENV=test pnpm --filter web exec jest --runInBand --runTestsByPath src/lib/auth/native-id-tokens.test.ts src/lib/auth/apple-jwks.test.ts src/app/api/auth/native/token/route.test.ts— 3 suites, 130 tests passed.pnpm --filter web run typecheckpassed.Targeted
oxfmt,oxlint, andgit diff --checkpassed.Limitations: live Apple issuance, physical-device attestation, and the hosted release-toggle backend remain unexercised locally. No mobile source or visual surface changed; no screenshots apply.
Change
Native Apple authentication applies the configured verification requirements and records accepted assertions in Redis. Storage availability has a distinct retryable response. The runtime transition setting has a firm deadline and is closed by default. Configuration is documented in
ENVIRONMENT.md.This follow-up merges
main, preserving its bounded key refresh, shared in-flight fetch, cooldown, cached-key retention, and request timeout alongside local fixture support. Adds a cache-expiry regression test covering successful verification with the refreshed key set.Production prerequisites
None.
Proxy answers
The owner's proxy gave these answers in the owner's place.