satom99

satom99

How do you do tokens and permissions? #REST

In a REST API, how do you handle tokens and permissions?

On tokens, once you have retrieved the token from the Authorization header, how do you verify you have issued that token in the past? Do you store it in your database and check whether an entry for it exists (and thus make sure you have indeed issued it) and what user it is liked to? Do you have a separate table for tokens just so you can have numerous tokens for an user, over a single one that is perhaps stored in the users table in a token column? Do you use Phoenix.Token and verify/4 it to get its stored user id and go from there? Why would you use Phoenix over generating a random string of a certain length each time you want to issue a token - how would this be done in Elixir?

On permissions, lets say we have a specific resource post that you want an user to have access to edit but not delete. How do you store and handle this kind of permissions? Perhaps a table named post_permissions with a bit with the user’s permissions? That would fit the case where there’s a single resource to handle, how would it go though for a system where post is just one of the many restricted resources?

Most Liked

OvermindDL1

OvermindDL1

Two standard ways when in-system like that. Either put the permissions in the database and look up the user’s permissions when needed, or store the permissions inside the Phoenix.Token directly, saving the database call, however that also means it will not be cleared out if, say, they are removed permission from later, however using very short-lived tokens is perfectly fine for that.

@satom99 is already using Phoenix.Token, which can do everything Guardian can do in this context but without the extra dependency and cost of JSON deserialization

People really need to quit recommending Guardian for areas where it is ill-suited. This is a perfect user-case for what they are already using, Phoenix.Token. Guardian is great for things like passing credentials to a remote non-connected server. If you are using it in the same server then it is just needless overhead.

And doing that you then remove the entire advantage of using Guardian at all (which is to keep you from having to hit a database when doing a cross-site call), why use Guardian at all in this case??

Still hitting the database, you may as well put the permissions in the database itself then and don’t use a token at all but instead just the session to hold the link, of which you can easily wipe if, say, they log out elsewhere so the session is then wiped from the database preventing replay attacks. Guardian on the other hand would let you trivially perform replay attacks, so quit suggesting it please! ^.^;

Stateless logins are nice, but you generally want short-lived tokens then to minimize replay attack abilities, and JWT is useful only if passing to another server; again if you are doing this all in the same server that you control then use Phoenix.Token, it is not as heavy, can hold arbitrary data, is faster, but does require that the server is on the BEAM or so all using the same key, JWT allows you to send data safely from server-to-server.

JWT claims are just simple on/off, fine for very simple things, but not good for more detailed permission types.

Exactly! This is the replay attack, they just replay the old token. If it is all in-system then better to keep it in the database and don’t use tokens at all!

If you are having Guardian hit the database anyway, they why are you using Guardian at all?! It makes no sense!

  • If you are doing the authentication and authorization all in the same server and you’ll be hitting the database anyway, don’t use tokens, just use Phoenix’s Session and the database, you have significantly greater control.
  • If you are doing the authentication and authorization all in the same server and you don’t always need to hit the database for short-lived authorization permissions, use Phoenix.Token and put the allowed permission inside the token itself (like via Phoenix.Token.sign("perms", [:read, :edit]) or whatever, you can encode whatever you want in it in any form that you want).
  • If you are doing authentication on one server and doing authorization on ‘another’ server and those two servers do not use the same secure phoenix keys, then and only then is JWT (Guardian) useful. Don’t use it otherwise, it is not safe and/or not secure in other contexts.
OvermindDL1

OvermindDL1

Other than it is the wrong abstraction? A couple of other reasons:

  • Significantly larger in payload because of all the packed json stuff required by the JWT spec.
  • More costly to (de)serialize, which just makes your request take that ever slightly bit longer.
  • Yet Another dependency when it adds about nothing unless JWT is really needed.
  • To use it properly you either need to push it in the DB yourself anyway or bring in Yet Another dependency like guardian_db.

Etc… ^.^;

wfgilman

wfgilman

Thanks, I appreciate your thoughtful comments as always.

Where Next?

Popular in Questions Top

vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
New
Tee
can someone please explain to me how Enum.reduce works with maps
New
mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
mgjohns61585
Could someone help me? I’m making my first elixir program, number guessing game. I can’t figure out how to convert the user’s guess from ...
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
dotdotdotPaul
Okay, I’m having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I’m sure I’...
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
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New

Other popular topics Top

sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
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
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New

We're in Beta

About us Mission Statement