refactor(api): extract shared SignedTokenCodec to dedup token services - #384
Conversation
#243) MarketingUnsubscribeTokenService and WaitlistConfirmationTokenService shared near-identical HMAC-SHA256 signing, base64url encode/decode, token composition, and signature-verification logic (SonarCloud flagged ~40 duplicated lines each). Extract the genuinely-shared codec into a single internal static SignedTokenCodec; each service keeps its own payload format, key source, and expiry semantics. Behavior- and wire-format-preserving: the token string, signing input, and verification are byte-identical, so tokens minted before this change still validate. No public interface or DI registration change (static helper). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
|
Code Review: PR #384 (thomasluizon/orbit-api) Scope: PR #384 — refactor(api): extract shared SignedTokenCodec to dedup token services Summary This is a pure, behavior-preserving refactor. It extracts the HMAC-SHA256 signing, base64url encode/decode, and constant-time signature-verification logic that was 100%-duplicated between MarketingUnsubscribeTokenService and WaitlistConfirmationTokenService into one new internal static SignedTokenCodec (src/Orbit.Infrastructure/Services/SignedTokenCodec.cs). A line-by-line comparison of the extracted code against the removed private methods in both services confirms the signing input, encode/decode logic, and CryptographicOperations.FixedTimeEquals comparison are byte-identical — only parameterized by signingKey. No public interface, DI registration (AddSingleton unchanged in Orbit.Api/Extensions/ServiceCollectionExtensions.Infrastructure.cs:68-69), or wire format changed. New tests/Orbit.Infrastructure.Tests/Services/SignedTokenCodecTests.cs exercises the shared helper directly (round-trip, wrong-key, tampered-signature, and malformed-token branches including the invalid base64url-length path). Both pre-existing service test suites are unchanged and unaffected since they black-box test through the public service methods only. Findings Critical: None. Subagents
Validation
Deferred — N/A dimensions
All 4 changed files got a verdict: src/Orbit.Infrastructure/Services/MarketingUnsubscribeTokenService.cs, src/Orbit.Infrastructure/Services/SignedTokenCodec.cs, src/Orbit.Infrastructure/Services/WaitlistConfirmationTokenService.cs, tests/Orbit.Infrastructure.Tests/Services/SignedTokenCodecTests.cs — nothing in the diffs inventory was skipped. Whats good
Recommendation: Safe to merge as-is. No action required. Note: this comment carries the full review content. The formal decision above (APPROVE) was submitted as this PRs single review; its body field was accidentally left as placeholder test text during tooling setup and could not be edited after submission via the tools available in this session. This comment is the authoritative report body for that APPROVE decision. |



What
MarketingUnsubscribeTokenServiceandWaitlistConfirmationTokenServiceshared near-identical token logic — HMAC-SHA256 signing, base64url encode/decode,payload.signaturecomposition, and constant-time signature verification. SonarCloud flagged ~40 duplicated lines in each file.This extracts the genuinely-shared logic into a single
internal static SignedTokenCodec(Encode(payloadBytes, signingKey)+TryDecode(token, signingKey, out payloadBytes)) insrc/Orbit.Infrastructure/Services/. Each service keeps only its own concern:Nformat), no expiry.email|language|expiresAtUnix, with expiry enforcement.Behavior & wire-format preserving
The token string, the signing input (HMAC over the raw payload bytes), and the verification path are byte-identical to before, so a token minted before this change still validates after it. No public interface change, and no DI change (the codec is a static helper — the two services keep their existing
AddSingletonregistrations).Tests
MarketingUnsubscribeTokenServiceTests,WaitlistConfirmationTokenServiceTests) pass unchanged — they act as the round-trip / tamper / wrong-key / expiry / malformed regression guard.SignedTokenCodecTestscovering the shared helper directly (round-trip, wrong key, tampered signature, malformed-token branches incl. the invalid base64url-length path).Orbit.Infrastructure.Tests: 1992 passed, 0 failed.Refs thomasluizon/orbit-ui-mobile#243