feat(wabe): add magic link#332
Conversation
|
Worried about impact? Review this PR in Change Stack to explore blast radius before you approve or request changes. Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughThis PR adds passwordless email OTP (magic link) authentication to Wabe. It includes type contracts supporting challenge-based flows, cryptographic OTP generation and verification, challenge storage and lifecycle management, provider implementations for sign-in/sign-up/verification, resolver integration, hook infrastructure to skip duplicate sign-up hooks, default authentication wiring, comprehensive integration tests, and documentation. ChangesMagic Link Authentication Implementation
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
|
@coderabbitai full review |
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
packages/wabe-documentation/docs/documentation/authentication/magicLink.md (1)
14-14: 💤 Low valueConsider splitting this sentence for clarity.
The sentence correctly describes non-enumeration behavior but packs multiple ideas (same response, no email sent, use sign-up instead, dual rationale). Splitting into 2–3 shorter sentences would improve readability.
✏️ Suggested rewording
-For `signInWith`, an email that is not registered yet receives the same API response (`challengeToken`, null tokens) but **no email is sent**. Use `signUpWith` to register a new address. This avoids sending OTP messages to people who never signed up while keeping responses neutral for enumeration. +For `signInWith`, an email that is not registered yet receives the same API response (`challengeToken`, null tokens) but **no email is sent**. To register a new address, use `signUpWith` instead. This design prevents sending OTP messages to addresses that never signed up while keeping responses neutral to avoid user enumeration.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/wabe-documentation/docs/documentation/authentication/magicLink.md` at line 14, Split the long sentence into two or three clearer sentences: state first that signInWith returns the same API response (challengeToken and null tokens) for unregistered emails while not sending any email, and then add a separate sentence advising to use signUpWith to register new addresses; mention the non-enumeration rationale (avoid sending OTPs to non-subscribers while keeping responses neutral) in a short follow-up sentence if needed. Ensure the text references signInWith, signUpWith, and challengeToken so readers can easily map behavior to the API symbols.packages/wabe/src/email/templates/magicLink.ts (1)
1-30: 💤 Low valueHardcoded validity duration may not match configured TTL.
The template states "valid for 15 minutes" (line 22), but
magicLinkOtpTtlMsis configurable viaAuthenticationSecurityConfig. If an operator changes the TTL, the email text would be misleading.Consider either accepting the TTL as a parameter or documenting that the default template assumes the default TTL.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/wabe/src/email/templates/magicLink.ts` around lines 1 - 30, The email template magicLinkTemplate currently hardcodes "valid for 15 minutes" which can diverge from AuthenticationSecurityConfig.magicLinkOtpTtlMs; change magicLinkTemplate to accept a TTL (milliseconds) parameter or a precomputed minutes value and interpolate the computed minutes into the sentence instead of the hardcoded "15 minutes"; update callers that invoke magicLinkTemplate (where OTPs are generated/sent) to pass AuthenticationSecurityConfig.magicLinkOtpTtlMs (or its minutes conversion) so the displayed validity matches the configured TTL.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/wabe/src/authentication/magicLink.inte.test.ts`:
- Around line 302-311: The test "should reject invalid OTP" uses a hardcoded OTP
value of '000000' which could legitimately be generated as a valid OTP in
test/dev mode, causing the test to fail unpredictably. Instead of using a
hardcoded invalid OTP, capture the valid OTP that was generated during the
signUpMagicLink call and create an invalid OTP dynamically by modifying the
valid one (for example, by incrementing or changing one of its digits). Pass
this dynamically generated invalid OTP to the verifyMagicLink function call to
ensure the test always uses a value guaranteed to be different from the actual
generated OTP.
---
Nitpick comments:
In `@packages/wabe-documentation/docs/documentation/authentication/magicLink.md`:
- Line 14: Split the long sentence into two or three clearer sentences: state
first that signInWith returns the same API response (challengeToken and null
tokens) for unregistered emails while not sending any email, and then add a
separate sentence advising to use signUpWith to register new addresses; mention
the non-enumeration rationale (avoid sending OTPs to non-subscribers while
keeping responses neutral) in a short follow-up sentence if needed. Ensure the
text references signInWith, signUpWith, and challengeToken so readers can easily
map behavior to the API symbols.
In `@packages/wabe/src/email/templates/magicLink.ts`:
- Around line 1-30: The email template magicLinkTemplate currently hardcodes
"valid for 15 minutes" which can diverge from
AuthenticationSecurityConfig.magicLinkOtpTtlMs; change magicLinkTemplate to
accept a TTL (milliseconds) parameter or a precomputed minutes value and
interpolate the computed minutes into the sentence instead of the hardcoded "15
minutes"; update callers that invoke magicLinkTemplate (where OTPs are
generated/sent) to pass AuthenticationSecurityConfig.magicLinkOtpTtlMs (or its
minutes conversion) so the displayed validity matches the configured TTL.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: d35ccf70-d4f0-4d2b-bf15-619c45dd1130
⛔ Files ignored due to path filters (2)
packages/wabe/generated/schema.graphqlis excluded by!**/generated/**packages/wabe/generated/wabe.tsis excluded by!**/generated/**
📒 Files selected for processing (29)
packages/wabe-documentation/docs/documentation/authentication/defaultMethods.mdpackages/wabe-documentation/docs/documentation/authentication/magicLink.mdpackages/wabe-documentation/rspress.config.tspackages/wabe/README.mdpackages/wabe/src/authentication/defaultAuthentication.tspackages/wabe/src/authentication/interface.tspackages/wabe/src/authentication/magicLink.inte.test.tspackages/wabe/src/authentication/magicLinkChallenge.tspackages/wabe/src/authentication/magicLinkOtp.test.tspackages/wabe/src/authentication/magicLinkOtp.tspackages/wabe/src/authentication/providers/EmailOTP.test.tspackages/wabe/src/authentication/providers/MagicLink.tspackages/wabe/src/authentication/providers/QRCodeOTP.test.tspackages/wabe/src/authentication/providers/index.tspackages/wabe/src/authentication/resolvers/signInWithResolver.tspackages/wabe/src/authentication/resolvers/signUpWithResolver.test.tspackages/wabe/src/authentication/resolvers/signUpWithResolver.tspackages/wabe/src/authentication/resolvers/verifyChallenge.test.tspackages/wabe/src/authentication/resolvers/verifyChallenge.tspackages/wabe/src/authentication/security.tspackages/wabe/src/database/DatabaseController.tspackages/wabe/src/database/interface.tspackages/wabe/src/email/interface.tspackages/wabe/src/email/templates/magicLink.tspackages/wabe/src/hooks/HookObject.tspackages/wabe/src/hooks/authentication.tspackages/wabe/src/hooks/index.tspackages/wabe/src/mutex/MutexController.tspackages/wabe/src/schema/Schema.ts
💤 Files with no reviewable changes (1)
- packages/wabe/src/mutex/MutexController.ts
Summary by CodeRabbit
Release Notes
New Features
Documentation