I am planning a Phoenix app with GraphQL subscriptions, using Absinthe. I would need authentication, and am wondering whether I should be looking at JWT auth – or something else?
Up to now, I have been using fairly basic Phoenix apps, with simple cookie based session authentication.
what @kokolegorille said - jwt with guardian is an option though - especially if you need/want to be able to invalidate tokens - or keep tabs on a users sessions - eg show which devices/computers they are signed in on - incl granularly signing one of those out etc. - then you need something like guardian + guardian_db
I probably read through most of the threads here regarding token-based authentication. One takeaway is that Guardian is currently very popular, but doesn’t fit my use-case since my web-app does not require server-to-server communication and thus seems overkill.
After rereading “Programming Phoenix”, especially Chapter 5. Authenticating Users, I am leaning towards still using traditional session-based authentication (as detailed in the book).
My main requirement would be role-based authorization, and it would not be a problem to manage this in the database, combined with an authentication plug. The main app is basically request /response–type in nature.
Regarding socket authentication, including GraphQL subscriptions, the book mentions that token authentication works better because the connection is a long-duration connection, and that we cannot access session cookies in a channel. Hence it recommends the generation of a Phoenix.token for already authenticated users and passing that to the socket on the front end.
So, my thinking is to use session-based authentication for the main app, and tokens only for the WebSocket stuff. I still need to think through whether we would need to the ability to revoke tokens or not, and the implications of that.
Just wondering if there are any big gaping holes in this flow?
jwt can be viewed as overkill - you probably don’t need to encode stuff in your token (I don’t) - and when you add something like guardian_db it kinda defies the concept of this stateless token you can pass around, and you add an extra DB call to each request. (I run everything but initial auth over websockets so very little/no performance penalty in my setup - ymmv) - also think jwts are meant to be shortlived/rotated (I don’t rotate mine) etc.
Think you got it - check for a low :max_age on the Phoenix.token in the socket connect - and you should be good to go.
Then it’s more about how you do the session based auth, think a common pattern is having something like a :authentication_token column in your users schema - that is stored/excahnged in the cookie…
so in the superadmin role got their laptop stolen scenario - you can regenerate that :authentication_token and thus signout/invalidate all that superadmin’s sessions…
Actually you can’t invalidate JWT, that is by it’s design, so I think you have this backwards?
Using something like guardian_db will store a copy of the JWT in the DB that you can then compare against, but then you are losing all purpose of JWT (as the remote server won’t have access to your database verification for example).
Actually JWT is just JSON, no decoding really needed. Although guardian supports encrypting/signing it, which is useful when sending it to other servers via the client (which is the best use-case of Guardian!).
Correct, if you don’t use server<->server data passing then Guardian is pretty well entirely useless for your use-case.
Absolutely. They should generally only be used for one request or just to give access to something for, say, X minutes or so on some other server (or database-less locally, but you can do that via phoenix token more easily then).