defmodule SansPassword do @moduledoc """ Passwordless authentication helpers for Guardian. """ @magic "magic" @access "access" @callback deliver_magic_link( resource :: any, magic_token :: String.t(), params :: map ) :: any defmacro __using__(_) do quote do @behaviour SansPassword def encode_magic(resource, claims \\ %{}) do SansPassword.encode_magic(__MODULE__, resource, claims) end def decode_magic(magic_token, claims \\ %{}) do SansPassword.decode_magic(__MODULE__, magic_token, claims) end def encode_access(resource, claims \\ %{}) do SansPassword.encode_access(__MODULE__, resource, claims) end def decode_access(access_token, claims \\ %{}) do SansPassword.decode_access(__MODULE__, access_token, claims) end def exchange_magic(magic_token) do SansPassword.exchange_magic(__MODULE__, magic_token) end def send_magic_link(resource, claims \\ %{}, params \\ %{}) do SansPassword.send_magic_link(__MODULE__, resource, claims, params) end end end def encode_magic(guardian, resource, claims \\ %{}) do guardian.encode_and_sign(resource, claims, token_type: @magic) end def decode_magic(guardian, magic_token, claims \\ %{}) do guardian.resource_from_token(magic_token, claims, token_type: @magic) end def encode_access(guardian, resource, claims \\ %{}) do guardian.encode_and_sign(resource, claims, token_type: @access) end def decode_access(guardian, access_token, claims \\ %{}) do guardian.resource_from_token(access_token, claims, token_type: @access) end def exchange_magic(guardian, magic_token) do with {:ok, _, {token, claims}} <- guardian.exchange(magic_token, @magic, @access) do {:ok, token, claims} end end def send_magic_link(guardian, resource, claims \\ %{}, params \\ %{}) do with {:ok, magic_token, claims} <- guardian.encode_magic(resource, claims) do guardian.deliver_magic_link(resource, magic_token, params) {:ok, magic_token, claims} end end end