mariosangiorgio

mariosangiorgio

Is there any recommended way of doing API authentication?

I’m working on a toy project and I’d like to add user authentication to regulate the access to its Phoenix API.

As a starting point, I found this post and I like the approach it proposes.

I also found that Phoenix has the facility to generate tokens (Phoenix.Token). I see that the post I linked above uses SecureRandom to generate tokens. Is it recommended to use the output of Phoenix.Token.sign instead? Given that it allows to check whether the token is expired or not it seems to be strictly better than a random number. That would also save me from needing to keep track of the active sessions in the database.

That approach should cover pretty much all I need. Later on I might want to invalidate tokens if the user explicitly logs out, but I could easily do that with a blacklist.

So, everything is good but that I also found out that there are a several competing authentication libraries and I wanted to check if any of those is the primary choice of the community and it’s recommended over the approach I’m thinking of adopting.

Most Liked

OvermindDL1

OvermindDL1

Do note that Guardian tokens are JWT, meaning they are large and heavy and overkill for many cases. If you can store the authorization needed into the JWT so you can prevent hitting the database in the API then Guardian is worth it, else use Phoenix Tokens and authorize via the database or cache or so.

OvermindDL1

OvermindDL1

I just roll my own since it is only a half-dozen or so lines of code anyway. Like here is the meat of mine:

  def verify_login(%Plug.Conn{}=conn) do
    with\
      token = Plug.Conn.get_session(conn, "account"),
      {:ok, {account_id, account_session}} <- verify("account", token, max_age: token_max_age()),
      true <- confirm_account_id_session?(account_id, account_session) do
      Plug.Conn.assign(conn, :account_id, account_id)
    else
      err -> normalize(err)
    end
  end
  def verify_login(token) when is_binary(token), do: verify("account_id", token, max_age: token_max_age())
  def verity_login(token) do
    Logger.warn("Invalid token typed passed to verity_login of:  #{inspect token}")
    {:error, :invalid_token}
  end

I can pass either a Plug.Conn or a raw token string to this, it then calls verify:

  def verify(salt, token, opts \\ []), do: Phoenix.Token.verify(get_token_key(), salt, token, opts)

Which just returns the data of the token. There are a dozen or so other little helper functions too, like I don’t store any permissions or so data in the token (but you could to save a database hit) and instead I just store a ‘session’ token inside the phoenix token, which I look up via:

  def get_account_id_session(account_id, account_session) do
    query =
      from s in DB.Account.Session,
      where: is_nil(s.removed_at) and
        ((s.id == ^account_id and s.token == ^account_session) or (s.id == ^account_session and s.token == ^account_id))
    Repo.one(query)
  end

I just confirm the account id and session id both (which is stored in the phoenix token) exist in the database (the functions that call these confirm that the age of the token is valid too for the given user and so forth). It is pretty simple stuff and honestly I’ve over-engineered it, you could do it in like 3 lines of code. ^.^;

kokolegorille

kokolegorille

I like to use guardian for this task

You can find examples on how to implement it…

https://github.com/ueberauth/guardian

Where Next?

Popular in Questions Top

chokchit
** (DBConnection.ConnectionError) connection not available and request was dropped from queue after 2733ms. You can configure how long re...
New
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
yawaramin
In the Dialyzer docs ( dialyzer — OTP 29.0.2 (dialyzer 6.0.1) ), there is a way to turn off a specific warning for a function: -dialyzer...
New

Other popular topics Top

lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
Lily
In templates/appointment/index.html.eex: &lt;%= for appointment &lt;- @appointments do %&gt; &lt;tr&gt; &lt;td&gt;&lt;%= appoi...
New
AstonJ
Please see the new poll here: Which code editor or IDE do you use? (Poll) (2022 Edition) It’s been a while since we first asked this, I...
208 31307 143
New
nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
klo
Got a question about when to concat vs. prepending items to list then reversing to achieve appending. So i know lists boil down to [1 | ...
New
Qqwy
Update: How to use the Blogs &amp; Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3271 127536 1222
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New
svb
Hi! Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New

We're in Beta

About us Mission Statement