How to implement Authorization in elixir and phoenix
Tags: elixir, phoenix, authorization, ecto
Published: 2019-10-06 11:34:49

---
title: How to implement Authorization in elixir and phoenix 
published: true
description: Implementing custom authorization is very easy in phoenix. There are many reasons and advantages for using custom authorization system a over a dedicated framework
tags: elixir, phoenix, authorization, ecto
---

In the world of web development, ensuring the security and privacy of user data is paramount. One of the key aspects of this is implementing robust user authorization systems. In this article, we will delve into the process of building a simple yet effective user authorization system for the Phoenix framework, a system that can be seamlessly integrated into applications of various sizes. Whether you're a seasoned Elixir developer or a beginner just getting started with Phoenix, this guide will provide you with a practical approach to implementing authorization in your applications.

Essentially, authorization allows a user or an entity to perform an action if they have the necessary permissions. There are multiple approaches to address this. But this one matches my requirements and it allows me to easily apply this logic between multiple projects. As usual there are libraries to do this. But in my case it was not necessary. 

Let's assume we want to authorize a rule where 'only the user who created a post can delete the post'. Basically, We can simply create a function to do that and call it from the action accessing it.

```elixir
def authorize_delete_post(user, post) do
  if(user.id == post.user_id) do
    {:ok}
  else
   {:unauthorized}
  end
end
```
This is the simplest type of authorization. It will work fine, but if you're reading this, you're likely seeking a more robust solution.

### Authorize module

It is recommended to centralize all authorization logic. So, we can create a new module `Authorize` and move it there.

```elixir
defmodule MyApp.Authorize do

alias MyApp.Accounts.User
alias MyApp.Posts.Post

 def check(:delete_post, %User{id: user_id}, %Post{user_id: user_id}), do: {:ok}
 def check(:delete_post, %User{}, %Post{}), do: {:unauthorized}
end
```

From now on, we can call `Authorize.check(:delete_post, user, post)` to authorize the user to delete the post. it will return `{:ok}` if `user_id` of post is equal to `id` of user.

We can refactor here, as there will be a need to authorize many more actions. But remember, this part should be done based on your application's requirements.

```elixir
defmodule MyApp.Authorize

alias MyApp.Accounts.User
alias MyApp.Posts.Post

 def check(:delete_post, %User{}=user, %Post{}=post), do: authorize_created_by(user, post)
 

 defp authorize_created_by(%User{id: user_id}, %{user_id: user_id}), do: ok
 defp authorize_created_by(%User{}, _), do: unauthorized

 defp ok, do: {:ok}
 defp unauthorized, do: {:unauthorized}
end
```

we can latter add 
```elixir
def check(:update_post, %User{}=user, %Post{}=post), do: authorize_created_by(user, post)
```
 to do authorization for updating the post.

That concludes the implementation part. Now, we can optimize on the controller end.

## Sending common error messages upon authorization error.

we have a plug in phoenix controller called `action_fallback` that allows us to call another plug as a fallback action. Follow the examples from  https://hexdocs.pm/phoenix/Phoenix.Controller.html#action_fallback/1 to understand how to do that. I don't want to cover it here since it is already well documented. Also as a bonus you have information on how you should call our authorization module in there. So, in our case the FallbackController will have this plug.
```elixir
def call(conn, {:unauthorized}) do
  # do something and return 403
end
```

## Conclusion

In conclusion, implementing a user authorization system in Elixir and Phoenix doesn't have to be a daunting task. With the right approach and understanding, you can build a system that is not only simple and easy to read, but also easy to implement and optimize based on your application's business logic. The method we've explored in this article provides a solid foundation, but remember, the world of web development is always evolving. Always be open to exploring new techniques, libraries, and best practices to ensure your authorization system remains robust, secure, and efficient. Happy coding!