Packages
ash_authentication
4.4.1
5.0.0-rc.12
5.0.0-rc.11
5.0.0-rc.10
5.0.0-rc.9
5.0.0-rc.8
5.0.0-rc.7
5.0.0-rc.6
5.0.0-rc.5
5.0.0-rc.4
5.0.0-rc.3
5.0.0-rc.2
5.0.0-rc.1
5.0.0-rc.0
4.14.1
4.14.0
4.13.7
4.13.6
4.13.5
4.13.4
4.13.3
4.13.2
retired
4.13.1
retired
4.13.0
4.12.0
4.11.0
4.10.0
4.9.9
4.9.8
4.9.7
4.9.6
4.9.5
4.9.4
4.9.3
4.9.2
4.9.1
4.9.0
4.8.7
4.8.6
4.8.5
4.8.3
4.8.2
4.8.1
4.8.0
4.7.6
4.7.5
4.7.4
4.7.3
4.7.2
4.7.1
4.7.0
4.6.4
4.6.3
4.6.2
4.6.1
4.6.0
4.5.6
4.5.5
4.5.4
4.5.3
4.5.2
4.5.1
4.5.0
4.4.9
4.4.8
4.4.7
4.4.6
4.4.5
4.4.4
4.4.3
4.4.2
4.4.1
4.4.0
4.3.12
4.3.11
4.3.10
4.3.9
4.3.8
4.3.7
4.3.6
4.3.5
4.3.4
4.3.3
4.3.2
4.3.1
4.3.0
4.2.7
4.2.6
4.2.5
4.2.4
4.2.3
4.2.2
4.2.1
4.2.0
4.1.0
4.0.4
4.0.3
4.0.2
4.0.1
4.0.0
4.0.0-rc.6
4.0.0-rc.5
4.0.0-rc.3
4.0.0-rc.2
4.0.0-rc.1
4.0.0-rc.0
3.12.4
3.12.3
3.12.2
3.12.1
3.12.0
3.11.16
3.11.15
3.11.14
3.11.13
3.11.12
3.11.11
3.11.10
3.11.9
3.11.8
3.11.7
3.11.6
3.11.5
3.11.4
3.11.3
3.11.2
3.11.1
3.11.0
3.10.8
3.10.7
3.10.6
3.10.5
3.10.4
3.10.3
3.10.2
3.10.1
3.10.0
3.9.6
3.9.5
3.9.4
3.9.3
3.9.2
3.9.1
3.9.0
3.8.0
3.7.9
3.7.8
3.7.6
3.7.5
3.7.4
3.7.3
3.7.2
3.7.1
3.7.0
3.6.1
3.6.0
3.5.3
3.5.2
3.5.1
3.5.0
3.3.1
3.3.0
3.2.2
3.2.1
3.2.0
3.1.0
3.0.3
Authentication extension for the Ash Framework.
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
lib/ash_authentication/plug.ex
defmodule AshAuthentication.Plug do
@moduledoc ~S"""
Generate an authentication plug.
Use in your app by creating a new module called `AuthPlug` or similar:
```elixir
defmodule MyAppWeb.AuthPlug do
use AshAuthentication.Plug, otp_app: :my_app
def handle_success(conn, _activity, user, _token) do
conn
|> store_in_session(user)
|> send_resp(200, "Welcome back #{user.name}")
end
def handle_failure(conn, _activity, reason) do
conn
|> send_resp(401, "Better luck next time")
end
end
```
### Using in Phoenix
In your Phoenix router you can add it:
```elixir
scope "/auth" do
pipe_through :browser
forward "/", MyAppWeb.AuthPlug
end
```
In order to load any authenticated users for either web or API users you can add the following to your router:
```elixir
import MyAppWeb.AuthPlug
pipeline :session_users do
plug :load_from_session
end
pipeline :bearer_users do
plug :load_from_bearer
end
scope "/", MyAppWeb do
pipe_through [:browser, :session_users]
live "/", PageLive, :home
end
scope "/api", MyAppWeb do
pipe_through [:api, :bearer_users]
get "/" ApiController, :index
end
```
### Using in a Plug application
```elixir
use Plug.Router
forward "/auth", to: MyAppWeb.AuthPlug
```
Note that you will need to include a bunch of other plugs in the pipeline to
do useful things like session and query param fetching.
"""
alias Ash.Resource
alias AshAuthentication.Plug.{Defaults, Helpers, Macros}
alias Plug.Conn
require Macros
@type activity :: {atom, atom}
@type token :: String.t()
@doc """
When authentication has been succesful, this callback will be called with the
conn, the successful activity, the authenticated resource and a token.
This allows you to choose what action to take as appropriate for your
application.
The default implementation calls `store_in_session/2` and returns a simple
"Access granted" message to the user. You almost definitely want to override
this behaviour.
"""
@callback handle_success(Conn.t(), activity, Resource.record() | nil, token | nil) :: Conn.t()
@doc """
When there is any failure during authentication this callback is called.
Note that this includes not just authentication failures but potentially
route-not-found errors also.
The default implementation simply returns a 401 status with the message
"Access denied". You almost definitely want to override this.
"""
@callback handle_failure(Conn.t(), activity, any) :: Conn.t()
@doc false
@spec __using__(keyword) :: Macro.t()
defmacro __using__(opts) do
otp_app =
opts
|> Keyword.fetch!(:otp_app)
|> Macro.expand_once(__CALLER__)
quote do
require Macros
Macros.validate_subject_name_uniqueness(unquote(otp_app))
@behaviour AshAuthentication.Plug
@behaviour Plug
import Plug.Conn
defmodule Router do
@moduledoc false
use AshAuthentication.Plug.Router,
otp_app: unquote(otp_app),
return_to:
__MODULE__
|> Module.split()
|> List.delete_at(-1)
|> Module.concat()
end
Macros.define_load_from_session(unquote(otp_app))
Macros.define_load_from_bearer(unquote(otp_app))
Macros.define_revoke_bearer_tokens(unquote(otp_app))
@impl true
defdelegate handle_success(conn, activity, user, token), to: Defaults
@impl true
defdelegate handle_failure(conn, activity, error), to: Defaults
defoverridable handle_success: 4, handle_failure: 3
@impl true
defdelegate init(opts), to: Router
@impl true
defdelegate call(conn, opts), to: Router
defdelegate set_actor(conn, subject_name), to: Helpers
defdelegate store_in_session(conn, user), to: Helpers
end
end
end