[HN Gopher] JWT vs. Opaque Tokens
___________________________________________________________________
JWT vs. Opaque Tokens
Author : fabig
Score : 118 points
Date : 2022-09-29 09:18 UTC (13 hours ago)
(HTM) web link (zitadel.com)
(TXT) w3m dump (zitadel.com)
| rubyist5eva wrote:
| Don't roll your own JWT implementations for client side
| applications, for the love of dog don't.
|
| Story time.
|
| Our company recently switched to JWTs for our SPAs from regular
| OAuth2. I told them up front - we need a way to invalidate a
| token if an account is compromised. The lead on this initiative
| said we can blacklist any token. I told him that's not practical
| because you would need to know the exact token to be able to
| blacklist and because we don't store them in the database and
| don't log them have any real way to figure out which token is
| being used by an attacker and which are not that it's basically
| useless.
|
| I suggested a simple fix: cypher the private key we sign the JWT
| with the hashed password of the user account we're generating the
| token for. If an account is compromised, we can reset the
| password and invalidate all tokens for that one user.
|
| I was ignored and lo-and-behold within a month CTO and tech lead
| are trying to track down JWTs for a hacked account. I told them
| we can update the app to cypher the key, it'll invalidate all
| tokens and people will have to log in again but at least they'll
| be secured. Nothing has been changed to this day, despite banging
| this drum for literally over a year. We've recently extracted our
| authentication into a micro-service (for no reason really, i'm
| still mad about this too) and still nothing has been done about
| this issue when it would have been the perfect time to fix this.
|
| I love my job but "priorities" and "business cases" as an excuse
| for this kind of incompetence is rage inducing.
|
| The point I'm trying to make is. You are most likely using some
| kind of web framework that can just plug in an authentication
| implementation, just use that. NIH is very real and it is more
| than a waste of time, it can be dangerous.
| mooreds wrote:
| Full disclosure, I work for FusionAuth, a competitor of Zitadel
| in the auth server market. Our software issues a lot of JWTs.
|
| I agree with the premise of the article, which is that JWTs
| aren't the right answer for every solution. Ine pattern we've
| often seen to mitigate some of the issues of JWTs is to store
| them serverside, in a session. Now you get all the benefits of
| session management (revokability, single view of usage) but can
| still present a JWT to other APIs if needed.
|
| I'd never put sensitive data in a signed JWT. In fact, at
| FusionAuth, even JWT claims like the user id is a UUID, just so
| you don't inadvertently leak information like "how many users are
| there" via an integer user id.
|
| The main reason why JWTs work so well is their statelessness. By
| that I mean the fact that you can verify their integrity without
| "calling home" (especially if you've set up asymmetric keys
| correctly). In this case, you don't have the same availability
| and scaling requirements for your server that issues JWTs that
| you would for a server that was responding to opaque token
| requests.
|
| It's from last year, but I compare and contrast these two
| approaches in this video I presented at a meetup, starting a few
| minutes in: https://youtu.be/rArCF7nUcvY?t=451
|
| JWTs are part of building an app that scales. But like any other
| scaling choice, it has consequences. Just as you wouldn't shard a
| database before you need to, you shouldn't build an app that uses
| JWTs to scale unless you need to. Though switching between
| sessions and JWTs is going to be an easier transition than
| sharding vs unsharding a database. Data has inertia and all that.
|
| I don't believe there is much functional difference between
| sessions and opaque tokens. Both have to be stored somewhere,
| both require a central source of truth, both require that store
| of truth to be constantly available. There are differences in how
| they are managed/acquired, but from an architectural perspective
| they are similar.
| zhte415 wrote:
| UUIDs leak information, by definition. For that reason, I'm not
| a fan. It's just leaking on the other side.
|
| I'll explain: A UUID should be pretty unique in the universe.
| Wherever it crops up, as there should always be an assumption
| of the possibility of leaking data and associated data at the
| same time, whomever the UUID belongs to has had their
| information leaked. That could be associated meta data in a
| request like IP address, to a print out that has a user's UUID
| in the header. In all cases it ties data to an individual.
|
| Better is to just use a high integer that doesn't simply
| increment, but changes by an amount. But low enough to blur
| into noise. Heck, this can be rotated.
|
| I stand to be convinced otherwise, but via the reasoning above
| I believe UUIDs are not desirable for user privacy.
| adamckay wrote:
| I don't understand what you mean here.
|
| You're saying that because UUIDs can be assumed to be unique
| in the universe, when it's leaked alongside other data it can
| then be correlated with other data leaks to tie data to an
| individual? How does a user ID being `8646846` make it any
| safer from leaks or correlation than
| `123e4567-e89b-12d3-a456-426614174000`?
| giancarlostoro wrote:
| > I agree with the premise of the article, which is that JWTs
| aren't the right answer for every solution. Ine pattern we've
| often seen to mitigate some of the issues of JWTs is to store
| them serverside, in a session. Now you get all the benefits of
| session management (revokability, single view of usage) but can
| still present a JWT to other APIs if needed.
|
| This seems weird to me. The whole point of the JWT is that you
| know with confidence that the client has the data you need and
| cannot change it. I mean, if it works for them cool, but at
| that point you might as well just have a session with an ID and
| a table with all the relevant session information in one swoop.
| mooreds wrote:
| > The whole point of the JWT is that you know with confidence
| that the client has the data you need and cannot change it
|
| I would change that to "The whole point of the JWT is that
| you know with confidence that the client can provide tamper
| proof data, often identity, to other servers and APIs."
|
| Yes, the OIDC id token is for the client to consume, but if
| it is an access token, it is for the resource servers (to
| slip into a bit of OAuth jargon). Put whatever you want in
| the id token, knowing the client will have full access to it.
| If it is a javascript or native client, you don't know where
| that will go, but having it shouldn't grant access to
| anything privileged.
| jwtbrothrow wrote:
| > Regarding that last, there's a lot of brainpower put
| towards edge cases and security in the OAuth working group
|
| This is obviously why people should adopt OIDC.
|
| I don't really get the hate for OIDC. Nothing says "Junior
| Developer" like posting on Hacker News how shitty this
| widely adopted, durable technology is, especially by
| calling it "JWT."
|
| This token expiration boogeyman is especially dumb. If
| there's a security misconfiguration so disastrous that the
| user can exploit it in less than 5 minutes (a typical
| access token lifetime), you're only going to be booting
| them out of the system after they've done the damage
| anyway.
| wokwokwok wrote:
| ...but how do you get the access token every 5 minutes?
|
| Surely not, because, it's be _obviously stupid_ using a
| refresh token right?
|
| Not a _long lived_ refresh token.
|
| A refresh token... that you might, say, need to revoke at
| some point?
|
| Somehow.
|
| Definitely a boogeyman. ...because people don't
| understand how it works.
| jwtbrothrow wrote:
| > Somehow.
|
| This word, revoke. It appears in OIDC exactly twice. You
| can look it up yourself. In order to get a new access
| token, you have to hit an authorization server URL, not
| an application server URL, with your refresh token. If it
| was revoked, you'll know then. The authorization server
| will simply not give you a new access token, and while
| you have a string of bits still called a refresh token,
| it is as useless as an old password.
|
| I get that your snark is stylized, and this is Hacker
| News, and uniformly, the junior developers in my life
| that I engage with deploy snark, that's all fine. Really
| the emphasis is on how much the OIDC people have thought
| about all these things, and while I agree it is a lot to
| learn, it is in principle the only winning standard for
| authentication and authorization nowadays, it is what
| everyone uses, so you might as well learn it.
| P5fRxh5kUvp2th wrote:
| I suspect cookie sessions is still more widely used than
| anything approaching OAuth and it's ilk. Hell, even JWT's
| often get associated with cookie sessions, which helps
| mitigate the revocation problem.
| wokwokwok wrote:
| > ...pattern we've often seen to mitigate some of the issues of
| JWTs is to store them serverside, in a session.
|
| ...
|
| > The main reason why JWTs work so well is their statelessness.
|
| You realise this is obviously a very weak argument for using
| them? Stateless in a way that is apparently not useful for most
| people. Great.
|
| I've never seen a serious JWT implementation that didn't use a
| database to manage lockout and other state related things that
| inevitably turn up as product requirements.
|
| Once you do, you now have a stupid pointlessly complicated
| session implementation that potentially leaks sensitive
| information.
|
| That's the whole point of the article.
|
| If you you need jwt for "other services" issue jwts for them
| when they become a requirement.
| mooreds wrote:
| > You realise this is obviously a very weak argument for
| using them? Stateless in a way that is apparently not useful
| for most people. Great.
|
| Well, it depends. With JWTs in a session, you get a time
| bound set of credentials that can be verified server side,
| with rotation built in and a lot of docs, libraries and
| experts thinking about things. (Regarding that last, there's
| a lot of brainpower put towards edge cases and security in
| the OAuth working group!)
|
| Other sets of users use JWTs in their pure stateless form,
| often with a short expiration time in a secure HTTPOnly
| cookie, transparently refreshing often. This offers easy
| horizontal scaling, as long as you only want to talk to
| servers in a single domain (you can always proxy calls other
| domains if needed).
|
| I don't think that JWTs are a magic bullet, but they
| definitely have some strengths.
| kyrra wrote:
| It's funny to read about all the web app usage of JWT, and here I
| am dealing with it server side.
|
| For those unaware, JWT has the 2 ways of encoding it: JWS and
| JWE. Because of these properties, you can use it how people would
| use it for application level messaging. If you are already on a
| secure channel, you can sign or encrypt the message so
| application level checks can happen.
|
| This makes it act like a replacement of PGP for you paranoid
| people out there.
|
| (Btw, I recommend against this, and think people should use PGP
| or Tink, as it's easy to footgun yourself with JWS.)
| tialaramex wrote:
| An ex-colleague _loved_ JWTs, using them in systems where I 'd
| argued strongly they were inappropriate, and since I wasn't able
| to cut holes in the resulting system in a few hours spare time
| spent tinkering and they really wanted to do it, it went ahead. I
| guess I at least know they didn't fuck up in any of the obvious
| ways because I checked those.
|
| Recommended thought experiment: Every programmer who makes or
| consumes the tokens in your system needs to attend a meeting
| about the tokens. Picture that meeting in your head. Was it a
| huge endeavour, involving several hotels and many months of
| planning? Then you probably need JWTs. If the meeting could
| happen in a coffee break then JWTs are wildly inappropriate.
| Xeoncross wrote:
| Session tokens need to be stored on the server (redis, db, etc..)
| so you can change them, see all devices logged in, and other
| requests product will have.
|
| They should be unguessable and unrelated to anything. Read 20
| bytes from /dev/urandom (or whatever stdlib your language
| provides), create an entry in your store for token->user_id, then
| put it in a httpOnly + secure cookie (so Javascript can't access
| it), and send it to the client.
| aaronmu wrote:
| What's the difference between an opaque token and a cookie that
| has a single session identifier in it? 'y know - the way we did
| it in the 90's.
| mooreds wrote:
| For a normal web app, not too much.
|
| As sibling comments point out, an opaque token can be stored
| elsewhere (though, to be fair, the session identifier which is
| in that cookie can be placed elsewhere too).
|
| Cookies are limited in where they can be sent
| (https://developer.mozilla.org/en-
| US/docs/Web/Security/Same-o...).
| ffo wrote:
| The cookies is mainly used to identity the user (e.g. his
| session and prior authentication), while the tokens are used to
| forward something to proof that the an application wants to
| access one or multiple apis.
| tgv wrote:
| So if you need the client to pass on sensitive
| (authentication/authorization) information to another party
| without that party having access to the original provider of
| that data (except its public key, I suppose). Then JWT is a
| usable format, with a lot of support.
| ffo wrote:
| Well, yes ;-)
| cnorthwood wrote:
| There isn't one - the session identifier is an example of an
| opaque token
| senko wrote:
| Cookie is a mechanism to store and send tokens to the server,
| which is orthogonal to what the token is.
|
| You could store JWT in a cookie, or use opaque token in a HTTP
| header, for example.
|
| That said, the session cookies we loved back in the day were
| usually opaque tokens, yeah.
| pmontra wrote:
| I investigated this issue with a customer recently with a focus
| on revocation. We concluded that if we have to hit the database
| to check if a JWT token is still valid we can use a session
| cookie (or equivalent) and hit the database to get the user, the
| associated capabilities, etc.
| Awerion wrote:
| Than you don't need it if you don't see the advantage.
|
| You normally do lots of API requests while you are logged in.
| To services and to download an image for example.
|
| You make sure the current jwt is valid for a few minutes and
| hit only the database with the refresh token for example.
|
| Only in worst case you really need to block a token and it
| might be much easier to sync those few tokens in your system
| into some local cache and let them expire automatically
| (because you know when they expire as it is contained in the
| token).
|
| But yes if all of this sounds complicated, use sessions and a
| distributed redis for your session or just the database.
| mooreds wrote:
| Exactly this! If you are hitting an authorization server via
| the introspect endpoint, why not simplify things even further
| and just hit dynamodb or redis or database and check the value
| of a cookie?
|
| A few reasons why you might want the opaque token come to mind:
|
| * You want the OAuth ecosystem (the libraries, the scopes, the
| user permissioning)
|
| * You are being forced to use an opaque token because your user
| authenticates somewhere else, and they only provide you an
| opaque token.
| ffo wrote:
| Or you want to share sessions across multiple domains.
|
| This is where a identity service also can help ;-)
| ffo wrote:
| Well you want to check your session cookies as well against
| something ;-)
|
| Surely you could trust a signature and lifetime but that makes
| the cookie no different than a JWT (only storage wise the
| differ in that case).
|
| Generally speaking it is recommended to use opaque tokens and
| rely on the userinfo / introspect endpoint call to make for the
| session management.
|
| Only in specific cases where latency and/or scaling might
| become an issue you should opt for JWT. At least this is my
| opinion.
| ketzu wrote:
| > Well you want to check your session cookies as well against
| something ;-)
|
| I think that is the point of the op: If you have to check a
| db to realize revocation, then you can use session cookies
| because they also need to hit the db. (Because you don't get
| rid of the db hit for using jwt).
| marcosdumay wrote:
| Well, that certainly depends. One accesses the db on every
| request, the other accesses the db on every correct request
| (and the db is smaller).
|
| As a rule, there is no difference. But if you are one of
| the exceptions, those can have differences of orders of
| magnitude.
| franky47 wrote:
| Another drawback for JWTs (when used fully statelessly) is the
| inability to list active sessions on other devices (which may
| lead to revocation).
|
| That being said, always going to the database for connecting an
| opaque session token to an identity can quickly become slow,
| and if those features listed above are not desirable, having a
| blocklist of revoked JWT IDs in an in-memory cache (like Redis)
| can bring back some performance benefits.
| Awerion wrote:
| You still can add a post response filter to update some
| statistics table after you send out the response to the
| customer to keep latency low and pressure on db low too.
|
| Still very few companies need something like this.
| Aeolun wrote:
| > always going to the database for connecting an opaque
| session token to an identity can quickly become slow
|
| PHP does this every single request. I've never had enough
| users that this became a significant issue (and you probably
| don't either)
| mooreds wrote:
| > having a blocklist of revoked JWT IDs in an in-memory cache
| (like Redis) can bring back some performance benefits.
|
| Doing this obviates some of the benefits of JWT's
| statelessness, but for situations where revocation is really
| important and you can't have that few seconds of JWT validity
| after a user logs out, this totally works.
|
| My employer has an article about this topic here:
| https://fusionauth.io/learn/expert-advice/tokens/revoking-
| jw...
| nodefortytwo wrote:
| Not all requests are created equally, maybe you don't check
| jwt revocation on some high throughput read endpoints but on
| updates or reading of sensitive data you do check that list.
|
| with JWTs you have the flexibility with the opaque you don't.
|
| JWTs also allow you to do client-side logic on things like
| entitlements but then verify against database when the user
| tries to view something
| philliphaydon wrote:
| > always going to the database for connecting an opaque
| session token to an identity can quickly become slow
|
| If select by id or token is slow for you then I worry about
| the rest of the application quality. Probably much slower
| elsewhere that the identity lookup is the least of your
| concern.
| Octoth0rpe wrote:
| Lots of messy terminology use here. Example:
|
| > In addition, since [opaque] tokens are stored on the server,
| they can carry more data than JWTs, and you can easily revoke
| them if necessary.
|
| Opaque tokens don't carry _anything_. THey're just an identifier
| used to query a database inside your application. The article
| repeatedly implies there is meaningful content inside an opaque
| token.
|
| More messiness:
|
| > Opaque tokens cannot be read by people that hold them since
| they are undecodable strings. A client cannot read the contents
| of the token
|
| Sure they can be read. It's just that the totality of the content
| _is_ the token itself.
| dfee wrote:
| > Opaque tokens don't carry _anything_.
|
| Opaque tokens are opaque to consumers. There's no limit on what
| can be in there, as long as they're opaque. So yeah, you don't
| need that token to just be a PK. It can be a real payload
| (generally encoded).
| Octoth0rpe wrote:
| > Opaque tokens are opaque to consumers.
|
| > It can be a real payload (generally encoded).
|
| Based on your definitions, a JWT is therefore a specific kind
| of opaque token. I don't think it is personally.
|
| I think we really should be talking about tokens as falling
| into two categories, of which JWT is an implementation of the
| first:
|
| 1) stateless - the token contains meaningful content that can
| be verified by a consumer. JWT is such an implementation with
| a standardized way of verifying the content without
| additional database queries (excepting revocation here)
|
| 2) pure identifiers - the token is merely an identifier, and
| all consumers must reach out to some other service (eg redis)
| to retrieve the details/capabilities that the session should
| have.
|
| Edit: alternative proposed terms: content-full, content-less
| jimbobimbo wrote:
| Opaque token is called opaque for a reason - only the
| issuer knows what's in it, whether it has content or not,
| is it an identifier or an encrypted payload, what to do to
| make use of it.
|
| Content-full and content-less break that abstraction.
| marcosdumay wrote:
| This is a hard area to work on, everybody that says
| something apply their own meanings to the words, you can
| never know what anybody else says.
|
| Anyway, I have always understood it as the token being
| opaque for the verifier too, that only ever tested it for
| equality. The token that is opaque only for the holder is
| normally called "encrypted". It may not be opaque to the
| issuer, but that doesn't change much.
|
| But anyway, depending on what you read, you will get
| different meanings.
| P5fRxh5kUvp2th wrote:
| > Anyway, I have always understood it as the token being
| opaque for the verifier too
|
| Which falls flat on its face the second you realize the
| "verifier" can pull out information based upon that
| opaque token.
|
| It just means the intent is not for the person receiving
| it to do anything except reflect it back on subsequent
| requests. That's it. Typically it's done by handing
| something that is meaningless without context, said
| context not being available to the consumer being issued
| the token. But there is absolutely nothing that says you
| can't hand them a JWT meant to be used as an opaque
| token. If you're really worried about it, encrypt that
| bad boy before giving it to them.
| senko wrote:
| My biggest problem with JWT is that it's way overhyped, leading
| less experienced devs to believe JWT is the only way to implement
| auth, unless you use a 3rd party provider.
|
| JWT is a solution to a problem 95% of us don't have:
| https://apibakery.com/blog/tech/no-jwt/
| hbrn wrote:
| To add to that, even if you have microservices everywhere on
| the backend, JWT is still rarely a good choice. Those services
| are typically exposed to customers via some sort of API
| Gateway/BFF. So if your clients don't speak to microservices
| directly, authentication between those services could easily be
| done via plain old HTTP Basic Auth.
|
| Stripe has been doing that for their public API since forever,
| and that's one of the big reasons why it is so easy to work
| with them.
| tobyjsullivan wrote:
| It's worth noting this coconut pattern (hard auth facade,
| soft interior), while popular and helpful for dev efficiency,
| is a weak security practice. Using simple pre-shared keys
| between internal services excludes any meaningful access
| controls over user data. Whether that's important depends on
| the domain.
|
| For stripe, though, I'm surprised they wouldn't want to
| ensure internal data requests are being made on behalf of
| customers who should actually have access to the data.
|
| Also, for bigger companies (although, why not smaller ones?),
| you hit a point where you can't keep blindly trusting every
| service. Better to have internal security controls.
|
| As for when these tradeoffs are appropriate, hard to say. But
| a good rule of thumb could be when the product is big enough
| to need an SOA.
| hbrn wrote:
| > As for when these tradeoffs are appropriate, hard to say
|
| And that is my biggest problem. If you don't know whether
| you need something, you don't need it.
|
| Or you just don't have enough expertise to understand why
| you need it, but that means you will implement it the wrong
| way anyway.
| marcosdumay wrote:
| > If you don't know whether you need something, you don't
| need it.
|
| That's a bad approach for security.
|
| Starting with the solution is the wrong way to do it, but
| you certainly need to actively look if you have problems.
| hbrn wrote:
| Let's say you're a startup that's hiring it's 5th
| engineer.
|
| Should you do criminal background checks? Install spyware
| on laptops? Forbid hiring from other countries? Restrict
| developer access to production env? Invest all your
| development time into security features until you run out
| of those?
|
| If you actively look for problems, you will justify all
| of those.
|
| Security is not about knowing which problems exist and
| fixing them all. It's about knowing which risks are
| acceptable at your current stage. If you don't know which
| risks are acceptable, applying random security practices
| is worse than no security at all. At least when there's
| no security you are aware of it.
|
| If you can't come up with an attack vector where HTTP
| Basic Auth causes significant problems, you don't need
| JWT to secure communication. And even if you can come up
| with an attack vector, is it really easiest one to
| execute?
|
| Speaking of attack vectors, how many of the folks that
| use JWT for inter-service communication actually rotate
| encryption keys when anyone who has access to them leaves
| the company? My bet is very few.
| P5fRxh5kUvp2th wrote:
| Why do security people think security trumps everything?
|
| It's a serious question. As time goes on I more and more
| land on the side of Linus Torvalds wrt to security.
|
| It kills me the amount of stupid shit I've seen done in
| the name of security.
|
| If security people were to come up with driving
| standards, no one would be allowed to turn left because
| it's more dangerous then turning right.
| schwap wrote:
| Ironically, authorization downstream of an API gateway is
| an application that JWTs are a good candidate for.
| dwaite wrote:
| You have different approaches of security depending on your
| desire for risk mitigation. Examples (with somewhat made-up
| names);
|
| 1. An ingress moat - your ingress makes decisions on whether
| someone should be allowed in, after which internally anything
| goes.
|
| 2. Two-stage auth - building on top of the above, internal
| messages need authentication/authorization for communication
| channels to be established. This might be basic, x509,
| kerberos, or federation-based protocols. Microservices
| environments might use SPIFFE for this.
|
| 3. Messenger auth - in addition to the above, requests need
| to show evidence of direct/indirect interaction with the
| parties involved. For example, an access JWT may be sent
| around since it would provide indication of a user and
| tenant.
|
| 4. Intermediary-authorization - a variation of the above,
| evidence is required on each communication channel 'hop' that
| the initiator(s) are authorized to make the request against a
| service. This may involve more centralized services to create
| many opaque/integrity-protected authorization decisions from
| an external systems view.
|
| 5. Transactional auth - another variation of 3, evidence is
| required specifically that a given action is authorized,
| including parties and potentially parameters. This might be
| sent directly from the original initiating party, or may be
| created for internal systems close to the ingress point.
|
| Note that for a service with a public API, all of these can
| hypothetically look identical. However, once you get to a
| certain amount of internal authorization checks, you
| naturally start to try to represent those with integrity-
| protected stateless tokens to avoid needing a massive
| centralized system with low latency consistency and high
| uptime needs. OAuth access and refresh tokens were designed
| to help there.
| feoren wrote:
| > This brings us back to how we implement authentication in
| Node projects you generate with API Bakery. If you've read all
| of the above, no surprise here - we use bearer tokens.
|
| WTF? They just spent the whole article talking about how bearer
| tokens were stupid (everything they said about JWT applies to
| all bearer tokens). And then they say "instead of this thing we
| said was stupid, we use the exact same thing but named
| differently". WTF?
| jsmith45 wrote:
| Nonsense. Issues like inability to revoke JWTs don't apply to
| bearer tokens where the API server needs to query the token
| issuer to found out who the user is (which can then implment
| revoking the token simply by dropping the record for the
| token from the DB, all further calls will fail the lookup!)
|
| Remember they stated:
|
| > Major advantage of JWT compared to bearer tokens [...] is
| that they don't require looking up the token.
|
| Other problems with JWTs vs opaque bearer tokens they listed
| include:
|
| - increased attack surface due to complexity of JSON
| parsing/validation
|
| - misconfiguring JWT libraries to allow no signature
|
| - leaking data to users because you thought JWTs were
| encrypted
|
| Now you are right that some of the complexities involved with
| JWTs like refresh token can apply with arbitrary bearer
| tokens, especially if you want to limit the lifespan of the
| access token, but those are implementation choices.
| Technically you can just have a single long lived bearer
| token instead of a long lived refresh token, and a short
| lived access token.
| yencabulator wrote:
| Worse than that, even when JWT is a solution to a problem you
| have, it's a bad solution.
|
| https://web.archive.org/web/20180324054020/https://storify.c...
|
| https://twitter.com/FiloSottile/status/1300946068411121665
|
| https://insomniasec.com/blog/auth0-jwt-validation-bypass
|
| https://paragonie.com/blog/2017/03/jwt-json-web-tokens-is-ba...
| goodpoint wrote:
| Like most web stuff and the blockchain, JWT sound fancy but it
| is a very trivial thing.
| [deleted]
| Aeolun wrote:
| I feel people come down too hard on JWT. If you do just two
| things there's basically no difference between sessions and
| tokens. Don't use it for storing sensitive data
| Expire often
| dkarl wrote:
| Where I've seen this turn into an argument is when people
| disagree about whether authorization info is "sensitive." Is it
| okay to send a list of roles or other authorization info in an
| unencrypted JWT? Security-wise this seems like it adds risk,
| but people often argue that it's a good trade-off in order to
| avoid a round-trip to an auth server (probably with a caching
| layer in front) for every call.
| gboone wrote:
| I figure unencrypted should be useful to the frontend, but
| use encrypted for authentication or authorization.
|
| Unencrypted: maybe a user preference, or first name, or
| something that adds value but does not overlap with auth.
| Like if a frontend could serve the same functionality across
| three departments but the styling is different, the token's
| unencrypted claims could determine which style set to use.
|
| Encrypted: user uuid, roles, maybe other known settings,
| things the backend can handle. Someone stealing a token will
| just try it anyway whether they can see claim or not, but
| because it's encrypted it will get decrypted so it's also a
| different logic flow than unencrypted and could trigger a
| process i.e. did it come from an accepted ip address or
| range? Does the ip match the previous? Does the ip match the
| other known ip for a websocket? So also in this sense we
| wouldn't want anyone to know what else we might check.
| [deleted]
| dkarl wrote:
| The front end almost always needs to know what a user is
| authorized to do, because it is reflected in the UI. Which
| edit/delete buttons are visible and active? Is there a link
| to the admin page? Is there a link to a supervisor
| dashboard? Most apps send that information to the front end
| in a way that maps 1-to-1 to how they model authorization
| on the back end, often using exactly the same language, in
| which case you don't gain much by encrypting it in the JWT.
| But if you are taking measures not to leak your
| authorization model in the front end, then it makes sense
| not to expose it in an unencrypted JWT.
| ehutch79 wrote:
| And then most people hit the db anyways, since they use the
| jwt as a session cookie anyways.
| jrochkind1 wrote:
| If there is no difference, then what is the advantage of JWT?
| hobofan wrote:
| That they've been around for long enough for proper
| implementations in all major languages to exist, their
| pitfalls being documented and a lot of devs have some
| familiarity with it.
|
| With that they are a better choice than most
| homebrew/framework-specific solutions.
|
| There are some other established (/"standardized") solutions,
| which might fit your use-case better though, but most of them
| lag behind JWT in implementations/dev familiarity.
| goodpoint wrote:
| Spot on. Even better if they used a better serialization
| protocol than stupid JSON.
| Sohcahtoa82 wrote:
| What's wrong with JSON?
| fireflash38 wrote:
| JSON really is the worst serialization, except for all
| the others.
| mvf4z7 wrote:
| My biggest problem with using JWTs for authenticating a SPA is
| where do you store them so that a user does not have to login
| every time they visit your application? Every SPA tutorial I have
| seen says to throw them in the browser's localStorage. Well now
| you just opened yourself up to XSS vulnerabilities. Any code
| running on your page can access localStorage and make requests to
| ship the tokens anywhere they would like.
|
| I prefer session cookies for web applications. Sure you have to
| worry about CSRF, but that is easily solved with CSRF tokens.
| Furthermore, is CSRF even really an issue when you are using a
| JSON API and have CORS properly configured.
| debacle wrote:
| Adding a CSRF middleware to your app is something that you need
| to do once, ever.
| mooreds wrote:
| > where do you store them so that a user does not have to login
| every time they visit your application?
|
| We recommend HTTPOnly, secure cookies for storage with an SPA.
| Diagrams here: https://fusionauth.io/learn/expert-
| advice/authentication/spa...
|
| If you need to access APIs from elsewhere, run an API proxy
| server side that can validate the JWT and then forward on the
| requests.
| xvinci wrote:
| Unless I misread I consider this statement not true or
| contradictory: it has all the information the
| server needs except the signing keys, so the server doesn't need
| to store this information server-side. This means that users can
| get a token from your authorization server and use it in another
| without those servers needing to consult a central service.
|
| In order to not have to care about rotating keys, a typical
| Resource Server would fetch the public key from the SSO server.
| Not necessarily in real-time, but at least on a frequent periodic
| basis. It even says "except the signing key", which is half true,
| since the public key needs to be well.. public and available.
|
| Now this may be nitpicking but it comes with an important
| implication: Your jwt validating party needs to have network
| access to the SSO service (unless you want to provide keys for
| token verification yourself, which I do not recommend), which is
| not always a given, especially in hybrid setups (On-Prem +
| Cloud).
| mooreds wrote:
| > In order to not have to care about rotating keys, a typical
| Resource Server would fetch the public key from the
| [authorization] server.
|
| Another option would to be prepackage N public keys with the
| resource server during deployment. This means there is
| absolutely no network access required, just filesystem access
| to the public keys.
|
| You want more than 1 so that you can rotate the signing keys if
| you need to, without redeploying said service.
|
| What is the correct value for N? I dunno, depends, but it's not
| hard to generate 100 public/private keypairs and then bundle up
| the 100 public keys into a deployment artifact.
|
| Is this as common as using JWKS? No, not in my experience. Is
| it possible? Absolutely.
| gboone wrote:
| Maybe it's about "can get" vs "should be allowed to get"? They
| can carry whatever so it's technically true, right?
| xvinci wrote:
| It was more about the and use it in another
| without those servers needing to consult a central service.
|
| part. Unless you take care of key distribution yourself (like
| another poster wrote), this consultation of a central service
| has to take place to exchange key information (but not for
| additional authentication or authorization information).
| ffo wrote:
| Well true, public keys would be better wording wise.
|
| One thing I just wanted to append to this here:
|
| > Not necessarily in real-time, but at least on a frequent
| periodic basis.
|
| Periodically fetching the keys is not really a best practice on
| its own. The consumer (RP) must be able to handle newly
| published keys at runtime. Since a JWT includes a KID it is
| recommended to lookup a local cache pre-filled from a scheduler
| while fetching new KIDs on demand.
| magicalhippo wrote:
| Indeed. We validate Azure AD tokens for our native application.
| Not all of our on-prem installations have unrestricted internet
| access. So we have a task that periodically checks and
| downloads Azure's signing keys[1], so we can distribute them to
| our customers.
|
| [1]: https://login.microsoftonline.com/common/v2.0/.well-
| known/op... (jwks_uri element)
| brokenwren wrote:
| As this applies to access tokens, if your application doesn't
| need a JWT, it shouldn't care whether the authorization server
| returns a JWT or an opaque token. On the flip side, if your app
| needs a JWT, then the authorization server must return one.
|
| Revocation is either offered by the authorization server or
| managed by the app. If the authorization server manages it, then
| JWTs vs. opaque tokens are not a concern because the
| authorization server issues and revokes its own tokens. If the
| app manages it, then generally it does so based on the token
| type. If the app revokes based on opaque tokens, it can handle
| any type of token, including JWTs. If it revokes based on JWTs,
| then JWTs are required.
|
| Beyond that, the only differences between the two token types are
| size and data leaks. Size rarely matters (hehe), so just ignore
| that. Data leaks are only an issue if you app is leaking JWTs,
| which is usually considered a critical vulnerability. Remember
| that access tokens are the main units of identity and if I steal
| an access token, I effectively become that user/client.
| b0afc375b5 wrote:
| Whenever I see jwt I always think of tptacek's arguments
|
| https://hn.algolia.com/?dateRange=all&page=0&prefix=false&qu...
| 42e6e8c8-f7b8-4 wrote:
| Thanks for the link. tpacek makes useful arguements.
|
| I've come to like JWT's for mundane, tiny projects because I
| can use https://www.keycloak.org/ and get a lot of boilerplate
| account stuff for free -- password reset, registration page,
| eula gate, et c.
| ffo wrote:
| Well you can have the turnkey of keycloak and JWT optional
| with ZITADEL ;-)
| aaaa_vougoza wrote:
| I came here to see what in the hell James Webb Telescope is not
| dealing with some opaque stuff on the universe and I got decepted
| orange_joe wrote:
| I don't have experience with JWTs, but if you can encode data,
| why couldn't you encode a "freshness" time stamp and just
| invalidate the token after an elapsed time. Does this compromise
| the encryption?
| sibit wrote:
| You can. Usually it's an "exp" value that you set when the
| token is issued. The time can be whatever you want, I might do
| something like now + 15 minutes. Then when verifying the token
| you can check if exp <= now kick out a 401 response.
| mattacular wrote:
| You can do that. A related problem: there is no obvious way to
| revoke early (ie. before the timestamp that was encoded when
| the token was issued). There are solutions but they require
| building extra mechanisms.
| FreakLegion wrote:
| Something that never comes up in these discussions is services
| with built-in JWT validation, like AWS API Gateway HTTP APIs. If
| you're already using one of these, you might as well take
| advantage of JWTs _in addition to_ your scheme of choice, whether
| that 's opaque tokens or something else. Let the service provider
| worry about unauthenticated people banging on your APIs.
|
| You can even maintain statelessness with opaque tokens if you
| really need it, e.g. issue both a JWT and a session cookie bound
| together by some shared value, say Fernet tokens. One goes in the
| JWT in local storage (anti-CSRF), the other goes in an HttpOnly
| cookie (anti-XSS), requests still require both to decrypt to the
| same value after the service passes them through.
|
| Generally this is overkill, though. JWTs for the service and your
| preference for the app works fine decoupled.
| phamilton wrote:
| We moved from jwt to opaque tokens and it's been fantastic. We
| also moved from using redis as our token store to using postgres
| (aurora).
|
| Querying against over 100M on postgres adds one or two
| millisecond p99 latency to all requests. That's perfectly fine.
| In fact, that's about the same performance we saw with Redis.
| Both were over the network, so I presume the network accounts for
| most of that delay.
|
| Having them in an rdbms is so convenient. It makes customer
| facing feature like enumerating current sessions very simple. It
| makes token expiration and remote logout simple. It makes
| spotting weird bugs much easier.
|
| I can't recommend it enough.
| rawoke083600 wrote:
| Whats the drawback for just including the ip in jwt and revoke if
| either time is up or ip change ?
| nkristoffersen wrote:
| I would imagine it would be a very poor user experience.
| Especially on mobile, where you jump around 4G/5G/WiFi networks
| and get a new IP address each time.
| deepstack wrote:
| or if the user allows JS in their browser, then just do some
| GPU/CSS/Font Collections,etc. finger printing and get the
| unique id, since all the major bowser vendors are not fixing
| this problem (except may be for webkit).
| lakomen wrote:
| The IP can change, is not guaranteed unique (many people can be
| behind 1 IP). Imagine unstable mobile connections going over
| 4/5g or random wifi as you move.
| Awerion wrote:
| Best things would be webauthn were you have crypto hardware
| like your smartphone
| xxs wrote:
| you can have multiple IPs at the same time.
|
| The "IP changes" is a common fallacy - even the mobile IP
| depend on the datacenter(s) process it. There is no grantee
| there will be a designated aliasing, and effectively there
| could be multiple IPs for the same client interleaving.
| notimetorelax wrote:
| IP can change multiple times when switching between mobile
| stations and wifi hotspots. Plus IP may change for each new TCP
| request if your operator uses CGNAT
___________________________________________________________________
(page generated 2022-09-29 23:02 UTC)