# `PhoenixKit.Users.MagicLink`
[🔗](https://github.com/BeamLabEU/phoenix_kit/blob/v1.7.87/lib/phoenix_kit/users/magic_link.ex#L1)

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

# `active_magic_links_count`

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

Useful for debugging or administrative interfaces.

## Examples

    iex> PhoenixKit.Users.MagicLink.active_magic_links_count(user)
    1

# `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`

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}

# `magic_link_url`

Generates a magic link URL for the given token.

This is a convenience function to construct the full URL that should be
included in magic link emails.

## Examples

    iex> PhoenixKit.Users.MagicLink.magic_link_url("token123")
    "http://localhost:4000{prefix}/users/magic-link/token123"

    # Where {prefix} is the configured PhoenixKit URL prefix

# `revoke_magic_links`

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`

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}

---

*Consult [api-reference.md](api-reference.md) for complete listing*
