Laravel Magic Login

repository·main·Indexed 41 days ago

https://github.com/maize-tech/laravel-magic-login

A package for implementing passwordless authentication in Laravel applications using magic links sent via email. It provides the MagicLink facade for generating and sending signed, temporary URLs, supports custom metadata storage, and allows configuration of expiration, login limits, and authentication guards.

Tokens
3.8K
Snippets
14
Records
18
Agent score
51%

What's inside Laravel Magic Login

  1. Register the Magic Link route

    main

    To enable the magic link functionality, you must register the magic link route in your application's routing files. It is recommended to add this to routes/web.php using the MagicLink facade.

    use Maize\
    MagicLogin\\Facades\\MagicLink;
    
    MagicLink::route();
  2. Install Laravel Magic Login

    main

    To add passwordless authentication to your Laravel application, install the package via Composer and then run the installation command to publish configuration and migration files.

    composer require maize-tech/laravel-magic-login
    
    php artisan magic-login:install
  3. Customize the MagicLinkNotification class

    main

    To change the appearance or content of the magic link email, create a custom notification class that extends Maize\MagicLogin\Notifications\MagicLinkNotification. You can then update the notification key in config/magic-login.php to point to your new class.

    Note: The base class provides the $this->uri property which contains the magic link.

    use Illuminate\
    Notifications\\Messages\\MailMessage;
    use Maize\\MagicLogin\\Notifications\\MagicLinkNotification as BaseMagicLinkNotification;
    
    class MagicLinkNotification extends BaseMagicLinkNotification
    {
        public function toMail($notifiable): MailMessage
        {
            return (new MailMessage)
                ->line(__('This is my custom magic link notification message'))
                ->action(__('Join now'), $this->uri);
        }
    }
  4. Configure Laravel Magic Login

    main

    The package behavior is controlled via a configuration file published during installation. You can customize the model, expiration, authentication guard, and more.

    Key configuration options include:

    • model: The class for the magic login model (default: Maize\MagicLogin\Models\MagicLogin::class).
    • expiration: Minutes before the link expires (default: 120).
    • guard: The authentication guard to use (default: 'web').
    • redirect_url: The default URL to redirect to after successful login.
    • force_single: If true, generating a new link revokes all previous links for that user (default: true).
    • logins_limit: How many times a single link can be used. -1 allows indefinite use (default: -1).
    • send_notification_action: Custom action class for sending the email.
    • notification: Custom notification class.

    Route settings can also be customized under the route key, including methods, uri, name, controller, and middleware.

    return [
        'model' => null,
        'expiration' => null,
        'guard' => null,
        'redirect_url' => null,
        'exception' => null,
        'force_single' => null,
        'logins_limit' => null,
        'send_notification_action' => null,
        'notification' => null,
        'route' => [
            'methods' => null,
            'uri' => null,
            'name' => null,
            'controller' => null,
            'middleware' => null,
        ],
    ];
  5. Store and query custom metadata

    main

    You can attach custom metadata to a magic link using the metadata parameter. This data is stored in the database and can be queried using the Maize\MagicLogin\Models\MagicLogin model via JSON queries.

    use App\\Models\\User;
    use Maize\\MagicLogin\\Facades\\MagicLink;
    use Maize\\MagicLogin\\Models\\MagicLogin;
    
    $user = User::firstOrFail();
    
    // Attach metadata
    $magicLink = MagicLink::send(
        authenticatable: $user,
        metadata: ['test' => true]
    );
    
    // Query using metadata
    MagicLogin::query()
        ->whereJsonContains('metadata->test', true)
        ->count(); // returns 1
  6. Send magic link via email notifications

    main

    To generate a link and automatically send it to the user via email, use the send method. Alternatively, you can use make with the notify: true parameter.

    // Option 1: Using send()
    use App\\Models\\User;
    use Maize\\MagicLogin\\Facades\\MagicLink;
    
    $user = User::firstOrFail();
    $magicLink = MagicLink::send(
        authenticatable: $user
    );
    
    // Option 2: Using make() with notify: true
    $magicLink = MagicLink::make(
        authenticatable: $user,
        notify: true
    );
  7. Generate a magic link with MagicLink::make()

    main

    You can generate a magic link for any model that extends Laravel's Authenticatable class using the make method. This returns the link without sending any notifications.

    use App\\Models\\User;
    use Maize\\MagicLogin\\Facades\\MagicLink;
    
    $user = User::firstOrFail();
    
    $magicLink = MagicLink::make(
        authenticatable: $user
    );
  8. Configure MagicLink::make() options

    main

    The make and send methods accept several parameters to customize the behavior of the generated link:

    • redirectUrl: The URL the user is sent to after successful authentication. Defaults to the redirect_url config value.
    • expiration: How long the link remains valid. Accepts a Carbon instance or an integer representing minutes. Defaults to the expiration config value.
    • routeName: The name of the route used to generate the link. Defaults to route.name in config.
    • guard: The authentication guard to use (e.g., 'api'). Defaults to the guard config value.
    • loginsLimit: How many times the link can be used. Use -1 for infinite uses. Defaults to logins_limit in config.
    • metadata: An associative array of custom data to store with the link for later querying.
  9. Generate a magic link with MagicLink::make()

    main

    Use the MagicLink::make() facade method to generate a magic link string for an authenticatable user. This method is useful when you want to generate the link but do not want to trigger the email notification immediately.

    Parameters:

    • $authenticatable: The user instance (must implement ext{Illuminate ext{ }} ext{Contracts ext{ }} ext{Auth ext{ }} ext{Authenticatable}).
    • $redirectUrl (optional): The URL to redirect the user to after successful login.
    • $expiration (optional): An instance of ext{Illuminate ext{ }} ext{Support ext{ }} ext{Carbon}, an integer (seconds), or null to define when the link expires.
    • $routeName (optional): The name of the route used for the magic link.
    • $guard (optional): The authentication guard to use.
    • $loginsLimit (optional): An integer specifying how many times this specific link can be used.
    • $metadata (optional): An array of metadata to attach to the link.
    • $notify (optional): A boolean. If true, it will trigger the email notification (similar to send()). Defaults to false.
    // Example: Generate a link that expires in 30 minutes and redirects to /dashboard
    $link = MagicLink::make(
        $user, 
        url('/dashboard'), 
        now()->addMinutes(30)
    );
  10. Perform a magic login using the MagicLogin model

    main

    The MagicLogin model provides a login() method that authenticates the associated user (the authenticatable entity) using the guard specified in the record.

    When calling login():

    1. It verifies if the associated entity exists and if the logins_limit has been reached.
    2. It uses the guard attribute to determine which Laravel authentication guard to use.
    3. It performs the login via auth()->guard($this->guard)->login($this->authenticatable).
    4. It increments the logins counter.

    If the entity is missing or the login limit has been exceeded, an Exception is thrown.

    // Assuming you have retrieved a MagicLogin instance
    $magicLogin = MagicLogin::where('uuid', $uuid)->first();
    
    try {
        $magicLogin->login();
    } catch (\Exception $e) {
        // Handle failed login (e.g., expired, limit reached, or user not found)
    }