View Source Guardian.Permissions (Guardian v2.3.1)

An optional plugin to Guardian to provide permissions for your tokens.

These can be used for any token types since they only work on the claims.

Permissions are set on a per implementation module basis. Each implementation module can have their own sets. Permissions are similar in concept to OAuth2 scopes. They're encoded into a token and the permissions granted last as long as the token does. This makes it unsuitable for highly dynamic permission schemes. They're best left to an application to implement.

For example. (at the time of writing) some of the Facebook permissions are:

  • public_profile
  • user_about_me
  • user_actions.books
  • user_actions.fitness
  • user_actions.music

To create permissions for your application similar to these:

defmodule MyApp.Auth.Token do

  use Guardian, otp_app: :my_app,
                         permissions: %{
                         default: [:public_profile, :user_about_me]
                         user_actions: %{
                           books: 0b1,
                           fitness: 0b100,
                           music: 0b1000,
                         }
                       }

  use Guardian.Permissions, encoding: Guardian.Permissions.BitwiseEncoding
  # Per default permissions will be encoded Bitwise, but other encoders also exist
  #  * Guardian.Permissions.TextEncoding
  #  * Guardian.Permissions.AtomEncoding
  # It is even possible to supply your own encoding module

  # snip

  def build_claims(claims, _resource, opts) do
    claims =
      claims
      |> encode_permissions_into_claims!(Keyword.get(opts, :permissions))
    {:ok, claims}
  end
end

This will take the permission set in the opts at :permissions and put it into the "pems" key of the claims as a map of %{set_name => integer}.

The permissions can be defined as a list (positional value based on index) or a map where the value for each permission is manually provided.

They can be provided either as options to use Guardian or in the config for your implementation module.

Once you have a token, you can interact with it.

# Get the encoded permissions from the claims
found_perms = MyApp.Auth.Token.decode_permissions_from_claims(claims)

# Check if all permissions are present
has_all_these_things? =
  claims
  |> MyApp.Auth.Token.decode_permissions_from_claims
  |> MyApp.Auth.Token.all_permissions?(%{default: [:user_about_me, :public_profile]})

# Checks if any permissions are present
show_any_media_things? =
  claims
  |> MyApp.Auth.Token.decode_permissions_from_claims
  |> MyApp.Auth.Token.any_permissions?(%{user_actions: [:books, :fitness, :music]})

using-with-plug

Using with Plug

To use a plug for ensuring permissions you can use the Guardian.Permissions module as part of a Guardian pipeline.

# After a pipeline has setup the implementation module and error handler

# Ensure that both the `public_profile` and `user_actions.books` permissions
# are present in the token
plug Guardian.Permissions, ensure: %{default: [:public_profile], user_actions: [:books]}

# Allow the request to continue when the token contains any of the permission sets specified
plug Guardian.Permissions, one_of: [
  %{default: [:public_profile], user_actions: [:books]},
  %{default: [:public_profile], user_actions: [:music]},
]

# Look for permissions for a token in a different location
plug Guardian.Permissions, key: :impersonate, ensure: %{default: [:public_profile]}

If the token satisfies either the permissions listed in ensure or one of the sets in the one_of key the request will continue. If not, then auth_error callback will be called on the error handler with auth_error(conn, {:unauthorized, reason}, options).

Link to this section Summary

Functions

See Guardian.Permissions.Plug.call/2.

See Guardian.Permissions.Plug.init/1.

Provides an encoded version of all permissions, and all possible future permissions for a permission set.

Link to this section Types

@type input_label() :: permission_label()
@type input_permissions() :: %{optional(input_label()) => input_set()}
@type input_set() :: permission_set() | permission()
@type label() :: atom()
@type permission() :: pos_integer()
@type permission_label() :: String.t() | atom()
@type permission_set() ::
  [permission_label(), ...] | %{optional(label()) => permission()}
@type plug_option() ::
  {:ensure, permission_set()}
  | {:one_of, [permission_set(), ...]}
  | {:key, atom()}
  | {:module, module()}
  | {:error_handler, module()}
@type t() :: %{optional(label()) => permission_set()}

Link to this section Functions

See Guardian.Permissions.Plug.call/2.

See Guardian.Permissions.Plug.init/1.

Provides an encoded version of all permissions, and all possible future permissions for a permission set.