# `Dialup.Auth`
[🔗](https://github.com/SouichiroTsujimoto/Dialup/blob/main/lib/auth.ex#L1)

Authentication helpers for Dialup applications.

Dialup separates two session concepts:

- `dialup_session` — connection ID for `UserSessionProcess` (anonymous until enriched)
- `_dialup_user_token` — opaque auth token resolved to `current_user`

Configure an accounts module on the app or plug:

    use Dialup,
      auth_accounts: MyApp.Accounts

    plugs: [{Dialup.Auth.Plug, accounts: MyApp.Accounts}]

# `accounts_module`

```elixir
@spec accounts_module(atom()) :: module() | nil
```

Returns the configured accounts module for an app, if any.

# `build_layout_session`

```elixir
@spec build_layout_session(map(), map()) :: map()
```

Merges auth context into an existing session map.

# `cookie_opts`

```elixir
@spec cookie_opts(Plug.Conn.t()) :: keyword()
```

Returns cookie options aligned with the app's `:secure_cookies` setting.

# `csrf_cookie`

Cookie name for CSRF double-submit.

# `csrf_token`

```elixir
@spec csrf_token(Plug.Conn.t()) :: {Plug.Conn.t(), binary()}
```

Returns a CSRF token for forms, setting the cookie when needed.

# `current_user`

```elixir
@spec current_user(Plug.Conn.t()) :: map() | struct() | nil
```

Resolves the current user from conn assigns (set by Dialup.Auth.Plug).

# `fetch_current_user`

```elixir
@spec fetch_current_user(Plug.Conn.t(), module()) ::
  {Plug.Conn.t(), map() | struct() | nil}
```

Fetches the current user from assigns or cookies.

# `initial_session`

```elixir
@spec initial_session(map() | struct() | nil) :: map()
```

Seeds layout session with `current_user` before layout.mount runs.

# `log_in_user`

```elixir
@spec log_in_user(Plug.Conn.t(), map() | struct(), module()) :: Plug.Conn.t()
```

Logs a user in by issuing the auth cookie and rotating dialup_session.

# `log_out_user`

```elixir
@spec log_out_user(Plug.Conn.t(), module()) :: Plug.Conn.t()
```

Logs a user out, clearing the auth cookie and rotating dialup_session.

# `public_user`

```elixir
@spec public_user(map() | struct() | nil) :: map() | nil
```

Projects a user for Dialup session / agent_state (no secrets).

# `require_authenticated_user`

```elixir
@spec require_authenticated_user(Plug.Conn.t(), binary()) :: Plug.Conn.t()
```

Halts with a redirect when no user is present.

# `resolve_conn_user`

```elixir
@spec resolve_conn_user(Plug.Conn.t(), atom()) :: map() | struct() | nil
```

Resolves the current user from plug assigns or cookies.

Matches HTTP page rendering: prefers `dialup_current_user` from `Dialup.Auth.Plug`,
then falls back to cookie resolution when `auth_accounts` is configured.

# `rotate_dialup_session`

```elixir
@spec rotate_dialup_session(Plug.Conn.t()) :: Plug.Conn.t()
```

Rotates the anonymous connection session cookie (session fixation mitigation).

# `safe_redirect_path`

```elixir
@spec safe_redirect_path(term()) :: binary()
```

Returns a same-origin relative path or `/` when the target is unsafe.

# `session_token`

```elixir
@spec session_token(Plug.Conn.t()) :: binary() | nil
```

Returns the opaque auth session token from a connection's cookies.

# `session_token_from_cookies`

```elixir
@spec session_token_from_cookies(map()) :: binary() | nil
```

Returns the opaque auth session token from cookies, if present.

# `user_from_cookies`

```elixir
@spec user_from_cookies(map(), module()) :: map() | struct() | nil
```

Resolves a user from request cookies using the accounts module.

# `user_token_cookie`

Cookie name for the opaque user session token.

# `valid_csrf?`

```elixir
@spec valid_csrf?(Plug.Conn.t(), map()) :: boolean()
```

Validates a CSRF token from form params against the cookie.

---

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