# Magic-Link Auth Pages

StarView ships an optional generator for AshAuthentication magic-link sign-in
pages rendered with StarView instead of the default
`AshAuthentication.Phoenix` LiveViews:

```sh
mix star_view.setup.auth
```

This task was included in v0.3.18 and remains available in v0.4.0. It uses the
optional Igniter dependency; it generates application code rather than adding
an authentication service to the SDK.

## What it generates

- `MyAppWeb.AuthController` — the `/auth/sign-in` page. Renders an email form,
  requests a magic link over a StarView event (no page reload), and swaps to a
  "check your email" state. Also implements the
  `AshAuthentication.Phoenix.Controller` callbacks (`success/4`, `failure/3`,
  `sign_out/2`).
- `MyAppWeb.Auth.MagicSignIn` — the `/magic_link/:token` landing page. Verifies
  the token on `GET` and renders a confirm button; the button POSTs back to
  exchange the token for a session, so the sign-in happens on a real form
  submission and the session cookie can be set with a normal redirect.

## Router changes

The task adds the routes to the `"/"` scope through the `:browser` pipeline:

```elixir
get "/auth/sign-in", AuthController, :mount
get "/magic_link/:token", Auth.MagicSignIn, :mount
post "/magic_link/:token", Auth.MagicSignIn, :submit
```

If the router already contains the default AshAuthentication sign-in routes,
they are removed and replaced by the generated pages:

- `sign_in_route ...` — removed
- `magic_sign_in_route ...` — removed
- `sign_out_route AuthController` — added when the router uses
  `AshAuthentication.Phoenix.Router` and no sign-out route exists yet

The StarView dispatch route (`post "/ds/:module/:event"`) and
`StarView.Plug.RenameCsrfParam` are added if they are missing, so the sign-in
form's events work without running the full installer first.

## Layout

Both pages render through `Layout.auth/1`, a full-height auth variant of the
generated StarView layout:

```heex
<Layout.auth conn={@conn}>
  ...
</Layout.auth>
```

If your layout module was generated by an older StarView version without
`auth/1`, the task patches it in: it inserts the `auth/1` component after
`app/1` and adds `:theme`, `:html_class`, and `:body_class` attrs to the
private `root/1` component. See the [layout guide](layout.md) for details.

## Requirements

The generated pages expect an AshAuthentication magic-link strategy on your
user resource with interaction required, so tokens are never consumed by email
link scanners:

```elixir
magic_link do
  identity_field :email
  registration_enabled? true
  require_interaction? true
  sender MyApp.Accounts.User.Senders.SendMagicLinkEmail
end
```

They also expect these code interfaces on your accounts domain:

```elixir
resource User do
  define :request_magic_link, action: :request_magic_link, args: [:email]
  define :sign_in_with_magic_link, action: :sign_in_with_magic_link, args: [:token]
end
```

Both actions are guarded by the `AshAuthenticationInteraction` policy bypass,
which is why the generated code calls them with
`context: %{private: %{ash_authentication?: true}}`.

Finally, point the magic-link sender email at the generated landing page:

```elixir
url(~p"/magic_link/#{@token}")
```

## Privacy

The sign-in page always reports success after a magic-link request, regardless
of whether the account exists, so it does not leak which emails are
registered.
