Skip to content
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

Add magiclogin token to email links #104

Merged
merged 2 commits into from
Oct 5, 2024
Merged

Add magiclogin token to email links #104

merged 2 commits into from
Oct 5, 2024

Conversation

david-loe
Copy link
Owner

@david-loe david-loe commented Oct 5, 2024

Fixes #101

Summary by CodeRabbit

  • New Features

    • Introduced a function for generating authenticated links using JWT tokens.
    • Enhanced email sending functionality to support dynamic links based on user status.
    • Improved redirect handling based on JWT token contents during the magic login process.
  • Bug Fixes

    • Improved user verification process in the magic login flow to ensure only active users are processed.
  • Documentation

    • Updated package dependencies to include jsonwebtoken for enhanced token handling.
  • Style

    • Corrected a typo in the email template variable name.

Copy link
Contributor

coderabbitai bot commented Oct 5, 2024

Walkthrough

The changes in this pull request focus on enhancing the MagicLoginStrategy and related authentication processes. Key modifications include the introduction of a JWT token handling mechanism, updates to email sending functionality, and improvements to user verification logic. A new function for generating authenticated links has been added, and existing functions have been modified to incorporate JWT decoding and dynamic redirect handling. Additionally, new dependencies for JWT support have been introduced in the package.json.

Changes

File Change Summary
backend/authStrategies/magiclogin.ts - Introduced genAuthenticatedLink function for JWT token generation.
- Updated sendMagicLink with new parameter.
- Modified verify function to check user activity.
backend/controller/authController.ts - Added JWT decoding in magicloginCallbackHandler.
- Updated magicloginHandler for active user checks.
- Introduced redirectToFrontend method.
backend/mail/mail.ts - Changed sendMail to async and added authenticateLink parameter.
- Introduced _sendMail for individual email sending.
backend/templates/mail.ejs - Corrected typo in variable name from paragaph to paragraph.
backend/package.json - Added jsonwebtoken and @types/jsonwebtoken dependencies.

Assessment against linked issues

