Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/mathieuprog/auth_z

Authorization library for Elixir applications
https://github.com/mathieuprog/auth_z

Last synced: about 2 months ago
JSON representation

Authorization library for Elixir applications

Awesome Lists containing this project

README

        

# AuthZ

AuthZ is a simple authorization library that allows you to

* ensure users are permitted to access protected routes;
* encourage authorization rules in contexts.

## Implementing authorization rules in contexts

Authorization is easy to implement using the power of pattern matching. Below is an
example where only authors are authorized to edit their posts.

`use AuthZ.Authorizer` simply injects a behaviour, requiring your module to implement
`authorize/3`. This function should receive an atom describing the action, the logged
in user and the resource intended to be accessed; the function should return `:ok` in
case the action is authorized, or a tuple containing `:error` as its first element and
an atom describing the reason of unauthorized access as its second element (allowing to
return different possible reasons of failure allows the controller for example to send
more specific error messages to the logs or the view).

```elixir
defmodule MyApp.Post.Policy do
use AuthZ.Authorizer

alias MyApp.Accounts.User
alias MyApp.Blog.Post

@unauthorized {:error, :unauthorized}

def authorize(:edit_question, %User{id: user_id}, %Post{author: user_id}) do
:ok
end

def authorize(:edit_question, _, _) do
@unauthorized
end
end
```

`use AuthZ.Authorizer` also injects the function `authorized?/3` which simply calls
the user-defined function `authorize/3` and returns a boolean indicating
authorization success or failure.

## Protecting routes against unauthorized users

Authorization can be enforced for some routes. Create a module using (`use`) the
`AuthZ.AuthorizationPlugMixin` module; then implement the callbacks
`handle_authentication_error/2` and `handle_authorization/3`. Both callbacks
receive a `Plug.Conn` struct and an atom identifying the set of routes that require
authorization; `handle_authorization/3` additionally receives the logged in user.

```elixir
defmodule MyAppWeb.Plugs.EnsureAuthorized do
use AuthZ.AuthorizationPlugMixin

import Plug.Conn
import Phoenix.Controller

alias MyApp.Accounts.User

def handle_authentication_error(conn, :admin_routes),
do: conn |> put_status(401) |> text("unauthenticated") |> halt()

def handle_authorization(conn, %User{type: "admin"}, :admin_routes),
do: conn

def handle_authorization(conn, _, _),
do: conn |> put_status(403) |> text("unauthorized") |> halt()
end
```

You may then use the new plug into a pipeline and ensure that routes requiring
authorization are accessed by authorized users only.

```elixir
pipeline :ensure_admin_routes_authorized do
plug MyAppWeb.Plugs.EnsureAuthorized,
resource: :admin_routes
end

scope "/admin", MyAppWeb, as: :admin do
pipe_through [:browser, :ensure_admin_routes_authorized]
# code
end
```

## Installation

Add `auth_z` for Elixir as a dependency in your `mix.exs` file:

```elixir
def deps do
[
{:auth_z, "~> 0.2.0"}
]
end
```

## HexDocs

HexDocs documentation can be found at [https://hexdocs.pm/auth_z](https://hexdocs.pm/auth_z).