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
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
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
Thanks, I appreciate your thoughtful comments as always.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








