A secure and straightforward example of backend authentication utilizing HttpOnly cookies for enhanced security.
This project serves as a practical demonstration of implementing a secure authentication system. By leveraging HttpOnly cookies, it helps mitigate common web vulnerabilities, providing a robust foundation for your backend services.
- Key Features
- Magic Link Authentication
- Google Oauth
- Environment Configuration
- Installation Guide
- API Endpoints & cURL Examples
- Email is King Architecture: Uses email as the single source of truth for user identity, allowing seamless integration between OAuth and Magic Link authentication.
- Secure by Design: Implements HttpOnly cookies to prevent cross-site scripting (XSS) attacks from accessing sensitive cookie data.
- Magic Link Authentication: Passwordless login option that sends secure login links via email for enhanced user experience.
- OAuth Integration: Google OAuth authentication that merges with existing user accounts by email.
- Enhanced Security: Token expiration, automatic cleanup, and proper error handling for all authentication methods.
- Backend Focused: A clear and concise backend implementation, perfect for learning and integration.
- Easy to Follow: Well-structured and commented code to guide you through the authentication flow.
This authentication system implements an "Email is King" architecture where email serves as the single source of truth for user identity. This approach provides a seamless user experience across different authentication methods.
- Unified Identity: All users are identified by their email address regardless of how they first registered
- Account Merging: If a user first logs in with Google (
user@example.com) and later requests a magic link for the same email, both methods access the SAME user account - Registration Source Tracking: The system tracks how users first registered (
registration_sourcefield) for analytics purposes - Email Confirmation: All authentication methods confirm the email address during first login
- Seamless UX: Users can switch between authentication methods without creating duplicate accounts
- Simplified Database Schema: No complex provider relationships or foreign keys
- Cleaner Codebase: Easier to maintain and extend with new authentication providers
- Better Security: Single identity reduces attack surface and prevents account duplication issues
Magic links provide a secure, passwordless authentication method that integrates seamlessly with the email-based architecture.
- Registration/Login: User enters their email and requests a magic link
- Email Sent: System generates a secure token with 15-minute expiration and sends it via email
- Authentication: User clicks the link to authenticate and gets redirected to the frontend
- Session Created: User is automatically logged in with an HttpOnly cookie session
- Tokens expire after 15 minutes for enhanced security
- Tokens are single-use and automatically cleared after use
- Users created via magic link are automatically confirmed
- Secure token generation using cryptographically strong random bytes
- Proper error handling with automatic token cleanup on failures
- Distinguishes between invalid and expired tokens for better UX
Google OAuth authentication seamlessly integrates with the email-based architecture, allowing users to authenticate using their Google accounts.
- OAuth Flow: User clicks Google login button and authenticates with Google
- Email Extraction: System receives the user's email from Google OAuth
- Account Lookup: System searches for existing user by email only
- Account Creation/Update: Creates new user or updates existing user's registration source
- OAuth Endpoint:
http://localhost:4000/auth/google - Redirect URL: Configured via
FRONTEND_URLenvironment variable - Account Merging: Automatically merges with existing accounts by email
- Registration Source: Sets
registration_sourceto "google" for audit purposes
- No Duplicate Accounts: Users with existing accounts (from magic links) are seamlessly logged in
- Consistent Experience: Same user session regardless of authentication method
- Simplified Management: No provider-specific tables or complex relationships
Properly setting up your environment variables is crucial for the application to run correctly. Below are the sample .env configurations for both the frontend and backend components.
# No environment variables are required for the frontend in this example.
DATABASE_URL=postgresql://user:password@localhost:5432/phx-auth
DB_USERNAME=user
DB_PASSWORD=password
DB_HOSTNAME=localhost
DB_NAME=phx-auth
SECRET_KEY_BASE=hash
GUARDIAN_SECRET=hash
GOOGLE_CLIENT_ID=secret-key
GOOGLE_CLIENT_SECRET=secret-key
FRONTEND_URL=http://localhost:3000
# Required for Magic Link Authentication
RESEND_API_KEY=your_resend_api_key
RESEND_FROM_EMAIL=noreply@yourdomain.com
APP_BASE_URL=http://localhost:4000
Important:
- Ensure you replace placeholder values with your actual database credentials and secret keys.
- Magic link authentication requires a Resend API key and email configuration.
- Get your Resend API key from https://resend.com/ Important: Ensure you replace the placeholder values with your actual database credentials and secret keys.
Follow these simple steps to get the project up and running on your local machine.
To install the necessary frontend packages, you have two options:
- Using Bun:
bun install
- Using npm:
npm install
For the backend, you'll need to fetch the Elixir dependencies using mix:
mix deps.getBelow are examples of how to interact with the API endpoints using cURL.
This endpoint sends a magic link for passwordless authentication. Creates user if doesn't exist.
curl -X POST \
-H "Content-Type: application/json" \
-d '{"email": "test@example.com"}' \
http://localhost:4000/api/login/magic-linkUsers click the link in their email to authenticate. The link format is:
http://localhost:4000/api/login/magic-link/{token}
After successful authentication, users are redirected to FRONTEND_URL with an active session.
Error Handling:
- Invalid Token: Redirects to
FRONTEND_URL/?error=invalid_magic_link - Expired Token: Redirects to
FRONTEND_URL/?error=expired_magic_link
Security Features:
- Tokens automatically expire after 15 minutes
- Single-use tokens that are cleared after authentication
- Automatic cleanup of expired tokens
This is a protected endpoint that requires a valid session cookie. We use -b cookie.txt to send the cookie that was saved during login.
curl -X GET \
-b cookie.txt \
http://localhost:4000/api/meThis endpoint invalidates the user's session. It also requires the session cookie to identify which user to log out.
curl -X POST \
-b cookie.txt \
http://localhost:4000/api/logout