Guardian/JWT vs Phoenix.Token?

A blacklist is by its very nature almost always a small subset of your total user base. Also, you only need to keep an item in the blacklist until the JWT key expires. Thus, the size of the blacklists is merely the number of users blacklisted in the last N minutes, which is usually a fraction of the total number of users.

4 Likes

This whole argument conveniently ignores the case when people operate in heterogeneous environment. JWT is fairly widely supported and works fine across multiple stacks.

1 Like

I’m using JWT (via Guardian) as a login ‘session’ token (bad form I know) and web page access permissions hit the database anyway, however the same JWT is also used on the API area, which does not always hit the database and uses the JWT course-grained permissions where possible. The JWT’s elapse really fast but get regenerated by the server as needed if the rest of the session data from phoenix matches as well. The main system uses a very very fine grained permission setup that I would not see a way to be able to stuff into a JWT in any kind of compressed way at all so I cannot use them strictly for main web interaction, but it is great for API interaction.

1 Like

Thanks for replying. So is it an performance argument then? Eg. the blacklist is small thus faster query results?

It doesn’t ignore it. This is solved the same way as any other microservices scenario, described at the bottom of my follow-up. You don’t need cross-stack sessions, it’s solving the wrong problem.

(Irritatingly, it seems Discourse doesn’t have a practical multi-reply feature.)

Major tech companies use bearer tokens, but not as their main session mechanism, rather in an SSO-like setup. They typically also keep around session for individual stateful services.

A refresh token can be revoked. The reason you can’t revoke a JWT is because by design you dont need to talk to a server. I don’t think guardian actually supports this at this time, but other JWT implementations do.

WRT blacklist is basically a session store, the difference is 1) you barely ever have to revoke sessions. That doesn’t mean its not an important feature (its extremely important), but its definitely the exceptional case. 2) You need something like JWTs anyways for stuff like JWTs anyways for APIs.

1 Like

@joepie91 Nice to have you back on the discussion again :slight_smile:

Question: How would you handle communication native app <–> JSON API. Cookies are not of any use here. Would using a JWT with a session id would be acceptable here?

But then I’m (naively I’m sure ;)) wondering, why wouldn’t I sign and/or encrypt a session ID and put it in the authorization header myself?

[offtopic]
Open a reply (even at the bottom replying to no one), highlight text, select Quote Reply that appears, they should still get the notification and all and you can do it for as many people as you wish.
[/offtopic]

It seems that “because by design you dont need to talk to a server” is one of the core elements of what a JWT is, and then we have refresh tokens. That seems defeating the point. As this article states:

This is a long story and I’m finally getting to the point: If you want JWT with powers to revoke the token, then you abandon the federation benefit.

Making the JWT self-descrbing means no honoring party needs to contact the issuer. Just verify the signature (verify the $20 bill is real), and then grant service. If you add in revocation as a requirement, then the honoring party then needs to contact the issuer: “I have $20 bill with serial number T128-DCQ-2872JKDJ; should I honor it?”

I see the benefits here. But it also looks a little like premature optimization.
Your ideas :slight_smile: ?

It depends. Cookies work just fine outside of browsers (any reasonable HTTP library will support them), so you can just use sessions like you would for a web-based thing. It does introduce potential CSRF issues though, depending on your setup, and a bit more state to keep around.

For application-only APIs, the solution is generally to use a standard API authentication scheme. This can be something as simple as a randomly generated API key in a header (over TLS, naturally). Like for sessions, invalidation is a concern, and so you want to avoid stateless tokens unless scale demands it.

For APIs that need to serve both standalone applications and web-based applications, you have two options:

  1. Either build a separate API or authentication scheme for each case. Standalone apps authenticate like above, web-based things use sessions. Especially if the type of operations that the app does are significantly different from the type of operations the web-based interface does, this is an attractive option maintainability-wise.
  2. If you’re on a deadline: build a single API that only supports session cookie authentication, and simply use a HTTP library in your stand-alone applications that supports cookies. Of course you still need to worry about CSRF - sending along the token in a header should suffice, and is possible in both the web-based interface and the standalone applications.

Because JWT is a generally well-tested implementation for what it does (ie. signed claims). For security-related things, you should always aim to use existing and well-tested implementations, rather than implementing your own. It’s really easy to mess something up fatally in security/crypto, and there’s no point making (likely fatal) mistakes that somebody else has already made and fixed for you.

Excellent, thanks, that helps :slight_smile:

4 Likes

I dont think any of the major elixir auth libraries (which is really what we are talking about) advocate completely replacing session management with JWT claims. That is kind nuts, since you often store privileged information in a session, and JWT by design are readable by the client.

They do advocate for using JWT to authorize sessions, or to support sessionless workflows, since most elixir apps have an api, websockets, and web for the same user.

1 Like

Your solution assumes you control the services that you are consuming that is not often the case. If we have universal solution across many systems we either have to support and/or integrate with that reduces the cost makes things simpler (even if the solution is not ideal).

Even if you do not control the services, that doesn’t mean that you need to use their authentication scheme everywhere. You just use their scheme where absolutely required, model your own system around sessions, and hand out tokens for other services where necessary. It’s still the same principle.

1 Like

I’m not saying one thing is better then another, im actually arguing against the idea that there is one golden hammer. Everything has tradeoffs in authentication, you can list the negatives of anything and come to the conclusion it is bad. And be right! But there is also good.

Modern webapps tend to be written in something that lives on the browser, and communicates with the server via API. They also tend to have mobile apps, as well as public APIs. Phoenix apps tend to use websockets (channels). JWT works well for all of those cases, while session id in a cookie matching a row in a db work well for html forms. So authentication gets a lot easier for the other cases, and the tradeoff is invalidation gets more complicated. Are session cookies bad because they are really clunky to use in non browser situations? Of course not. Its all about tradeoffs and using the right tool for the job.

5 Likes

As you mention the cookie attribute httponly and emphasize that local storage is not okay, what is your opinion on the points mentioned over here and here for example?

2 Likes