
Ask HN: What's the current sentiment on JWT for stateless auth tokens? - gkop
HN threads from 2016-2018 complain that JWT gives us too much rope with which to hang ourselves, and some advocate for alternatives like PASETO instead. Today it&#x27;s not clear however that any alternatives like PASETO have crossed the threshold of adoption to warrant preference over JWT when choosing a stateless auth token solution.<p>What solution would you choose today for stateless auth tokens?
======
dang
11 months ago:
[https://news.ycombinator.com/item?id=18804875](https://news.ycombinator.com/item?id=18804875)

2018:
[https://news.ycombinator.com/item?id=18353874](https://news.ycombinator.com/item?id=18353874)

[https://news.ycombinator.com/item?id=16517412](https://news.ycombinator.com/item?id=16517412)

2017:
[https://news.ycombinator.com/item?id=14290114](https://news.ycombinator.com/item?id=14290114)

[https://news.ycombinator.com/item?id=13865459](https://news.ycombinator.com/item?id=13865459)

2016:
[https://news.ycombinator.com/item?id=11929267](https://news.ycombinator.com/item?id=11929267)

[https://news.ycombinator.com/item?id=11895440](https://news.ycombinator.com/item?id=11895440)

2015:
[https://news.ycombinator.com/item?id=9616425](https://news.ycombinator.com/item?id=9616425)

2014:
[https://news.ycombinator.com/item?id=8283006](https://news.ycombinator.com/item?id=8283006)

~~~
Zamicol
The first comment from 11 months ago is wrong.

>JWTs are useful, but there are a few things that are not immediately obvious.
>1) They are signed not encrypted.

This is not true. JWT's can be encrypted, signed, or both (nested). One might
first look to see if this misconception is the fault of a poorly written spec,
but it's literally in the second sentence of the abstract and plain as day in
the introduction. People are simply not reading it.

[https://tools.ietf.org/html/rfc7519](https://tools.ietf.org/html/rfc7519)

It drives me mad when people refer to JWT's as basically JWS's, ignoring the
rest of the JWT standard and JOSE. The fact that these misconceptions continue
to be up voted shows the broad misunderstanding of the standard.

~~~
falcolas
Or, they highlight that the spec is overly complicated. And a complicated spec
is very challenging to implement both correctly and safely.

EDIT: Case in point, all the disagreements and conflicting best practices
throughout the threads on this topic.

~~~
AmericanChopper
I think complex specs are fine. Complex and under defined spec are a
nightmare. I had to work on a WebAuthn project recently. That spec is rather
complex, but makes perfect sense after you take the time to understand it.
More recently, I had to answer a very simple question about X.509. After
spending half a day reading the RFC (and about half a dozen other dependant
specifications), I gave up and concluded that the question did not have an
answer, the best I could come up with was some general graph theory principles
relating to DIT.

~~~
speedplane
> I think complex specs are fine. Complex and under defined spec are a
> nightmare.

Perhaps, but in practice there generally seems to be a correlation between
complexity of a specification and holes in the specification (e.g., html, pdf,
etc.).

~~~
AmericanChopper
Complexity, whether necessary or not, makes it harder to maintain a spec. But
I’d argue that it’s other issues, whether they’re symptoms of complexity or
not, that make it hard to implement. Some things have to be complex, but they
don’t have to be full of problems.

------
munchbunny
In my experience, don't use JWT's for carrying application state.

In more words, if you need to carry application state and you haven't outgrown
the simple database cluster, then just use the tried and true formula of
carrying state via SQL database. Pretty much every engineer these days
understands how the architecture works, it's fast and reliable due to the
sheer maturity of the components involved, and you don't add cryptography and
maliciously crafted input attack surfaces to your auth system (see the recent
talk at BlackHat 2019 about Outlook accepting unverified auth tokens). In this
case using a predictable and mature approach is a good thing.

On the other hand, JWT's work well for (1) federated authentication, though
revocation is still hard, and (2) carrying authorization claims. The reason is
that these aren't state in the sense of application state. They're
attestations of an existing fact and you're using the signature mechanism to
let one service trust another without having to talk directly to each other or
to protect any shared secrets. You need to send signed payloads containing
user ID's and lists of claims anyway, and JWT's meet those requirements pretty
well.

~~~
Izkata
> though revocation is still hard

My understanding was that they're supposed to only last on the order of 5-10
minutes, with a fresh one created for the next set of requests instead of
reusing one JWT for days. Is revocation still an issue with the expiry so
short?

~~~
save_ferris
No, you just have to always keep in mind that if you misconfigure your
application to sign a token with no expiry, you will never be able to revoke
it. Period.

~~~
ryanisnan
No, not period. If you're using an API gateway (which you should be), you can
check against blacklisted tokens. The `jti` is your unique token identifier.
As long as you have a way of maintaining a blacklist of tokens, this is
trivial.

~~~
nothrabannosir
One of the major points for signed tokens is stateless operation. If you need
to maintain a blacklist, you lose that, and the question arises: why not just
have a whitelist of tokens/UUIDs/... to begin with?

This is why people suggest "short tokens" as a work-around, accepting a 5min
window of unrevokable tokens as trade-off.

Or, one has to justify that a blacklist implementation is significantly
cheaper than a whitelist one. But is it, really?

~~~
ryanisnan
If you have a sole identity provider, or token issuer, the blacklist can be
quite simple to maintain. Plus, with short token life spans, you probably
aren't revoking tokens very frequently.

In my experience, usage of the black list occurred with two use cases:

1) Invalidating all of a user's tokens 2) Alteration of claims that a user's
JWT should have

As far as your applications go, you still have the benefit of not having to
bother with checking the state (this is already done by the gateway).

------
altmind
JWT were aiming to be stateless, yet they cannot be stateless if you need them
to be revocable. If you keep using plain sessions you got a SPOF, but you are
immune, for a whole lot of consistency and cred management problems.

[http://cryto.net/~joepie91/blog/2016/06/19/stop-using-jwt-
fo...](http://cryto.net/~joepie91/blog/2016/06/19/stop-using-jwt-for-sessions-
part-2-why-your-solution-doesnt-work/)

~~~
jchw
To be clear though you generally set the validity to be relatively short and
refresh often, so that way you don’t have to worry too much; you can then
“revoke” a token by refusing to refresh it.

~~~
3pt14159
But then it isn't stateless, right? Because you need to know which current
tokens are unrefreshable.

To me, JWT works great for things like physical people getting access to a
physically isolated building, like a military research site that's
disconnected from the internet. Some secure other place holds the private key
and signs the JWT token then you can wave in anywhere you need to go until the
validity period is up. Then you have to go back to the secure place to get a
new key, verifying the same way you did the first time and the secure place
can broadcast its public key to the sites you want access to. It's essentially
a great mechanism where you _don 't_ have constant communication links.

But I just don't get it for servers. Also, everyone considering using a JWT
token should know about the "algorithm none" setting and ensure that their
stack isn't vulnerable to it.

~~~
jchw
Actually creating a JWT token is not stateless, but at least your architecture
is not centralized. If your auth server goes down, that’s a problem no matter
what.

A common validity period is around 1 hour, which is good enough that most
users won’t need to refresh very many times per day.

Also: you don’t necessarily need to track tokens that aren’t refreshable. A
typical architecture might have a timestamp stored per user that specifies the
earliest token creation date that’s valid for refresh. That way you can
invalidate all tokens without needing to ever store them; something you might
need to do for password reset, for example.

~~~
kelnos
> _A typical architecture might have a timestamp stored per user that
> specifies the earliest token creation date that’s valid for refresh._

There's a race condition there, though. If you have a revocation event and set
the timestamp, it's possible that an in-progress refresh might have a
timestamp just slightly after your stored timestamp. Then you have a rogue JWT
that can continue to be refreshed.

Clocks are sometimes not in sync with millisecond precision. Databases don't
replicate instantly. Distributed systems just don't work that way.

~~~
JamesSwift
You could instead store a "generation", and increment on revocation events

------
rvz
Today I would still use alternatives like PASETO [0] or Branca [1] tokens
which the latter is a fernet-like secure alternative to JWTs.

The problem with JWTs is that they are discouraged by many cryptographers due
to their "cryptographic agility" and provide a mixture of protocols which
includes weak ciphers and configurations to shoot the programmer in the foot.
Why include insecure ciphers in the first place? The mentioned alternatives
stick to a single cipher for its intended purpose.

JWTs are inefficient for performance and are bloated in their data structure
and have a performance hit when you parse the token to extract its properties
compared with the same operation in other alternatives (simple session cookie
require zero parsing and thus is faster).

And using them for sessions poses it own pitfalls [2] which you are better off
with the alternatives or plain old session cookies.

They say that JWTs are "good when used right" but with those above footguns,
that's like saying C++ is safe when used right, rather than having safe
defaults.

[0] [https://paseto.io/](https://paseto.io/)

[1] [https://branca.io/](https://branca.io/)

[2] [http://cryto.net/~joepie91/blog/2016/06/19/stop-using-jwt-
fo...](http://cryto.net/~joepie91/blog/2016/06/19/stop-using-jwt-for-sessions-
part-2-why-your-solution-doesnt-work/)

~~~
cordite
Another interesting one is Macaroons [1], although the implementations have
not had much activity since 2014.

[1]
[https://ai.google/research/pubs/pub41892](https://ai.google/research/pubs/pub41892)

~~~
justincormack
See
[https://github.com/CleverCloud/biscuit/blob/master/README.md](https://github.com/CleverCloud/biscuit/blob/master/README.md)
for a newer take on macaroons.

~~~
cordite
This is very interesting! Although it is very much a draft in progress.

It also references a new one I haven’t seen before,
[https://vanadium.github.io/concepts/security.html](https://vanadium.github.io/concepts/security.html)

------
013a
I think, philosophically, they're interesting, but in practice the
statelessness ends up not being a huge benefit.

In the few deployments I've seen, you end up observing this pattern of, first,
not enough information is placed in the JWT to eliminate stupidly common
database calls on every request (example: "the JWT contains a UserId, but we
need a RoleId that we store on the user document to determine their
authorization level. for, like, every API call.")

Ok. So, two options: you can give up, admit JWTs were a weird choice, and just
do everything possible to make those common database calls fast (which is a
_very_ solvable and scalable problem); or, you can go down the rabbit hole.
Lets put a RoleID in the JWT. But, really, a RoleID doesn't tell us anything
about the user's authz; it saves us one table join, but we need the underlying
permissions/claims/authorizations/etc. We could put those in there.

In other words, "stateless" is a misnomer. You just _moved_ the state; from a
single, consistent, and scalable database, to a "distributed database" where
every node is a JWT held by your users.

JWTs are probably fine. I just think the most claimed benefit they offer is
mostly overblown. But, in the 2% of use-cases where that benefit could be
exploited to the maximum, they're worth using, and they're also "fine" in the
98% of other use-cases.

~~~
charrondev
You could keep the role information in memory pretty easily though. A lot
setups don’t have that many roles (even big enterprise deployments I’ve seen
tend not be more than 1000, and that’s pretty extreme).

The roles per user and auth of the user on the other scales linearly with
users and is harder to keep in memory.

------
jrockway
I am fine with using JWT-alikes for bearer tokens. Good for one request or a
very time-limited duration.

Some use cases:

1) Sign In with Google gives your browser a time-limited JWT that it then
provides to the application you're trying to sign in to. The application's
server checks the validity of the token (without having to contact Google,
except for daily key refreshes) and can upgrade that to a session for your
browser using its normal session-management machinery. The idea is to transfer
a piece of information between two systems (Google and the server app) through
an untrusted system (your browser). For that, the JWT works well enough.

2) I wrote a proxy to convert one's external SSO session cookie to a JWT
internally. That ways apps can check the user without having to make any
requests to a user service, and can propagate that safely to other backends.
It was very time-limited (min(RPC deadline, global deadline) + a few seconds
of slop in both directions) and never exposed outside of an internal network.

Some anti-patterns:

You don't want to store sessions in a database, so you store the state in a
JWT that the user stores in their browser cache. This has the problem that you
can't revoke the token when the user is fired or gets hacked, which is a big
problem. (You can of course add a database that only stores revocations... but
you now have that check inside your request path, so you should have just done
it the other way around and saved the user from having to send you a giant
cookie on every request.)

~~~
Fellshard
Add 'issuing date' to the token, revoke all before a given issue date by a
single date field in your auth table. Effectively clears all tokens. Would
that work, if done up front?

~~~
jrockway
You have to check this date on every request.

I think, on some level, you can make a revocation database scale better than a
validity database. You store the revocation in some durable datastore. Then
you have some service in front of this that calculates the entire set of
revoked tokens, and pushes that to each auth gateway. Then the auth gateway
can check if a token is revoked without putting any load on a database. It has
to do this for every request, but you can scale the auth gateway horizontally
rather easily.

(When an auth gateway starts, it gets a copy of the full revocation table
again.)

On some level, you do need the ability to push revocations to your auth
server, because when you hit the kill switch on a session, you really want it
to close all their open TCP connections (HTTP/2, Websockets, SSH, etc.)

Having said that, starting simple is the best approach. I used MySQL to store
sessions at my last job. Every request went from Envoy -> ext_authz ->
authentication/authorization service -> MySQL and this whole flow added only
1-3ms of latency per request. Someday you will hit scaling limits of using
MySQL for this, but it's a long way in the future. Do the simple and reliable
thing first, then make it complicated later.

~~~
DenisM
> 1-3ms of latency per request.

Is that a big problem in practice? I always wonder about the tangible benefits
of this approach.

~~~
jrockway
Yeah, I am quite OK with these numbers. The sessions-in-a-database-table is
fast, simple, and accurate.

------
authaway
JWTs aren't just bad because they embody poor cryptographic engineering, but
they are also bad because _stateless authentication_ in itself is poor
security engineering for almost every application.

> What solution would you choose today for stateless auth tokens?

Issue token (=random 256 bit string), verify against cached database. If you
believe this to be a significant performance issue, you are very likely wrong.

~~~
ravenstine
It's kinda funny how some people think that this would be a performance
problem, but it's something that computers and programming languages are
specifically designed to do really well.

~~~
bpicolo
KV lookups with no dependent data are pretty much infinitely scalable with
modern systems.

~~~
andyroid
It’s not the lookup that is the cost but the network call.

~~~
bpicolo
That's darn cheap in modern systems, and most are doing a plethora of network
calls per request either way. .5% overhead won't matter for a long time.

------
DGAP
If you like Ptacek, read this: [https://latacora.micro.blog/2019/07/24/how-
not-to.html](https://latacora.micro.blog/2019/07/24/how-not-to.html)

But more importantly, why do you need stateless auth tokens?

~~~
spookthesunset
> why do you need stateless auth tokens?

So you aren't hitting some validation server on every HTTP request to validate
a token. Said validation server adds a very nasty point of failure & potential
for page latency.

Going mostly stateless via JWT lets you balance the desire for fast token
revocation times and load on your auth server. Even if your revocation time is
a minute, meaning your clients need to refresh their token once every sixty
seconds, that can still substantially lighten the load on your auth server.
High security stuff can always validate the token on every request but stuff
that doesn't matter as much can have a much more policy.

~~~
eropple
_> So you aren't hitting some validation server on every HTTP request to
validate a token._

This is not a real problem for the 99.9% case and you can add another nine if
you aren't defaulting to "extreme conservative"on your risk analysis. A
session token lookup in a Redis or a Postgres is _completely trivial and
cheap_.

("But my auth service is over a network link," cries the architecture
astronaut, who now has more problems and fewer solutions. Build simpler
things, you almost certainly don't need more complex and you can build better
solutions than JWT when you need them.)

~~~
spookthesunset
JWT is much simpler architecture than looking up session tokens every request.

~~~
eropple
Until you need revocation.

Which is to say _until you need a working authentication system_.

JWTs solve a nonexistent problem in the 99.9% case but are so very, very
bloggable that they've brainwormed the population but good.

~~~
spookthesunset
It’s a trade off dude. You trade off the ability to revoke a token instantly
for fewer backend calls. For most parts of your site (99.9%) that trade off is
fine. For the parts where it isn’t fine you... call the auth server every
request.

JWT doesn’t mean you give up anything....

------
lightwin
JWT helped me to achieve authentication and authorization without needing to
make a trip to database on every API call. I use to store user role code in
the token.

I kept the token expiry to an hour or two depending upon the usecase.

Added logic to client to refresh the token right before expiry of existing
token. Otherwise, on token expiry, server returns 401 and client can attempt
to refresh token or send user to login page.

If there is a need of instant revocation, then I can maintain a list of
revoked tokens for the duration of token life (1-2 hours) in cache layer.
After 1-2 hours token will be expired anyway.

~~~
ossworkerrights
Why do you need a db call for api request when you can just cache session
data?

~~~
ninjakeyboard
In memory caches have scalable concerns and require sticky load balancer.
You'd need to decentralize the cache (eg create a db for the session
information) to allow horizontal scaling of services so this approach is
generally considered old-school.

JWT has its own slew of problems, most of them are temporal (eg invalidation
of all sessions), usability (eg short expiry), or additional security vectors
(many poor JWT implementations, accidentally authenticating invalid tokens w/o
signing, careless storage of readable values)

~~~
ossworkerrights
Hmm never had an issue with in memory caching and scalability (except in the
old days of memcache). One can send a unique and hard to guess pair of
identifiers and drop the lb stickiness. anyway depends on the use case, but i
feel like given the symptoms you describe there are a few other ways of doing
it without jwt.

~~~
ninjakeyboard
For sure - they're just considerations/complexities if you need to quadruple
your service infrastructure for black friday or what not. I don't feel JWT is
often appropriate - I wrote one of the early scala implementations so have
seen the lifecycle of a security library.

------
ceejayoz
Frankly, I just went back to sessions.

Everyone thinks they're building the next Facebook, but most of us aren't
gonna stress out even a single Redis instance.

~~~
MuffinFlavored
In that same mindset, why not just do a JWT in a cookie then?

~~~
schwap
Because then you have all the headaches of JWT, without any of the benefits of
stateless auth tokens.

~~~
TobiasA
Which headaches would that be?

~~~
dewey
That you have to keep a white/blacklist if you want to revoke a token.

------
AndrewStephens
Who cares what the current thinking is - define your problem and implement the
solution that makes the most sense to you.

IMHO, the problems with JWT are overblown. Yes, people have made huge mistakes
implementing JWTs, but the fault lies with the implementation not the
standard.

Stateless authentication tokens are always going to problems with revocation.
There is always going to be a limit on how much you can cram into them. These
problems are not unique to JWTs.

JWT has the advantage of being a standard with good support across languages.
Other schemes might be slightly better at handling larger amounts of session
data. Take your pick.

~~~
ceejayoz
Some of the mistakes people commonly make - insecure ciphers, for example -
should've been addressed _in_ the standard.

------
madhadron
My sentiment: use sessions in cookies the way people have for years if what
you're doing is managing sessions.

There isn't really such a thing as stateless auth tokens. For authentication
you need revocation. For authorization, you can't stick that in a token that
you send out because permissions can change. So you end up having state that
you distribute everywhere anyway, so do it in the easiest way possible.
Scaling fast lookups of a session key is much simpler problem.

------
codegeek
One of the secrity experts here at HN always recommends against it for auth.
Go to the search box on HN and type "author:tptacek jwt". Make sure you are
searching within comments. You will see his multiple responses over the years.

I have mostly stuck to plain old server side sessions that are easy to revoke.
If anyone is using Go, I highly recommend this library :

[https://github.com/alexedwards/scs](https://github.com/alexedwards/scs)

~~~
spookthesunset
> I have mostly stuck to plain old server side sessions that are easy to
> revoke.

But you have implicitly made a tradeoff. Your front-end infrastructure now has
a very strong dependency on your auth server. Any minor hiccup in the auth
system will blow up your downstream clients. Worse, in large sites you will be
sending a ton of traffic to your auth server.

You've also introduced a source of latency to your page-load times as each
request now needs to call the auth server to validate the token. Whatever the
response time of the auth system now gets added to the front-end response
time.

Going with tokens that can be validated on the front-end system can
dramatically lighten load on your auth system and reduce your front-end
response time.

The only major trade-off is you can't kick somebody out instantly. The bad-
actor can do whatever until the token expires--a knob you control. And even
then, for shit that matters, you can always have the front-end server validate
the auth token on each request anyway.

------
StreamBright
I think there are two great options:

\- [https://paseto.io](https://paseto.io)

\- [http://macaroons.io](http://macaroons.io)

I use simple http only cookies with the following setup:

    
    
        "cookie_name=cookie_value; Domain=sub.domain.com; Path=/; Secure; HttpOnly; SameSite=Strict; Max-Age=31557600"
    

This is valid for a year when you can decide if you want to renew it.
Everything else stays on our end and we controll sessions, permissions, etc.
Javascript (in theory) cannot access these cookies.

~~~
kcolford
Are you sure you're protected from CSRF from older browsers? There's still
plenty of IE going around on old desktops in libraries and such.

~~~
IggleSniggle
Not OP, but wrt to enterprise apps, SameSite protects from CSRF even on IE
since June 2018 update. [https://caniuse.com/#feat=same-site-cookie-
attribute](https://caniuse.com/#feat=same-site-cookie-attribute)

------
MadWombat
Everyone seems to be posting the "stop using JWT" article from 2016. It has a
lot of merit, but I think there is small logic hole in it. When the second
part attempts to address the issues of token revocation, its only argument is
"what if your blacklist is down?". But that is silly. Blacklist is part of
your authentication process, if it is down you don't authenticate. Its like
asking how would you serve your API if your API server is down. You won't,
your server is down.

Otherwise, blacklisting tokens as a way of revocation process seems just fine
to me. Set reasonable expiration to the key, allow users to refresh keys, then
when you need to revoke a key, add it to blacklist together with the
expiration timestamp and expire it out of the blacklist at the same time the
key itself would expire. You can do all of this by magic by using Redis for
your blacklist storage and setting expiration on your blacklisted keys. Yes,
you would need to check your blacklist on every request, but a) blacklist is
going to be smaller than a list of every issued token (like you would with
normal sessions) b) you don't even have to store the whole token, just
calculate some hash and store that, now you only need to read a few bytes on
every request instead of reading the whole session.

The author does make a some good points though.

~~~
NewEntryHN
The argument is that the blacklist is as much a SPOF as a session server would
be. The blacklist kills the statelessness.

~~~
james_s_tayler
Does that negate all the benefits though?

If a single component of your application maintains a little state, say the
API Gateway, and all the downstream services simply get a clean JWT they can
trust with all the right claims in it?

I'm thinking this is still nicer than having every downstream service also
having to check auth claims against some datastore.

~~~
jeltz
Yes, because then the API gateaway could instead just use traditional sessions
and attach relevant data when forwarding the request downstream.

------
andyroid
JWTs and sessions are not in any way orthogonal in a system as a whole. We use
JWTs primarily for scalable _backends_ \- if a session is setup or not in the
front end is not a concern for the API backend services. In a microservice
environment there could be many of these - that’s the whole point after all.
And with JWTs being sent to these they can simply verify the integrity of the
caller without asking a central authority. Coupled with OAuth2 and OIDC as
protocols for delegation/federation and you have a system that scales
extremely well. Of course, it might not be the first concern that needs to be
addressed in a small startup but that doesn’t mean it doesn’t have a place.

------
Znafon
In my experience, the idea that JWT is stateless is wrong. When your client
log-out you will need to keep the token in a blacklist and check all requests
against it to make sure it is not reused until it expires.

Since you need to keep a list of invalid tokens, it's not easier to just use
standard token. If what's you like in JWT is the ability to store a payload
that your backend gets back, you can keep that in your store alongside the
token and read it at the same time you check the token is valid.

IMO, JWT only makes sense when an other entity is doing the authentication of
your clients.

~~~
ravenstine
> When your client log-out you will need to keep the token in a blacklist and
> check all requests against it to make sure it is not reused until it
> expires.

Sounds like a great way to DOS a server by running out its disk or memory
space. (unless there's some sort of rate limiting in place)

~~~
Znafon
How does keeping a short token in redis or other would make the application
easier to DOS than any other resource?

~~~
ravenstine
Because keeping a blacklist means keeping a list of all invalid tokens that
haven't expired. If a user creates a crapload of sessions, you have to keep a
running list of all the invalid tokens until they expire, which creates a few
problems. You now have to have some mechanism to clear out tokens that have
expired, which totally defeats one of the benefits of JWTs. And keeping a
blacklist opens up the doors to someone slamming your /session endpoint,
eventually running out your storage and/or memory because the blacklist will
just keep growing. Sure, you can build in rate limiting, which you should have
anyway. The reason I think this is still a problem is that a lot of amateurs
are going to go straight for JWT and are too inexperienced or lazy to
implement rate limiting.

But why add all this complexity? Just have a _whitelist_ , and you avoid these
problems.

------
jrobn
We need FIDO2 or some other standardized security key protocol in our devices.

I recently got an Apple Watch and having to just tap on my wrist to
authenticate is amazing.

Would love to just be able to give a website one way to contact me and have it
ping my device to authenticate with faceid, touchid, Windows hello, or an
smart watch.

Basically, a magic link on steroids.

------
hashamali
JWT bearer tokens have worked well in my experience, though I haven't used
PASETO. The main benefit is being able to use the same authentication
mechanism for mobile and web apps.

The biggest drawback is the inability to revoke tokens without giving up
statelessness. Keeping a KV blacklist isn't the end of the world, especially
if expiration times for tokens are short. But at that point, the cost/benefit
vs cookies+sessions gets blurry.

Some general JWT tips:

* Use a sufficiently long secret key if you're using HMAC based signing ([https://auth0.com/blog/brute-forcing-hs256-is-possible-the-i...](https://auth0.com/blog/brute-forcing-hs256-is-possible-the-importance-of-using-strong-keys-to-sign-jwts/)).

* Use bearer tokens to avoid CSRF attack surfaces.

* Avoid long (or non-existant) expiration times.

------
gremlinsinc
I was torn, but recently I found Inertia.js and love it. It uses server
session for auth, and makes vue a bit like turbolinks, and I'm able to use vue
without router/vuex, so for a fullstack but better at backend guy like myself
it makes more sense. Look at their pingcrm for a good intro using laravel.

------
andersonmvd
Just use stateful tokens because if you are dealing with sessions and you are
doing it right, you WILL want to revoke them at the user's will or at some
suspect activity in a session.

I've wrote how to revoke a JWT ([https://dadario.com.br/revoking-json-web-
tokens/](https://dadario.com.br/revoking-json-web-tokens/) \- caveat: requires
a db lookup), but if you are going through the trouble of revoking a JWT, just
use a stateful session instead. It's way easier.

You can use JWT to pass along user information to other components within your
architecture, that's fine :)

------
bfrog
I feel like JWT is a poor version of aead cookies like rails uses.

------
mooseburger
I'm not sure I understand the people claiming you should use server side
session tokens instead. How am I supposed to make that work with Angular? I
have to be able to send to the client the user privileges somehow.

~~~
GordonS
When logging in, the backend will generate some state (e.g. user privileges)
and store it somewhere, alongside a random session ID. It might be stored on
disk, in a database or in a KV store like redis.

The backend returns this session ID in a cookie.

You store this session ID as a client-side cookie, which gets sent on every
request to your backend.

When your backend receives a request, it will (typically using some kind of
middleware) lookup the session ID in the backing store and deserialise the
state.

Sliding expiration is typically used, so as long as you keep making requests,
you'll remain logged in.

Revoking a single session ID is very easy, since you've just deleting a single
row/key/line from your backing store.

------
lifeisstillgood
I would be grateful if anyone could point to a "how to build a PKI based
(client and server certificate based) ecosystem"

------
TomMarius
Even if your tokens are stateful, they should be signed.

------
rolltiide
Where’s that guy from that Oauth company that always pushed JWT, I think he
was with Okta

Its fine to be wrong its also hilarious

------
markandrewj
This isn't a technical answer, or me saying that there are not better options,
however with JWT's being one of the corner stones of Oauth and OIDC, it would
be hard to argue that there are not successful implementations.

------
blackflame
The biggest thing to worry about is a hash length extension attack.
[https://blog.skullsecurity.org/2012/everything-you-need-
to-k...](https://blog.skullsecurity.org/2012/everything-you-need-to-know-
about-hash-length-extension-attacks) This requires avoiding the use of a MAC
hashing algorithm such as sha1 or even sha256 because it's possible to append
data and generate a valid signature from a previous oracle. Alternatively, you
could use SHA2 to generate a 512-bit key and then truncate the key to 256 or
use an HMAC

------
KaiserPro
We use encrypted JWT tokens. I'm not sure it was the best choice, but it was
the simplest for our needs.

Basically the developer is responsible for generating & distributing auth
tokens for each device that they want to use our service.

This service is designed to fit into games and AR apps, so we didn't want to
force our own oauth flow on the end user. This way, the developer can generate
a token on behalf of the end user, and distribute it how they see fit.
(assuming one token per user, but it don;t overly matter, it's still tied to
their account.)

------
vbezhenar
I'm doing everything by hand. Like byte array with timestamp (4 bytes), IP-
address (4 or 16 bytes), user id (4 bytes) and so on, then this array is
signed and converted to string using base64. I looked into JWT and it was
absurdly long. I don't like to waste bytes.

~~~
peburrows
“I don’t like to waste bytes” isn’t exactly a great reason to write off a
widely accepted and deployed spec for transmitting data in a trustworthy
manner and instead write your own implementation, which most likely hasn’t
considered all the attack vectors the JWT (and broader JOSE) spec has
considered and accounted for.

I get the motivation — and I hesitate a little bit to say this — but it’s
2019, and a few “wasted” bytes on your auth token are less than
inconsequential in a world where your front-end codebase mostly like “wastes”
thousands (if not millions) of bytes.

When it comes to securely transmitting data, it most often pays to lean on the
work and research of others.

~~~
vbezhenar
I prefer to keep it simple. JWT does not look like a simple thing.

------
Zamicol
JOSE and COSE fill a void not filled by anything else on the market.

Sure, Branca may compare to just a JWT, but it doesn't compare to a JWS let
alone JOSE.

If all you need is stateless auth tokens, use Branca or a good JWT library.

IMHO, the problem is the libraries, not the JOSE(JWS/JWE/JWK/JWT/JWA)
standard. IMHO, after ~4 years there's still no good Javascript or Go library
for JOSE, but potentially a few good JWT focused libraries.

[https://blog.zamicol.com/2018/03/its-jose-not-jwt-
pedantic-c...](https://blog.zamicol.com/2018/03/its-jose-not-jwt-pedantic-
complaint.html)

