Bastion can be installed by adding bastion
to your list of dependencies in mix.exs
:
def deps do
[
{:bastion, "~> 0.1.0"},
]
end
Overview (from Bastion main @moduledoc)
Bastion allows you to specify scopes in your Absinthe GraphQL Schemas, and then authorize requests only on requested fields.
To use Bastion, you need to:
- Set scopes on your GraphQL fields via Bastion's
scopes
macro - Set the authorized scopes on each Plug.Conn.t, via
Bastion.Plug.set_authorized_scopes/2
- Call
plug Bastion.Plug
ahead ofplug Absinthe.Plug
in your router
Bastion will reject requests to scoped fields that the user does not have an authorized scope for.
Notably, the request is rejected only if a scoped field is included - requests for non protected fields will pass through.
In your Absinthe.Schema:
defmodule MyAbsintheSchema do
use Absinthe.Schema
use Bastion
query do
field :users, list_of(:user) do
scopes [:admin]
end
end
object :user do
field :name, :string
end
end
In your router:
defmodule MyRouter do
use Plug
plug :set_scopes
defp set_scopes(conn, _opts) do
# get authorized scopes from your own user or domain logic
Bastion.Plug.set_authorized_scopes(conn, [:admin])
end
plug Bastion.Plug, schema: MyAbsintheSchema
plug Absinthe.Plug, schema: MyAbsintheSchema
end
This is effectively an authorization middleware, and so its opinion leans toward rejecting requests more quickly than not.
If you do not set the authorized scopes on the connection with a call to Bastion.Plug.set_authorized_scopes/2
BEFORE calling plug Bastion.Plug
in your router,
ALL of the requests will be rejected.
If you're getting started with Bastion, you can write a simple plug function to set the authorized scopes to an empty list, as exemplified in the readme.