# `PhoenixKitWeb.Users.Auth`
[🔗](https://github.com/BeamLabEU/phoenix_kit/blob/v1.7.164/lib/phoenix_kit_web/users/auth.ex#L1)

Authentication and authorization plugs for PhoenixKit user management.

This module provides plugs and functions for handling user authentication,
session management, and access control in Phoenix applications using PhoenixKit.

## Key Features

- User authentication with email and password
- Remember me functionality with secure cookies
- Session-based authentication
- Route protection and access control
- Module-level permission enforcement via on_mount hooks
- Integration with Phoenix LiveView on_mount callbacks

## on_mount Hooks

- `:phoenix_kit_ensure_admin` — Requires Owner/Admin role, or a custom role
  with at least one permission. For custom roles, also checks the specific
  permission key mapped to the current admin view. Unmapped views deny
  custom roles but allow Owner/Admin.
- `:phoenix_kit_ensure_module_access` — For custom roles, checks that the
  feature module is both enabled and permitted. Owner/Admin bypass both
  the enabled and permission checks.

## Usage

The plugs in this module are automatically configured when using
`PhoenixKitWeb.Integration.phoenix_kit_routes/0` macro in your router.

# `assign_embedded_current_user`

```elixir
@spec assign_embedded_current_user(Phoenix.LiveView.Socket.t(), map()) ::
  Phoenix.LiveView.Socket.t()
```

Reconstructs and assigns the current user + scope on an **embedded**
LiveView mount from a host-supplied `session["current_user_uuid"]`.

A LiveView rendered via `live_render/3` mounts with
`:not_mounted_at_router`, so it never runs a router `live_session`'s
`on_mount` hook (e.g. `:phoenix_kit_ensure_admin`) — leaving
`:phoenix_kit_current_scope` / `:phoenix_kit_current_user` absent, which
blinds any user-aware embedded UI (comment composers, activity-actor
attribution). The host bridges identity across the `live_render`
process boundary by passing its own authenticated user's UUID as
`session["current_user_uuid"]` — a **string**, never the `%User{}`
struct (a signed-but-not-encrypted `live_render` session would expose
it to the client). This helper reloads that user and assigns both
`:phoenix_kit_current_user` and `:phoenix_kit_current_scope`.

  * No-op when `:phoenix_kit_current_scope` is already assigned (router
    mount — the `on_mount` hook ran, before `mount/3`). Never clobbers
    the canonical scope.
  * An active user → assigns it + `Scope.for_user(user)`.
  * Absent / unknown / inactive uuid, or a transient DB error →
    anonymous (`nil` user + `Scope.for_user(nil)`), never raising.

> This reconstructs **identity** (audit, comment authorship), not
> **authorization** — it performs no role check. The UUID must come
> from the host's trusted server-side scope, never request params; and
> a host embedding an admin LiveView must gate the embedding page
> itself (the `on_mount` admin gate does not run for embeds).

Generic across embeddable feature modules — `phoenix_kit_projects` is
the reference consumer.

# `fetch_phoenix_kit_current_scope`

Fetches the current user and creates a scope for authentication context.

This plug combines user fetching with scope creation, providing a
structured way to handle authentication state in your application.

The scope is assigned to `:phoenix_kit_current_scope` and includes
both the user and authentication status.

Also verifies session fingerprints if enabled to detect session hijacking attempts.

# `fetch_phoenix_kit_current_user`

Authenticates the user by looking into the session
and remember me token.

Also verifies session fingerprints if enabled to detect session hijacking attempts.

This plug is idempotent - if the user has already been fetched, it returns early
to avoid duplicate database queries.

# `get_endpoint`

# `log_in_user`

Logs the user in.

It renews the session ID and clears the whole session
to avoid fixation attacks. See the renew_session
function to customize this behaviour.

It also sets a `:live_socket_id` key in the session,
so LiveView sessions are identified and automatically
disconnected on log out. The line can be safely removed
if you are not using LiveView.

## Session Fingerprinting

When session fingerprinting is enabled, this function captures the user's
IP address and user agent to create a session fingerprint. This helps
detect session hijacking attempts.

# `log_out_user`

Logs the user out.

It clears all session data for safety. See renew_session.

# `log_out_user_from_all_sessions`

Logs out a specific user by invalidating all their session tokens and broadcasting disconnect to their LiveView sessions.

This function is useful when user roles or permissions change and you need to force re-authentication
to ensure the user gets updated permissions in their session.

## Parameters

- `user`: The user to log out from all sessions

## Examples

    iex> log_out_user_from_all_sessions(user)
    :ok

# `maybe_redirect_authenticated`

Checks if the current user is authenticated and returns a redirect socket if so.

Used by auth pages (login, register, etc.) that should not be accessible
to already-authenticated users when placed in a shared public live_session.

Returns `{:redirect, redirected_socket}` if authenticated (caller should halt),
or `:cont` if not authenticated (caller should proceed with normal mount).

# `on_mount`

Handles mounting and authenticating the phoenix_kit_current_user in LiveViews.

## `on_mount` arguments

  * `:phoenix_kit_mount_current_user` - Assigns phoenix_kit_current_user
    to socket assigns based on user_token, or nil if
    there's no user_token or no matching user.

  * `:phoenix_kit_mount_current_scope` - Assigns both phoenix_kit_current_user
    and phoenix_kit_current_scope to socket assigns. The scope provides
    structured access to authentication state.

  * `:phoenix_kit_ensure_authenticated` - Authenticates the user from the session,
    and assigns the phoenix_kit_current_user to socket assigns based
    on user_token.
    Redirects to login page if there's no logged user.

  * `:phoenix_kit_ensure_authenticated_scope` - Authenticates the user via scope system,
    assigns both phoenix_kit_current_user and phoenix_kit_current_scope.

  * `:phoenix_kit_ensure_owner` - Ensures the user has owner role,
    and redirects to the home page if not.

  * `:phoenix_kit_ensure_admin` - Ensures the user has admin or owner role,
    and redirects to the home page if not.
    Redirects to login page if there's no logged user.

  * `:phoenix_kit_redirect_if_user_is_authenticated` - Authenticates the user from the session.
    Redirects to signed_in_path if there's a logged user.

  * `:phoenix_kit_redirect_if_authenticated_scope` - Checks authentication via scope system.
    Redirects to signed_in_path if there's a logged user.

## Examples

Use the `on_mount` lifecycle macro in LiveViews to mount or authenticate
the current_user:

    defmodule PhoenixKitWeb.PageLive do
      use PhoenixKitWeb, :live_view

      on_mount {PhoenixKitWeb.Users.Auth, :phoenix_kit_mount_current_user}
      ...
    end

Or use the scope system for better encapsulation:

    defmodule PhoenixKitWeb.PageLive do
      use PhoenixKitWeb, :live_view

      on_mount {PhoenixKitWeb.Users.Auth, :phoenix_kit_mount_current_scope}
      ...
    end

Or use the `live_session` of your router to invoke the on_mount callback:

    live_session :authenticated, on_mount: [{PhoenixKitWeb.Users.Auth, :phoenix_kit_ensure_authenticated_scope}] do
      live "/profile", ProfileLive, :index
    end

# `redirect_if_user_is_authenticated`

Used for routes that require the user to not be authenticated.

# `redirect_invalid_locale`

Redirects invalid locale URLs to the canonical default-locale shape.

Takes the current URL path and replaces the invalid locale segment so
the redirect target matches the rest of the app's URL emission:

- With `default_language_no_prefix?` ON → strip the segment entirely
  (the canonical primary shape is prefixless, e.g. `/phoenix_kit/admin`).
- With the setting OFF (default) → swap the invalid segment for the
  primary base code so the canonical prefixed shape is preserved
  (e.g. `/phoenix_kit/xx/admin` → `/phoenix_kit/en/admin`).

# `redirect_to_base_locale`

Redirects full dialect code URLs to base language URLs (301 permanent).

This function handles backward compatibility by redirecting old URLs with
full dialect codes (en-US, es-MX) to the new simplified base code URLs (en, es).

Uses 301 Permanent redirect to tell browsers and search engines to update bookmarks
and indexed URLs. This is SEO-friendly and provides clean URL migration.

## Examples

    iex> redirect_to_base_locale(conn, "en-US")
    # /phoenix_kit/en-US/admin → /phoenix_kit/en/admin

    iex> redirect_to_base_locale(conn, "es-MX")
    # /phoenix_kit/es-MX/users?page=2 → /phoenix_kit/es/users?page=2

## Preservation

- Query parameters preserved
- URL fragments preserved
- Request method unchanged (GET → GET)
- Full path structure maintained

## Notes

- Status code 301 (Permanent) tells clients to update bookmarks
- Halts conn pipeline (no further processing)
- Logged for monitoring migration patterns

# `require_admin`

Used for routes that require the user to be an admin or owner.

If you want to enforce the admin requirement without
redirecting to the login page, consider using
`:phoenix_kit_require_authenticated_scope` instead.

# `require_authenticated_scope`

Used for routes that require the user to be authenticated via scope.

This function checks authentication status through the scope system,
providing a more structured approach to authentication checks.

Enforces email confirmation before allowing access to the application.

# `require_authenticated_user`

Used for routes that require the user to be authenticated.

Enforces email confirmation before allowing access to the application.

# `require_module_access`

Used for routes that require the user to have module-level permission.

# `require_owner`

Used for routes that require the user to be an owner.

If you want to enforce the owner requirement without
redirecting to the login page, consider using
`:phoenix_kit_require_authenticated_scope` instead.

# `require_role`

# `validate_and_set_locale`

Validates and sets the locale for the current request.

This function is called as a plug in the router to validate locale codes in the URL path.
It implements PhoenixKit's simplified URL architecture:

- URLs use base language codes (en, es, fr) for simplicity
- Full dialect codes (en-US, es-MX) are redirected to base codes (301)
- User preferences determine which dialect variant to use for translations
- Translation system uses full dialect codes internally

## Data Flow

1. Check if URL contains full dialect code → redirect to base
2. Validate base code exists in predefined language list
3. Resolve to full dialect using user preference or default mapping
4. Set Gettext to full dialect for translations
5. Store both base code (for URLs) and full dialect (for translations)

## Examples

    # Base code in URL (preferred format)
    conn = validate_and_set_locale(conn, [])
    # Sets: current_locale_base="en", current_locale="en-US"

    # Full dialect in URL (legacy/bookmarks)
    conn = validate_and_set_locale(%{path_params: %{"locale" => "en-US"}}, [])
    # Redirects 301 to: /en/...

    # Invalid locale in URL
    conn = validate_and_set_locale(%{path_params: %{"locale" => "xx"}}, [])
    # Redirects to default locale URL

---

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