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:
- Token Expiration: Each token is given an expiration time. This limits the window during which the token can be used.
- Single Use: Tokens are marked as used after a successful login, preventing reuse.
- Cryptographic Security: The use of the `secrets` module ensures that our tokens are cryptographically secure.
Benefits of Magic Links
- Enhanced User Experience: Users do not need to remember passwords, reducing the friction associated with login processes.
- Increased Security: By eliminating passwords, we reduce the risk of password-related attacks such as brute force or credential stuffing.
- 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.