PhoenixKit.Users.Auth.SessionRef (phoenix_kit v2.64.1)

Copy Markdown View Source

A live browser session as an actor, for code that runs on a person's behalf without a Plug.Conn (an assistant LiveView, a task it starts).

A session is referred to by {session_token_uuid, user_uuid}: the uuid of its row in phoenix_kit_users_tokens and the user it belongs to. Neither is a secret, so the pair may travel in the signed (but not encrypted) session map of a nested LiveView; the raw session token must not, and never leaves the cookie session.

scope_for_session/2 rebuilds the user's PhoenixKit.Users.Auth.Scope from that row on every call, by the rules a web request follows (PhoenixKit.Users.Auth.UserToken.verify_session_token_uuid_query/1): the row is a "session" row and has not expired, its user is not a service user, and the scope is narrowed to the role this session acts as (PhoenixKit.Users.ActiveRole). The account must also pass the gate every authenticated page applies: a confirmed email while require_email_confirmation is on, and the invite-only gate (PhoenixKit.Users.Referrals.access_satisfied?/1), so a session acts with no more than its pages would let it. Logging out, revoking the session or blocking the user takes effect on the next call.

from_session/1 reads the reference from a LiveView's session map.

The pair is not a secret, but it is an in-process credential: any code that hands it to PhoenixKit.API.Executor.execute_as/5 or visible_for/3 acts as that session. Take it only from the signed session of the LiveView that runs in that session (from_session/1 in its connected mount), never from params or client events.

Maintenance mode is deliberately not checked on this path: the web shows the maintenance layout at mount, where nothing that calls the Executor is rendered.

Summary

Types

Why a session cannot act: :session_gone (no such live session: logged out, revoked, expired, not a session row, or a service user's), :mismatch (the session belongs to another user), :inactive (the user is blocked), :unconfirmed (the email is not confirmed and confirmation is required) or :referral_required (the invite-only gate still asks for a referral code).

t()

{session_token_uuid, user_uuid}.

Functions

The reference of the session a LiveView runs in, read from its session map: the "user_token" of the cookie session resolved to {session_token_uuid, user_uuid}. :error when there is no token or it is not a live session.

The scope of the live session session_token_uuid, which must belong to user_uuid.

Types

refusal()

@type refusal() ::
  :session_gone | :mismatch | :inactive | :unconfirmed | :referral_required

Why a session cannot act: :session_gone (no such live session: logged out, revoked, expired, not a session row, or a service user's), :mismatch (the session belongs to another user), :inactive (the user is blocked), :unconfirmed (the email is not confirmed and confirmation is required) or :referral_required (the invite-only gate still asks for a referral code).

t()

@type t() :: {String.t(), String.t()}

{session_token_uuid, user_uuid}.

Functions

from_session(arg1)

@spec from_session(map()) :: {:ok, t()} | :error

The reference of the session a LiveView runs in, read from its session map: the "user_token" of the cookie session resolved to {session_token_uuid, user_uuid}. :error when there is no token or it is not a live session.

Call it in the nested LiveView itself (a sticky live_render beside the page, e.g. a widget in the layout): LiveView merges the cookie session into the session of every LiveView, nested ones included, both in the connected mount (the socket's connect_info: [session: ...]) and in the static render (the parent's conn session). The reference read in a static render is the same one, but act on it (call the executor) only in the connected mount. Do not have a host page read the reference and pass it in the nested LiveView's :session: a widget rendered by the core layout has no host that holds the cookie session. Like PhoenixKitWeb.Users.MultiSession.impersonated?/1, call it where the session is signed and trusted, never with data from params or events.

scope_for_session(session_token_uuid, user_uuid)

@spec scope_for_session(term(), term()) ::
  {:ok, PhoenixKit.Users.Auth.Scope.t()} | {:error, refusal()}

The scope of the live session session_token_uuid, which must belong to user_uuid.

Returns {:ok, scope} narrowed to the session's active role, or {:error, reason} (refusal/0). Never raises on a malformed reference.