fbpx

Implementing Magic Links for Passwordless Authentication in Our Application

At Agilno, we are dedicated to developing innovative solutions that simplify user experiences. For one of our applications, we implemented Magic Links as a form of passwordless authentication. This approach facilitates the easier creation and management of multiple user accounts by our application’s facilitators when organizing retreats.

Project Overview

Our application is a platform designed for therapists and facilitators who organize retreats. It allows them to efficiently manage their clients by sending out forms to fill out, documents to sign, and keeping all relevant information in one centralized location. This streamlined process enhances both the facilitators’ and clients’ experiences, ensuring that all necessary documentation and communications are handled smoothly and securely.

What are Magic Links?

Magic Links are a passwordless authentication method that allows users to log in to an application without needing to remember a password. Instead, a unique, cryptographically safe link is generated and sent to the user’s email address. By clicking on this link, the user is authenticated and granted access to the application.

Tools used:

Django and Django Rest Framework (DRF)

We used Django, a high-level Python web framework, along with Django Rest Framework (DRF) to build a secure and scalable backend for our application.

Sendgrid

Sendgrid was integrated for reliable email delivery, ensuring that Magic Links are sent efficiently and consistently to users’ email addresses.

Celery

Celery was used to create asynchronous email-sending tasks, offloading the email sending process to a background task to maintain application responsiveness.

Python’s Secrets Module

The `secrets` module was utilized to generate cryptographically secure random strings, ensuring the security of our Magic Links.

Summary of Tools

We utilized Django and DRF for our backend, Sendgrid for email delivery, Celery for task management, and Python’s `secrets` module for secure token generation.

Generating the Magic Link

When a user attempts to log in to our application, we generate a random, cryptographically secure string of numbers and letters. This string serves as a unique token for the user’s login attempt. We use Python’s `secrets` module to ensure the randomness and security of the generated string:

import secrets

def generate_magic_link_token():
    return secrets.token_urlsafe(64)

This token is then stored in our database, associated with the user’s account, and included in a URL that is emailed to the user.

Sending the Magic Link

For sending the Magic Link, we utilize Celery to create an email-sending task and integrate Sendgrid to handle the actual email delivery. This ensures reliable and efficient email processing, even during high-traffic periods.

Celery Task

We define a Celery task to handle the email-sending process. This allows us to offload the email sending to a background task, improving the responsiveness of our application.

from celery import shared_task
from django.conf import settings
import sendgrid
from sendgrid.helpers.mail import Mail

@shared_task
def send_magic_link(user_email, token):
    sg = sendgrid.SendGridAPIClient(api_key=settings.SENDGRID_API_KEY)
    magic_link = f"{settings.SITE_URL}/login/{token}"
    message = Mail(
        from_email=settings.DEFAULT_FROM_EMAIL,
        to_emails=user_email,
        subject="Your Magic Link for Our Application",
        plain_text_content=f"Click the following link to log in: {magic_link}"
    )
    response = sg.send(message)
    return response.status_code

Handling Login Attempts

When the user clicks on the Magic Link, they are redirected to our application with the token in the URL. Our backend then verifies the token:

from django.shortcuts import redirect
from django.contrib.auth import login
from django.utils import timezone

def login_with_magic_link(request, token):
    user = authenticate_with_token(token)
    if user:
        login(request, user)
        return redirect('dashboard')
    else:
        # Handle invalid or expired token
        return redirect('login')

def authenticate_with_token(token):
    try:
        user_token = UserToken.objects.get(token=token, used=False, expires_at__gt=timezone.now())
        user_token.used = True
        user_token.save()
        return user_token.user
    except UserToken.DoesNotExist:
        return None

Security Considerations

To ensure the security of our Magic Links:

  1. Token Expiration: Each token is given an expiration time. This limits the window during which the token can be used.
  2. Single Use: Tokens are marked as used after a successful login, preventing reuse.
  3. Cryptographic Security: The use of the `secrets` module ensures that our tokens are cryptographically secure.

Benefits of Magic Links

  1. Enhanced User Experience: Users do not need to remember passwords, reducing the friction associated with login processes.
  2. Increased Security: By eliminating passwords, we reduce the risk of password-related attacks such as brute force or credential stuffing.
  3. Simplified Account Management: Facilitators can easily create and manage multiple user accounts without needing to distribute and manage passwords.

Conclusion

Implementing Magic Links in our application has significantly improved our user authentication process. This passwordless approach not only enhances the user experience but also provides a secure and efficient way for facilitators to manage user accounts. At Agilno, we continue to leverage innovative technologies to deliver superior solutions for our clients.

For more information about our services or to discuss how we can help with your next project, contact us at hello@agilno.com