Authentication/authorization options for GraphQL subscriptions?

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.

@OvermindDL1 would advise You to use Phoenix.Token instead of jwt. It is lighter and more appropriate for this situation.

Also in the Absinthe book, they use Phoenix.Token to sign in user.

6 Likes

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

2 Likes

Another difference between the two is You cannot decode phoenix token client side, while You can decode with jwt.

1 Like

Thanks for the info.

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?

1 Like

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…

1 Like

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!). :slight_smile:

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).

2 Likes

agreed, fully aware that I’m using guardian+guardian_db as a token auth system - and that it’s not real jwt in any way… who needs that :stuck_out_tongue:

time to market?/built your own auth before your app? etc :wink:

outlog, I’m curious, in your set-up, are you then essentially using “stateful tokens” in a sort of session mechanism?

Would that be functionally the same as session cookies?

If so, what are the advantages of your choice? Does it seem to offer a better UI/UX for the end user, etc?

2 Likes