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

FEAT(auth): implement magic link authentication #642

Merged
merged 9 commits into from
Mar 2, 2025

Conversation

sam-uel-ayo
Copy link
Contributor

@sam-uel-ayo sam-uel-ayo commented Mar 1, 2025

Description

This PR adds a complete magic link authentication mechanism, allowing users to sign in without a password by receiving a one-time login token via email. In addition to the initial send-magic-link endpoint, this PR now includes a new verify-magic-link endpoint, updates to the email sending logic, an improved email template, and comprehensive tests for both endpoints.

Changes Introduced

1. Magic Link Request Endpoint (POST /api/v1/auth/magic-link)

  • Generates a secure, random token.
  • Saves the token and its expiration (30 minutes) in the user’s record.
  • Sends the token via email using the updated MagicLinkEmail mailable.
  • Returns appropriate JSON responses for success (200) or errors (400, 404, 500).

2. Magic Link Verification Endpoint (POST /api/v1/auth/magic-link/verify)

  • Validates the request parameters (email and token).
  • Checks that the token matches the user’s token and is not expired.
  • Upon successful verification:
    • Updates the user’s status (sets is_active to 1, updates last_login_at).
    • Clears the magic link token and its expiration.
    • Generates a JWT token (using JWTAuth) for the user.
    • Returns a JSON response matching the structure of the standard login endpoint, including user profile details and organizations.
  • Returns appropriate error responses if the token is invalid, expired, or if the email is not found.

3. Tests

  • Existing tests for the send-magic-link endpoint have been retained and improved.
  • New tests have been added for the verify-magic-link endpoint, covering:
    • Failure when an invalid token is provided.
    • Failure when the token has expired.
    • Failure when the email does not exist.

How Has This Been Tested?

  • Run the app locally using:

    php artisan serve
  • Use Postman to send a POST request to /api/v1/auth/magic-link with the request body:

    {
      "email": "[email protected]"
    }

    Expected Responses:

    • 200 (Success):
      {
        "status": "success",
        "status_code": 200,
        "message": "Verification token sent to email"
      }
    • 400 (Invalid Email Format):
      {
        "status": "error",
        "status_code": 400,
        "message": "Invalid email address"
      }
    • 404 (User Not Found):
      {
        "status": "error",
        "status_code": 404,
        "message": "User not found"
      }
    • 500 (Email Sending Failure):
      {
        "status": "error",
        "status_code": 500,
        "message": "Failed to send email"
      }
  • For the verification endpoint, send a POST request to /api/v1/auth/magic-link/verify with:

    {
      "email": "[email protected]",
      "token": "the-valid-token"
    }

    Expected Successful Response (structure identical to login):

    {
        "status_code": 200,
        "message": "Login successful",
        "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
        "data": {
            "user": {
                "id": "9e548afd-c4cd-4184-970e-2117d2cd1072",
                "first_name": "Samuel",
                "last_name": "X",
                "email": "[email protected]",
                "avatar_url": null,
                "is_superadmin": false,
                "role": "user"
            },
            "organisations": [
                {
                    "organisation_id": "9e548afe-3b8c-4aca-9ead-0e0709111146",
                    "name": "Samuel's Organisation",
                    "user_role": "admin",
                    "is_owner": true
                }
            ]
        }
    }
  • Run the tests with:

    php artisan test --filter=MagicLinkTest

    All tests should pass.

Documentation

  • API documentation has been updated to include both endpoints and their expected responses.
  • A note has been added that the magic link email contains a placeholder URL for the frontend callback, to be implemented in a separate issue.

Checklist

  • Code follows the project’s coding style.
  • Documentation has been updated accordingly.
  • All tests (both new and existing) pass.
  • Changes are non-breaking and add functionality.
  • Migration for magic_link_token and magic_link_expires_at is handled separately via php artisan migrate.

This PR now fully implements the magic link authentication flow—from requesting a magic link to verifying it and logging the user in—all while maintaining consistency with our existing login responses. Please review and let me know if any further changes are needed.

- Add MagicLinkController to handle magic link requests
- Add MagicLinkEmail mailable for sending magic link emails
- Add magic_link.blade.php template for the email content
- Add unit tests for the magic link functionality
- Update routes/api.php to include the magic link endpoint
- Add migration to add magic_link_token and magic_link_expires_at columns to users table"
- Update MagicLinkController to return consistent error response"
- Added JSON documentation for the new /api/v1/auth/magic-link POST endpoint.
- Included request body, responses (200, 400, 404, 500), and example payloads.
- Updated the API documentation to reflect the new passwordless authentication feature.
- Added endpoint `/api/v1/auth/magic-link/verify` to complete passwordless login implementation
- Implemented `MagicLinkController` to handle magic link verification requests
- Updated `routes/api.php` to include magic link verifiacation endpoint
- Included unit tests for magic link verification functionality

FIX(auth): resolve issues in magic link handling

- Fixed missing email variable in `MagicLinkEmail` constructor
- Ensured magic link includes both email and token in the URL
- Fixed incorrect route in `magic_link.blade.php` template
- Handled email sending failure with proper error responses
@bhimbho bhimbho merged commit 00f429b into hngprojects:dev Mar 2, 2025
1 check passed
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.

2 participants