PhoenixKit.Users.MagicLink (phoenix_kit v1.7.71)

Copy Markdown View Source

Magic Link authentication system for PhoenixKit.

Magic Link provides passwordless authentication where users receive a secure link via email that allows them to log in without entering a password.

Features

  • Passwordless Authentication: Users log in with just their email
  • Secure Token System: Uses existing UserToken infrastructure
  • Time-Limited Links: Magic links expire after a configurable period
  • Optional Integration: Works alongside existing password authentication
  • Email Verification: Links are sent to the user's email address
  • Auto-Confirmation: Unconfirmed users are automatically confirmed upon magic link use

Usage

# Generate and send magic link
case PhoenixKit.Users.MagicLink.generate_magic_link(email) do
  {:ok, user, token} ->
    # Send email with magic link
    PhoenixKit.Mailer.send_magic_link_email(user, token)
    {:ok, user}

  {:error, :user_not_found} ->
    # Handle unknown email
    {:error, :invalid_email}
end

# Verify magic link token
case PhoenixKit.Users.MagicLink.verify_magic_link(token) do
  {:ok, user} ->
    # Log user in
    {:ok, user}

  {:error, :invalid_token} ->
    # Handle invalid/expired token
    {:error, :expired_link}
end

Security Considerations

  • Magic link tokens are single-use (automatically deleted after use)
  • Short expiry time (default: 15 minutes) to minimize exposure
  • Tokens are hashed before storage in database
  • Email address verification ensures link goes to correct recipient
  • Integration with existing user session management

Configuration

Magic link expiry can be configured in your application:

# config/config.exs
config :phoenix_kit,
  magic_link_for_login_expiry_minutes: 15

Summary

Functions

Gets the number of active magic link tokens for a user.

Cleans up expired magic link tokens.

Checks if magic link authentication is enabled for the application.

Generates a magic link for the given email address.

Generates a magic link URL for the given token.

Revokes all active magic link tokens for a user.

Verifies a magic link token and returns the associated user.

Functions

cleanup_expired_tokens()

Cleans up expired magic link tokens.

This function can be called periodically (e.g., via a scheduled job) to remove expired tokens from the database.

Returns the number of tokens deleted.

Examples

iex> PhoenixKit.Users.MagicLink.cleanup_expired_tokens()
5  # 5 expired tokens were deleted

enabled?()

Checks if magic link authentication is enabled for the application.

This can be used in controllers and views to conditionally show magic link UI.

Examples

iex> PhoenixKit.Users.MagicLink.enabled?()
true

generate_magic_link(email)

Generates a magic link for the given email address.

This function includes rate limiting protection to prevent token enumeration attacks. After exceeding the rate limit (default: 3 requests per 5 minutes), subsequent requests will be rejected with {:error, :rate_limit_exceeded}.

Returns {:ok, user, token} if the user exists and rate limit is not exceeded, {:error, :user_not_found} if no user is found with that email, or {:error, :rate_limit_exceeded} if the rate limit has been exceeded.

Examples

iex> PhoenixKit.Users.MagicLink.generate_magic_link("user@example.com")
{:ok, %User{}, "magic_link_token_here"}

iex> PhoenixKit.Users.MagicLink.generate_magic_link("nonexistent@example.com")
{:error, :user_not_found}

iex> PhoenixKit.Users.MagicLink.generate_magic_link("user@example.com")
{:error, :rate_limit_exceeded}

revoke_magic_links(user)

Revokes all active magic link tokens for a user.

This is useful when:

  • Generating a new magic link (only one should be active)
  • User logs in via other means (invalidate pending magic links)
  • Security concerns require invalidating all passwordless access

Examples

iex> PhoenixKit.Users.MagicLink.revoke_magic_links(user)
:ok

verify_magic_link(token)

Verifies a magic link token and returns the associated user.

The token is automatically deleted after successful verification (single-use).

If the user's email is not yet confirmed, this function will automatically confirm the user, since clicking the magic link proves email ownership.

Returns {:ok, user} if the token is valid, or {:error, :invalid_token} if the token is invalid, expired, or already used.

Examples

iex> PhoenixKit.Users.MagicLink.verify_magic_link("valid_token")
{:ok, %User{}}

iex> PhoenixKit.Users.MagicLink.verify_magic_link("invalid_token")
{:error, :invalid_token}