Set Up Seamless Magic Link Authentication with SendGrid and Laravel
Time to read: 6 minutes
Set Up Seamless Magic Link Authentication with SendGrid and Laravel
Several password breaches over the years have sparked a revolt against standard password-based authentication, resulting in the growth of passwordless authentication.
Passwordless authentication is a method of logging a user into a system without a password or any other knowledge-based secret. One of these approaches is magic link authentication.
Magic link authentication is a contemporary and user-friendly mechanism enabling users to log in or register without passwords. Users can safely authenticate themselves by clicking a link via email.
This tutorial will walk you through implementing magic link authentication in a Laravel application using SendGrid.
Prerequisites
- Prior knowledge of Laravel and PHP
- PHP 8.2 or newer
- Composer globally installed
- A SendGrid account. Create a free account if you don't already have one.
- Your preferred text editor or IDE
Set up the project
To begin, you need to create a new Laravel project via Composer, navigate into the project folder:
Next, generate an API key to connect your SendGrid account to Laravel. In your SendGrid Dashboard, navigate to the Settings tab on the left-hand side and choose API Keys. When you click the "Create API Key" button on the top-right corner, a form will be displayed. After completing this form, you will have access to your API credentials.
After that, open the .env file in your preferred IDE or text editor to store these credentials. there, update the mail configuration settings, they're prefixed with MAIL_
, to reflect the configuration below.
Make sure you replace the two placeholders with your newly generated SendGrid API key and your verified single-sender email address.
By default, Laravel 11 configures the application to use SQLite. You can modify the .env file to configure a different database, if you desire.
The application would need the magic_links table to store information regarding the magic link. Run the command below to create the MagicLink
model and migration classes:
This generates two files, the model: app/Models/MagicLink.php and the migration: database/migrations/[timestamp]_create_magic_links_table.php, respectively.
Paste the code below into the migration file:
Then, add the code below to the model file:
Building the Frontend
This application will require three pages: login, registration, and dashboard. First, you'll create a GuestLayout that contains shared codes for the login and registration pages by running the following command below:
The command created a GuestLayout.php file in the app/View/Components directory and a guest-layout.blade.php file in resources/views/components/. In guest-layout.blade.php, paste the following code:
Next, create a new directory named auth in the resources/views directory, then, in that new directory, create a file named register.blade.php. Then, paste the code shown below into the new file:
Then, create a second new file named login.blade.php file in the resources/views/auth directory, and paste the code shown below:
Finally, create a third file, named dashboard.blade.php, this time in the resources/views directory, and paste the code shown below:
Write the registration logic
For the registration process, the user fills out the form, the inputted values are validated, and if no error occurs, a unique link is generated and sent to the user by mail. When this link is clicked, the authenticity of the link is verified. If there are no errors, the user’s record is created, and the user is then authenticated.
To achieve this, you will need a controller to handle the registration logic. To create one, run the command below:
Open the newly created file ( app/Http/Controllers/Auth/RegisterController.php) and paste the following code into it:
The first method defined in RegisterController
, index()
, returns the view for registration and will be linked to a route later on. The create()
method, which handles the first bit of the registration process, ensures that the data from the submitted form meets the criteria defined in the validate()
method.
Next, a token that is pivotal in verifying the request is generated and passed to a temporary, signed route. The reason for using a temporary signed route is that if the URL changes after it has been sent out of the system, the change will be noted, and the route can also expire. Currently, its lifespan is set to one hour (this can be adjusted as desired).
Following that, a notification class is dispatched to send the email. Finally, records about this event are stored in the "magic_links" database, and the user is redirected back to the registration page with a message confirming that the registration link has been sent. It is worth noting that the user's record is not yet stored in the database, as only records of users whose registrations have been verified are entered.
The user table has certain fields that are not required. Therefore, it's worth cleaning them up by replacing the content of the database/migrations/0001_01_01_000000_create_users_table.php file with:
Now, run the migrations to effect these changes.
Create the notification class
In this application, rather than sending the mail via a Mailable class, the mail will be sent via a Notification class to whip things up quickly. To create the notification class, run the command below:
This creates a file named RegisterNotification.php in the app/notification directory. Open the file and paste the code shown below:
Verify the registration link
With all the steps done, the first part of registration is complete. However, the need to verify the link sent via email and authenticate the user still needs to be met. For that, add the store()
method below to app/Http/Controller/Auth/RegisterController.php:
You may recall that a record of the event was kept in the database's "magic_links" table. If you examine the link, you will see that it contains a token. This token is checked with the database. If there is a match in the database and the IP address of the current request matches the stored IP address, the user is created, and then authenticated, before being redirected to the dashboard.
Finally, create the required routes in the routes/web.php file:
Write the login logic
The logic for the login process is similar to the registration logic. The user fills out the form, the inputted value is checked against the database, and if a match is found a unique link is generated and sent to the user by email. When this link is clicked, the user is then authenticated if the link is valid.
To achieve this, you will need a controller to handle the registration logic. To create one, run the command below:
Open the just-created file (app/Http/Controllers/Auth/LoginController.php) and paste the following code into it:
The index()
method returns the login view. The create()
method validates the submitted data. A token just like in the RegisterController
is generated and passed to a temporarily signed route whose lifespan is set at 10 minutes. Following that, a notification class is dispatched to be sent by mail. Finally, records about the event are stored in the "magic_links" database and a redirection back to the login page occurs, with a message confirming that the login link has been sent.
The store()
method is used for verifying the login link, which is quite similar to the RegisterController
's store()
method. The only difference here is that instead of a new user being created, the user record is searched for based on the email stored in the "payload" column.
Next, run the command below to create a login notification class:
After that, paste the code below in the newly created file ( app/Notifications/LoginNotification.php):
Finally, add the login routes to the "guest" middleware group where the register routes are found in the routes/web.php file:
Testing the application
After completing the necessary development steps, it's important to test the code to ensure it functions properly. Start the application by running the following command.
The PHP development server will start on port 8000. You can now test this in your browser by visiting http://127.0.0.1:8000/register.
Input your name and email address, then click on the REGISTER button:
After a successful submission, you should see a success message above the form.
Next, check your email inbox for the registration link:
You will be authenticated when you click the Complete Registration button in the email, and a new user record will be created in the database. Then, you will be redirected to the “/dashboard” route.
That's how to set up magic link authentication with Laravel and SendGrid
In this tutorial, you learned how to create seamless Magic Links using SendGrid and Laravel. This solution increases security by eliminating the need for passwords while also providing a more convenient login process.
Additionally, schedule a process to clean up the MagicLink database every 24 hours to free up database resources. Happy coding!
Prosper is a freelance Laravel web developer and technical writer who enjoys working on innovative projects that use open-source software. When he's not coding, he searches for the ideal startup opportunities to pursue. You can find him on Twitter and Linkedin.
Related Posts
Related Resources
Twilio Docs
From APIs to SDKs to sample apps
API reference documentation, SDKs, helper libraries, quickstarts, and tutorials for your language and platform.
Resource Center
The latest ebooks, industry reports, and webinars
Learn from customer engagement experts to improve your own communication.
Ahoy
Twilio's developer community hub
Best practices, code samples, and inspiration to build communications and digital engagement experiences.