Objective Addressed Explanation
Add magiclogin token to email links (#101)

Possibly related PRs

Poem

In the meadow where magic links fly,
A token now dances, oh my, oh my!
With emails that sparkle, and users so bright,
Authentication's magic takes flight tonight!
🐇✨


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🧹 Outside diff range and nitpick comments (4)
backend/authStrategies/magiclogin.ts (1)

2-2: Simplify the import statement for 'MagicLoginStrategy'

You can simplify the import by directly importing the default export without using the { default as ... } syntax.

Apply this diff:

-import { default as MagicLoginStrategy } from 'passport-magic-login'
+import MagicLoginStrategy from 'passport-magic-login'
backend/controller/authController.ts (2)

2-2: Group the 'jsonwebtoken' import with other third-party imports

Consider grouping the jsonwebtoken import with other third-party libraries for better organization and readability.


43-43: Specify a more precise type for the redirect variable

The variable redirect is currently typed as any. For better type safety, consider specifying it as string | undefined.

Apply this diff:

-      let redirect: any
+      let redirect: string | undefined
backend/mail/mail.ts (1)

84-84: Update comment to reflect single recipient

The to field now contains a single recipient's email address, but the comment says 'list of receivers'. Update the comment for clarity.

Apply this diff to update the comment:

     to: recipient.email, // list of receivers
+    to: recipient.email, // recipient email address
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 4fa6d3f and 54d11c2.

⛔ Files ignored due to path filters (1)
  • backend/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (4)
  • backend/authStrategies/magiclogin.ts (2 hunks)
  • backend/controller/authController.ts (2 hunks)
  • backend/mail/mail.ts (2 hunks)
  • backend/package.json (2 hunks)
🔇 Additional comments (4)
backend/package.json (3)

16-16: LGTM: Addition of jsonwebtoken dependency

The addition of the jsonwebtoken library (version ^9.0.2) is appropriate for implementing the magiclogin token functionality as described in the PR objectives. This is the latest stable version, and the use of the caret (^) for version matching allows for compatible updates, which is a good practice.


34-34: LGTM: Addition of @types/jsonwebtoken dev dependency

The addition of @types/jsonwebtoken (version ^9.0.7) as a dev dependency is appropriate. This package provides TypeScript type definitions for the jsonwebtoken library, which will improve development experience and type safety. The version is compatible with the main jsonwebtoken library and is correctly placed in the devDependencies section.


Line range hint 1-62: Overall changes look good and align with PR objectives

The changes to package.json are minimal and focused, adding only the necessary dependencies for implementing the magiclogin token functionality. The additions of jsonwebtoken and its TypeScript types are appropriate and consistent with the project's structure. No other modifications were made, which keeps the changes scoped to the task at hand.

To ensure the new dependencies are properly integrated:

This script will help verify that the newly added dependencies are actually being used in the codebase, ensuring that the changes are not just in the package.json file but are also reflected in the implementation.

✅ Verification successful

Dependencies Verified Successfully

The new dependencies, including jsonwebtoken, have been properly integrated and are actively used within the codebase. Specifically, jsonwebtoken is imported in backend/controller/authController.ts and backend/authStrategies/magiclogin.ts, and its functions jwt.sign are utilized in the latter. No further issues detected.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify that the new dependencies are being used in the codebase

# Check for imports of jsonwebtoken
echo "Checking for imports of jsonwebtoken:"
rg --type typescript 'import.*jsonwebtoken'

# Check for uses of jwt.sign or jwt.verify functions
echo "Checking for uses of jwt.sign or jwt.verify:"
rg --type typescript 'jwt\.(sign|verify)'

Length of output: 343


Script:

#!/bin/bash
# Verify that the new dependencies are being used in the codebase

# Check for imports of jsonwebtoken
echo "Checking for imports of jsonwebtoken:"
rg --type ts 'import.*jsonwebtoken'

# Check for uses of jwt.sign or jwt.verify functions
echo "Checking for uses of jwt.sign or jwt.verify:"
rg --type ts 'jwt\.(sign|verify)'

Length of output: 503

backend/authStrategies/magiclogin.ts (1)

34-35: Approve addition of user activation check

The additional check for await user.isActive() ensures that only active users can log in, enhancing security measures.

backend/authStrategies/magiclogin.ts Outdated Show resolved Hide resolved
backend/authStrategies/magiclogin.ts Show resolved Hide resolved
backend/controller/authController.ts Outdated Show resolved Hide resolved
backend/controller/authController.ts Outdated Show resolved Hide resolved
backend/mail/mail.ts Outdated Show resolved Hide resolved
backend/mail/mail.ts Outdated Show resolved Hide resolved
backend/mail/mail.ts Outdated Show resolved Hide resolved
@david-loe david-loe merged commit 4497be4 into main Oct 5, 2024
3 checks passed
@david-loe david-loe deleted the david-loe/issue101 branch October 5, 2024 12:06
Copy link
Contributor

@coderabbitai coderabbitai bot left a 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

🧹 Outside diff range and nitpick comments (3)
backend/authStrategies/magiclogin.ts (1)

44-55: LGTM with suggestion: New genAuthenticatedLink function

The new genAuthenticatedLink function successfully implements the PR objective of adding a magiclogin token to email links. However, as mentioned in a previous review, this function can be simplified using the synchronous version of jwt.sign. Consider refactoring as follows:

export function genAuthenticatedLink(payload: { destination: string; redirect: string }) {
  const code = Math.floor(Math.random() * 90000) + 10000 + ''
  const token = jwt.sign({ ...payload, code }, secret, jwtOptions)
  return `${callbackUrl}?token=${token}`
}

This refactoring will improve code readability and reduce complexity while maintaining the same functionality.

backend/mail/mail.ts (2)

26-37: LGTM: Implementation of magiclogin token addition

The changes effectively implement the PR objective of adding magiclogin tokens to email links:

  1. Each recipient is processed individually, resolving the issue of shared button object mutation.
  2. Link authentication is correctly implemented and conditional based on the authenticateLink parameter and the presence of a magiclogin foreign key.
  3. The new _sendMail function is called for each recipient, allowing for individual email customization.

Minor optimization suggestion: Consider using Array.prototype.forEach instead of a traditional for loop for better readability:

recipients.forEach(async (recipient) => {
  const language = recipient.settings.language;
  const recipientButton = { ...button };
  if (authenticateLink && recipient.fk.magiclogin && recipientButton.link.startsWith(process.env.VITE_FRONTEND_URL)) {
    recipientButton.link = await genAuthenticatedLink({
      destination: recipient.fk.magiclogin!,
      redirect: recipientButton.link.substring(process.env.VITE_FRONTEND_URL.length)
    });
  }
  _sendMail(recipient, subject, paragraph, recipientButton, lastParagraph, language);
});

This change is optional and doesn't affect functionality.


Line range hint 39-90: LGTM: New _sendMail function

The new _sendMail function effectively encapsulates the email sending logic for a single recipient:

  1. It improves code modularity by separating the email sending logic from the recipient processing logic.
  2. The early return when mailClient is undefined addresses a previous review comment about inconsistent return statements.
  3. The function correctly uses the provided parameters to generate and send the email.

Suggestion for improved error handling: Consider logging an error or throwing an exception when mailClient is undefined, to make debugging easier in case of configuration issues:

if (mailClient == undefined) {
  console.error('Mail client is not initialized');
  return;
}

This change is optional and doesn't affect the core functionality.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 54d11c2 and 9b5627d.

📒 Files selected for processing (4)
  • backend/authStrategies/magiclogin.ts (2 hunks)
  • backend/controller/authController.ts (2 hunks)
  • backend/mail/mail.ts (4 hunks)
  • backend/templates/mail.ejs (1 hunks)
🔇 Additional comments (9)
backend/authStrategies/magiclogin.ts (4)

1-2: LGTM: Necessary imports added

The imports for jsonwebtoken and MagicLoginStrategy are correctly added and will be used in the implementation of the magic login functionality.


9-13: LGTM: Configuration constants properly defined

The secret, callbackUrl, and jwtOptions are correctly defined. The expiresIn value in jwtOptions is now properly set to 120 minutes in seconds, addressing the previous issue mentioned in the past review comments.


Line range hint 18-41: LGTM: Updated sendMagicLink and verify functions

The changes to sendMagicLink and verify functions look good. The verify function now correctly checks if the user is both found and active.

However, could you please clarify the purpose of the new false parameter added to the sendMail function call on line 27? It would be helpful to understand its significance in the context of the PR objectives.


Line range hint 1-55: Overall implementation looks good, with minor improvements needed

The changes in this file successfully implement the magiclogin token functionality as per the PR objectives. The new genAuthenticatedLink function and updates to the MagicLoginStrategy configuration work together to add magiclogin tokens to email links.

To ensure the changes are fully integrated and don't cause unintended side effects, please:

  1. Address the remaining issues mentioned in the previous comments.
  2. Clarify the purpose of the new false parameter in the sendMail function call.
  3. Consider the suggested refactoring for the genAuthenticatedLink function.

To verify the impact of these changes on the wider codebase, please run the following script:

This script will help identify any other parts of the codebase that might need to be updated to align with the changes made in this file.

✅ Verification successful

Verification Successful: No Issues Found

The changes in backend/authStrategies/magiclogin.ts have been successfully verified. There are no unintended usages of MagicLoginStrategy, and other functions like sendMail and genAuthenticatedLink in different parts of the codebase remain unaffected by these updates.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any other uses of MagicLoginStrategy or sendMail that might be affected by these changes

# Search for other uses of MagicLoginStrategy
echo "Checking for other uses of MagicLoginStrategy:"
rg --type typescript "new MagicLoginStrategy" -g '!backend/authStrategies/magiclogin.ts'

# Search for other uses of sendMail with 5 parameters
echo "Checking for other uses of sendMail with 5 parameters:"
rg --type typescript "sendMail\([^)]+,[^)]+,[^)]+,[^)]+,[^)]+\)" -g '!backend/authStrategies/magiclogin.ts'

# Search for uses of genAuthenticatedLink
echo "Checking for uses of genAuthenticatedLink:"
rg --type typescript "genAuthenticatedLink"

Length of output: 666


Script:

#!/bin/bash
# Description: Check for any other uses of MagicLoginStrategy or sendMail that might be affected by these changes

# Search for other uses of MagicLoginStrategy in .ts and .tsx files
echo "Checking for other uses of MagicLoginStrategy:"
rg "new MagicLoginStrategy" --glob "!backend/authStrategies/magiclogin.ts" -g "*.ts" -g "*.tsx"

# Search for other uses of sendMail with 5 parameters in .ts and .tsx files
echo "Checking for other uses of sendMail with 5 parameters:"
rg "sendMail\([^)]+,[^)]+,[^)]+,[^)]+,[^)]+\)" --glob "!backend/authStrategies/magiclogin.ts" -g "*.ts" -g "*.tsx"

# Search for uses of genAuthenticatedLink in .ts and .tsx files
echo "Checking for uses of genAuthenticatedLink:"
rg "genAuthenticatedLink" -g "*.ts" -g "*.tsx"

Length of output: 1253

backend/mail/mail.ts (3)

13-13: LGTM: Import statement for genAuthenticatedLink

The import of genAuthenticatedLink from the magiclogin module is correctly added and aligns with the PR objective of incorporating magiclogin tokens into email links.


18-24: LGTM: Updated sendMail function signature

The changes to the sendMail function signature are appropriate:

  1. The function is now correctly marked as async.
  2. The new authenticateLink parameter allows flexible control over link authentication.
  3. The typo in the paragraph parameter has been fixed, addressing a previous review comment.

These changes align well with the PR objectives and improve the function's flexibility.


Line range hint 153-153: LGTM: Updated sendMail function call

The sendMail function call in sendNotificationMail has been correctly updated to match the new function signature. This change ensures compatibility with the modified sendMail function while maintaining the existing notification mail functionality.

backend/controller/authController.ts (1)

42-56: ⚠️ Potential issue

Security improvements needed in magiclogin callback handler

While the changes align with the PR objectives, there are two important security issues that need to be addressed:

  1. Use jwt.verify instead of jwt.decode:
    The current implementation uses jwt.decode, which doesn't validate the token's signature. This could allow tampered tokens to be accepted.

  2. Validate the redirect parameter:
    The redirect URL from the token is not properly validated, which could lead to open redirect vulnerabilities.

To address these issues, please apply the following changes:

 const magicloginCallbackHandler = useMagicLogin
   ? (req: ExRequest, res: ExResponse, next: NextFunction) => {
       let redirect: any
       if (req.query.token) {
-        const token = jwt.decode(req.query.token as string) as jwt.JwtPayload
-        const redirectPath = token.redirect
-        if (redirectPath && typeof redirectPath === 'string' && redirectPath.startsWith('/')) {
-          redirect = redirectPath
+        try {
+          const token = jwt.verify(req.query.token as string, process.env.JWT_SECRET) as jwt.JwtPayload
+          const redirectPath = token.redirect
+          if (redirectPath && typeof redirectPath === 'string' && redirectPath.startsWith('/')) {
+            redirect = redirectPath
+          }
+        } catch (error) {
+          console.error('Invalid token:', error)
         }
       }
       passport.authenticate('magiclogin', {
         failureRedirect: process.env.VITE_FRONTEND_URL + '/login' + (redirect ? '?redirect=' + redirect : '')
       })(req, res, next)
     }
   : NotImplementedMiddleware

These changes will:

  1. Use jwt.verify to validate the token's signature.
  2. Wrap the token verification in a try-catch block to handle invalid tokens gracefully.
  3. Maintain the existing validation for the redirect path.

Make sure to define process.env.JWT_SECRET in your environment variables and keep it secure.

To ensure that JWT_SECRET is properly set, run the following command:

This will search for occurrences of JWT_SECRET in your project files, helping to verify its presence in configuration files or documentation.

backend/templates/mail.ejs (1)

352-352: Typo correction approved.

The change from <%= paragaph %> to <%= paragraph %> corrects a typo in the variable name. This improvement ensures that the correct variable is referenced when rendering the email template.

backend/authStrategies/magiclogin.ts Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add magiclogin token to email links
1 participant