AshAuthentication.Sender behaviour (ash_authentication v5.0.0-rc.4)

Copy Markdown View Source

A module to implement sending of a token to a user.

Allows you to glue sending of instructions to swoosh, ex_twilio or whatever notification system is appropriate for your application.

Senders should return :ok on success or {:error, reason} on failure. Failures will propagate as AshAuthentication.Errors.SenderFailed errors and cause the authentication action to fail.

If you need retry logic or want to avoid blocking the action on email delivery, consider using a job queue like Oban. Your sender can insert a job and return :ok immediately, letting the job handle delivery and retries asynchronously.

Example

Implementing as a module:

defmodule MyApp.PasswordResetSender do
  use AshAuthentication.Sender
  import Swoosh.Email

  def send(user, reset_token, _opts) do
    new()
    |> to({user.name, user.email})
    |> from({"Doc Brown", "emmet@brown.inc"})
    |> subject("Password reset instructions")
    |> html_body("""
      <h1>Password reset instructions</h1>
      <p>
        Hi #{user.name},<br />

        Someone (maybe you) has requested a password reset for your account.
        If you did not initiate this request then please ignore this email.
      </p>
      <a href="https://example.com/user/password/reset?#{URI.encode_query(reset_token: reset_token)}\">
        Click here to reset
      </a>
    """)
    |> MyApp.Mailer.deliver()
    |> case do
      {:ok, _} -> :ok
      {:error, reason} -> {:error, reason}
    end
  end
end

defmodule MyApp.Accounts.User do
  use Ash.Resource,
    extensions: [AshAuthentication],
    domain: MyApp.Accounts

  authentication do
    strategies do
      password :password do
        resettable do
          sender MyApp.PasswordResetSender
        end
      end
    end
  end
end

You can also implement it directly as a function:

defmodule MyApp.Accounts.User do
  use Ash.Resource,
    extensions: [AshAuthentication],
    domain: MyApp.Accounts

  authentication do
    strategies do
      password :password do
        resettable do
          sender fn user, token ->
            MyApp.Mailer.send_password_reset_email(user, token)
          end
        end
      end
    end
  end
end

Summary

Callbacks

send(user, token, opts)

@callback send(
  user :: Ash.Resource.record() | String.t(),
  token :: String.t(),
  opts :: list()
) ::
  :ok | {:error, term()}

Sending callback.

This function will be called with a value representing a user, the token and any options passed to the module in the DSL.

Should return :ok on success or {:error, reason} on failure.