AshAuthentication.Phoenix.Plug (ash_authentication_phoenix v3.0.0-rc.9)

View Source

Helper plugs mixed in to your router.

When you use AshAuthentication.Phoenix.Router this module is included, so that you can use these plugs in your pipelines.

Summary

Functions

Attempt to retrieve actors from the Authorization header(s).

Attempt to retrieve all actors from the connections' session.

Revoke all token(s) in the Authorization header(s).

Revoke all token(s) in the session.

Set the actor from the connection's assigns.

Build a scope from the connection's assigns and store it, along with the actor.

Attempts to sign in the user with the remember me token if the user is not already signed in.

Skip Phoenix CSRF protection for OAuth2/OIDC callback POSTs.

Store the actor in the connections' session.

Functions

load_from_bearer(conn, opts)

@spec load_from_bearer(
  Plug.Conn.t(),
  keyword()
) :: Plug.Conn.t()

Attempt to retrieve actors from the Authorization header(s).

A wrapper around AshAuthentication.Plug.Helpers.retrieve_from_bearer/2 with the otp_app as extracted from the endpoint.

load_from_session(conn, opts)

@spec load_from_session(
  Plug.Conn.t(),
  keyword()
) :: Plug.Conn.t()

Attempt to retrieve all actors from the connections' session.

A wrapper around AshAuthentication.Plug.Helpers.retrieve_from_session/2 with the otp_app as extracted from the endpoint.

revoke_bearer_tokens(conn, opts)

@spec revoke_bearer_tokens(Plug.Conn.t(), any()) :: Plug.Conn.t()

Revoke all token(s) in the Authorization header(s).

A wrapper around AshAuthentication.Plug.Helpers.revoke_bearer_tokens/2 with the otp_app as extracted from the endpoint.

revoke_session_tokens(conn, opts)

@spec revoke_session_tokens(Plug.Conn.t(), any()) :: Plug.Conn.t()

Revoke all token(s) in the session.

A wrapper around AshAuthentication.Plug.Helpers.revoke_session_tokens/2 with the otp_app as extracted from the endpoint.

set_actor(conn, subject_name)

@spec set_actor(Plug.Conn.t(), atom()) :: Plug.Conn.t()

Set the actor from the connection's assigns.

This plug takes the user from conn.assigns.current_<subject_name> (set by load_from_session/2) and sets it as the Ash actor via Ash.PlugHelpers.set_actor/2.

This is required for authentication strategies that need to access the current user via Ash.PlugHelpers.get_actor/1.

Example

pipeline :browser do
  plug :load_from_session
  plug :set_actor, :user
end

set_scope(conn, scope_module)

@spec set_scope(Plug.Conn.t(), module() | keyword()) :: Plug.Conn.t()

Build a scope from the connection's assigns and store it, along with the actor.

This plug takes the user from conn.assigns.current_<subject_name> (set by load_from_session/2 or load_from_bearer/2) and the tenant from Ash.PlugHelpers.get_tenant/1, wraps them in your scope struct, and assigns it to conn.assigns.current_<subject_name>_scope. The scope struct is expected to implement Ash.Scope.ToOpts, so it can be passed straight into Ash actions:

Ash.read!(query, scope: conn.assigns.current_user_scope)

It is a superset of set_actor/2 — it also sets the Ash actor via Ash.PlugHelpers.set_actor/2, so use set_scope instead of set_actor, not alongside it.

The scope module is referenced only as data and instantiated at runtime with Kernel.struct/2, so this plug introduces no compile-time dependency on your scope module (and therefore no router recompilation cycle). Keys absent from the struct are ignored rather than raising.

Options

Pass the scope module directly for the common single-subject case, or a keyword list to override the subject:

  • :scope - the scope module to instantiate. Required.
  • :subject - the subject name to build the scope for. Defaults to :user.
  • :default_scope? - when true, also assigns the scope to current_scope (in addition to current_<subject_name>_scope). This designates the subject as the application's primary one and exposes it under the singular current_scope assign that Phoenix-idiomatic code expects. Defaults to false.

Example

pipeline :browser do
  plug :load_from_session
  plug :set_scope, scope: MyApp.Accounts.Scope, default_scope?: true
end

pipeline :admin do
  plug :load_from_session
  plug :set_scope, scope: MyApp.Accounts.Scope, subject: :admin
end

sign_in_with_remember_me(conn, opts)

@spec sign_in_with_remember_me(
  Plug.Conn.t(),
  keyword()
) :: Plug.Conn.t()

Attempts to sign in the user with the remember me token if the user is not already signed in.

A wrapper around AshAuthentication.Plug.Helpers.sign_in_with_remember_me/2 with the otp_app as extracted from the endpoint.

skip_csrf_for_oauth_callback(conn, opts)

@spec skip_csrf_for_oauth_callback(
  Plug.Conn.t(),
  keyword()
) :: Plug.Conn.t()

Skip Phoenix CSRF protection for OAuth2/OIDC callback POSTs.

Providers that use response_mode=form_post (e.g. Sign in with Apple) return the callback as a cross-site POST that carries no CSRF token — the OAuth state parameter is the CSRF defence there. Phoenix's :protect_from_forgery would otherwise reject it before it reaches the callback. This plug marks such requests to skip CSRF, and must therefore run before :protect_from_forgery.

Only POST requests to a callback path (<auth_routes_prefix>/…/callback) are affected. Every other request — including all other authentication POSTs (password, magic link, TOTP, WebAuthn, …) — remains fully CSRF-protected.

Options

  • :auth_routes_prefix - the prefix your auth routes are mounted under. Defaults to "/auth".

Example

pipeline :browser do
  # ...
  plug :skip_csrf_for_oauth_callback
  plug :protect_from_forgery
end

store_in_session(conn, actor)

@spec store_in_session(Plug.Conn.t(), Ash.Resource.Record.t()) :: Plug.Conn.t()

Store the actor in the connections' session.