12 ms·
Bearer tokens are just awful
- kmac_ 5y agoIt would be nice to see some alternatives, "it's awful" isn't very constructive. From my experience JWTs significantly simplified development: simple model, easy to understand, standardised, easy to "debug". Show me something that can compete.
- shakezula 5y agoIt’s also not supposed to be the last stop in your security model - it’s supposed to be the first.
- pWnZMoyg 5y ago
- iso1631 5y agoSo don't set the token to expire after the "heat death of the universe", make the user reauthenticate after an appropriate time for the service being used.
- mjg59 5y agoThe problem is that you don't have control over what third parties are doing here. You may have control over the policies associated with tokens issued by your identity provider, but how do you audit the policies that third party services are applying to their tokens?
- xnorswap 5y agoI don't understand the argument here, if you're not issuing the tokens then they're not your responsibility. Can you give a more fleshed out example, why should you audit third party services?
- mjg59 5y agoHypothetical: I have a Github Enterprise org. Users log in via my identity provider to gain access. Github then issues a long-lived oauth token to the Github Desktop app. An attacker compromises a user's laptop and copies that oauth token. That attacker now has access to all my private repos until I notice and revoke it.
- iso1631 5y agoThat's github's service, before choosing to use it you should look at these policies (who and how github enterprise trust tokens) and see if it matches your needs. If you were running the service, then the power to trust those tokens is with you.
- mjg59 5y agoYou're a 5-person startup. How do you verify that all of Github's token issuance policies align with your needs?
- iso1631 5y agoDon't. Run your own. It's a cost of business, you can either rely on the standard terms of your suppliers, or you can supply your own, it's far easier than the vast majority of industries. Git especially is a federated system that has no need for things like github.
- mjg59 5y agoOr we could invent better solutions where we didn't need to depend on policies imposed by vendors? The value that Github provides isn't around their git hosting, it's all the integrated features. Reimplementing that isn't going to be trivial - there's a reason so many people use hosted Git rather than doing it themselves.
- xnorswap 5y agoSo you're worried that a very short lived compromise of a SSI / federated auth layer can lead to long-lived compromises of everything it grants access to because a short time can be used to generate long-lived auth to third parties? That's a legitimate concern, any compromise of the SSI needs a complete refresh of anything it's touched, including refreshing all API keys, keyrings, etc. Hopefully as the ecosystem matures it'll be easier to en-masse mark an account as compromised and have that status propagate and trigger resets of affected credentials. A similar threat is insider threat, (probably actually a greater threat) where someone leaving a company could generate tokens which grant them access for long after they've gone. If reason about how that's typically managed (disabling their upstream accounts) that gives insight into how to deal with your initial concern, it should be managed in the same way.
- iso1631 5y agoSo I have a service using openid and I use google to authenticate the person logging in. I do that, then that's done. Now I could simply issue a session cookie, or a permament cookie, to the client so we never have to use google again. Or I could make it so that cookie lasts 10 minutes before reauthentication. I can use a refresh token which means they don't need to reauthenticate but if google expires the connection (disabled user etc), I expire mine. Either way, that's my decision as the person running my site, and it's the clients decision as the person running the client to decide whether to send the blob, or to share that blob with other clients. The only information I know is that somebody authenticated with google at a specific time and I had proof of that, I have no control over what happens to that blob. Google has nothing to do with what I or the client do with the information. You're right that I can't audit the third party (google, microsoft, etc), but I don't pretend I can. Google could simply change their password checking to "if (true)", that's google's business. If I'm worried about the third party authenticator then I shouldn't use it, and I should roll my own. (There was an early Tom Scott video imagining a world where google just says "yes" to passwords[0]) I have an internal read-only blog site using our corporate openid service to ensure that someone accesses the site. Once they authenticate, I allow them access for 30 days before forcing a reauthentication, because it's low risk. OK if they log in from a compromised machine than a hacker gets to read some internal information, its very low risk. I've also got a site where you can make major changes. You have to reauthenticate far more frequently to make those changes (every 30 minutes). It's a matter of risk. [0] https://www.youtube.com/watch?v=y4GB_NDU43Q https://www.youtube.com/watch?v=y4GB_NDU43Q
- mjg59 5y agoI, as the company paying for your service, have no direct ability to influence the policy that you apply to the tokens you issue. If you start issuing tokens that are good for decades, I have no trivial mechanism to detect that.
- iso1631 5y agoAsk before you spend the money, stick it in the contract. If you don't like the answer don't sign the contract.
- michaelt 5y agoThis is a common problem in enterprise single-sign-on systems. The issue is: If the user presses the 'log out' button, you want it to take effect within a few seconds. But if logouts are simply a timestamped record expiring, they'd have to expire within seconds, and that would basically mean re-authenticating on every single request. And at the same time, some webapps have shitty re-authentication flows (like discarding any unsaved work-in-progress and kicking the user back to the homepage) and they're only usable with a re-authentication periods measured in days.
- jillesvangurp 5y agoIt's tradeoff. If you require tokens to be invalidated instantly, there's no way around the notion of doing some kind of lookup when you are validating the tokens. It could be as simple as having a database/memory store somewhere with invalidated tokens or all the still valid tokens. You might cache those for a few seconds so the performance overhead would be pretty minor. You can make this as strict/complicated/slow as you need it to be. It's up to the validating party to decide just how strict they want to be. But mostly, the device simply deleting the tokens when the user clicks logout is good enough though. Logout does not protect against mitm attacks of course. But that's not what logout is about. And if you have attacks like that going on, the user clicking logout or not does not matter anyway because you can't trust anything they do since you can no longer tell them apart from whomever is attacking. All a logout signals is the user throwing away their tokens (and probably a lot of other local state). Which is why world + dog uses either tokens that never expire or tokens with expiration times that are pretty long. In our case we use access tokens and refresh tokens. The access tokens are refreshed regularly and the refresh tokens expire after a few months. So, the only users that we force through repeated login procedures are those that don't regularly use our app. Anything more would be annoying. And yes, if their devices get hacked, those users have would have an issue. That's the tradeoff. The user using a token they just threw away is not a real problem because they wouldn't. The user's tokens getting stolen is a different problem. That's why having the tokens expire eventually is a good thing. Long expiration times are not appropriate if you are a bank for obvious reasons. So, they tend to use expiration times measured in minutes typically and use additional authentication around sensitive transactions.
- xnorswap 5y agoA big limitation is forced early expiration. If you need to do that then you end up needing to share expiration information and therefore need to share something that might as well be a password hash. So for example it's not great to use instead of a session key. You could design a system where you have, say, 6 API endpoints and instead of the API endpoints needing access to the authentication db, you use bearer tokens from a single sign on to grant access to the API. That works great until Bob realizes that Eve has got access to his password and hits a password reset to force Eve out the system. But with bearer tokens, Eve still has access until those tokens expire. You could add a check for expiration against the calls, but then we're back to session keys being more straightforward because we're back to having some central information (has Bob's token expired) that needs propagation to the different services. You could have extremely short expiration but then you're back to having to round-trip to re-authenticate often (or in an auto-refresh situation, one where you're back to checking for expiration yet again). I think bearer tokens work best for internal proxies / APIs to avoid hitting the data store, they aren't a great replacement for session keys.
- mormegil 5y agoYeah, there is this classic: http://cryto.net/~joepie91/blog/2016/06/19/stop-using-jwt-for-sessions-part-2-why-your-solution-doesnt-work/ http://cryto.net/~joepie91/blog/2016/06/19/stop-using-jwt-fo...
- spacemanmatt 5y agoLong-time fan of joepie. Worth a follow.
- eurasiantiger 5y ago> You could have extremely short expiration but then you're back to having to round-trip to re-authenticate often (or in an auto-refresh situation, one where you're back to checking for expiration yet again). GraphQL clients like Apollo can solve this by re-authenticating transparently on error and reissuing the same request.
- ledauphin 5y ago
- jillesvangurp 5y agoExactly, all of the reasons bearer tokens might be awful are essentially self inflicted pain. Simple suggestion: don't do that and do it right instead. It's an opaque blob, by design. Which means it could be anything. Including something bearing useful information that you can verify in a sane way. In our case, we use JWT tokens that contain a few claims, are signed, have an expiration token, etc. Not awful at all. Verifiable information, signed by us with our private key, exchanged over https. That's not information the bearer of the token needs to be aware of but it is something our APIs can trivially verify and use as a basis for authenticating the bearer of the token. Pretty neat mechanism. Nothing wrong with it. Used at scale by world + dog on the internet without a lot of issues. And before somebody starts ranting about JWTs being awful: same argument. They don't have to be but they can might if you decline to use sane crypto. So, use it properly and you're fine. It's not that hard.
- mjg59 5y agoAnd if I compromise a system that possesses one of those JWTs, I can copy it elsewhere and have access to all the resources that JWT grants me access to. You're not tying it to a specific device, and you're not providing a mechanism to verify the device state when making the access decision.
- jillesvangurp 5y agoThat's why we use expiration times. If I was a bank, I would be using very short expiration times and also use second factors. And have a lot of ceremony around releasing our app. And if I cared enough I would indeed add some claims narrowing down the scope of the token to a device, require our user to wear tin foil hats, and what not. Security measures are proportional to the thing they protect. Plenty of banks use both bearer tokens and JWTs. Nothing inherently wrong with that. If your require these things, do them. If you don't, then don't.
- mjg59 5y agoI, as your customer, don't control your expiration time. But I, as your customer, would like to be able to apply my choice of policy to tokens that you issue that grant someone access to my data, because otherwise I don't control access to my data.
- zabzonk 5y ago> In theory you could just hand someone a randomly generated blob, but then you'd need to keep track of which blobs you've issued and when they should be expired and who they correspond to Is this so difficult?
- recuter 5y agoIt isn't until it is. And wherever you store it is a juicy target.
- zabzonk 5y agoAnd more secure would be....what?
- withinboredom 5y agoNot localstorage. :) I've seen them in http-only cookies which is sent with every request but not inspectable by js. The server can automatically refresh the token every-so-often transparently without the client even being aware or able to influence it in any way.
- mike-cardwell 5y agoWhen will "until it is" kick in? It has never kicked in for me...
- zimpenfish 5y agoI've worked at a couple of places where the session token lookups were the bulk of database traffic - to the extent that one place had to split it off to its own cluster just to stop it clogging everything up.
- gary_0 5y agoWouldn't you just store it in the same place you're storing the main authentication data (eg. password hashes)? [edit] I guess that database would get hammered pretty hard on every request, unless you use caching... which might be what you're getting at.
- lowwave 5y agoOr you can put device/or ip related info baked into the token. That way when the user device or ip changes, you can invalidate the token.
- mjg59 5y agoDevice info is spoofable, and tying it to IP means the phone experience is just awful.
- lowwave 5y agoFor sure, but then the user assume they know what they are doing. It is to prevent cookie hijacking.
- lelanthran 5y ago> Or you can put device/or ip related info baked into the token. That way when the user device or ip changes, you can invalidate the token. yeah, I always wondered why there isn't a standard field in the JWT containing a fingerprint/hash of the client's machine/browser/etc.
- samarthr1 5y agoAdvertisers would love such a thing
- lelanthran 5y ago> Advertisers would love such a thing Why? It doesn't give them any more info than they already have (the logged-in user!)
- sokoloff 5y agoIt could be used to tie that logged in user to other web sessions that are currently anonymous.
- soco 5y agoIs there a difference between that token and a password? Yes, the token is bigger and created by somebody else, yet for all practical means it walks like a password and quacks like a password...
- xnorswap 5y agoIsn't the fundamental difference that a password needs checking against a stored per-user value such as password hash and therefore needs a database lookup, while a token can be validated through just the cryptographic signature and therefore avoids hitting the central database?
- ptsneves 5y agoYes but then you add revocation and you are back at a centrally stored database to check against.
- xnorswap 5y agoThat's correct. There are scenarios where it still makes sense. It's plausible that it would more efficient for some high traffic services to push (the somewhat rare) revocation notices out to endpoints as still being more efficient. For example imagine a whatsapp clone. People send thousands (probably tens of thousands) more messages than they issue password/auth resets. Having the incoming message endpoint maintain a cache of recently expired tokens would let you set a reasonably long (e.g. 24 hr) token expiry. You could have the app re-auth in the background on start-up and/or when it detects the expiration window is closing, while incoming messages avoid hitting the central DB for auth. Maintaining a cache of expired tokens pushed to endpoints would be vast orders of magnitude smaller than maintaining a cache of all session keys. I don't know for sure though, perhaps central session caches are just more practical and secure anyway for these kind of end-user endpoints. In some ways this is similar to the Certificate Revocation List handles certs. There are certificate revocation notices that are used instead of needing to check centrally the validity of all certificates. That said, the CRL has essentially been deprecated in preference of a lookup model.
- 3np 5y agoSo what is the option, actually? TEEs and TPMs which the end-user and device owner/operator/admim have zero control or insight into (or is this also under the scope of the "local enclave"?) OP doesn't propose any in their opinion better alternatives. I'd argue for (roughly, on the move) client-side keys and cryptographic signing (mutual certs basically) and issuing session certs which could be counter-signed, with a short lifetime, but it sounds like they'd be against that too. Under ZT, how precisely is one to confidently verify local state otherwise? There's a lot of value in the ZT paper and movement, but this particular aspect is both spooky and confounding.
- mjg59 5y agoMutual certs get you closer, but the missing component is device state validation. I probably don't want to share my understanding of device state with a third party (it might include things like which apps are installed on a device, and sharing that with a third party is extremely not cool), and I probably don't want to share my policy (if they get popped then an attacker is going to be able to figure out what I'm looking for), so I need a mechanism where the third party can call out to me with proof of the client identity and I can then compare that against my policy and give an answer back. And we don't have a good way to do that yet.
- ThePhysicist 5y agoI think the article mixes up several different problems. Both cryptographic keys and opaque tokens are "possession factors", i.e. if you have them you can authenticate against a service. Signature-based authentication schemes are mostly used to protect against replay attacks, which are easy to perform with an opaque token as it won't change. That said you can tie both opaque and cryptographic tokens to additional factors. For example, machine tokens can be tied to specific IP addresses, so an adversary won't be able to use them from a different device. Tying them to other possession factors like TOTP codes would also work, though it's often impractical. Mobile apps can easily make use of signature-based authentication schemes based on keys stored in a secure enclave, both Apple and Android phones have good support for that. For web apps it's more complicated as there's no way to store keys in an enclave (and many older laptops/computers don't even have TPMs), so you keep them lying around in memory or in the browsers' session/local storage, which of course isn't ideal.
- fragile_frogs 5y agoYou can actually securely store a key pair inside of indexeddb by setting extractable to false [1]. You can then get a reference to the key and perform your allowed key usages without JS touching the key. [1] https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/generateKey https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypt...
- chriswarbo 5y agoI like bearer tokens, but the author's terminology makes it sound like they're not thinking about them from an appropriate perspective. My preferred way to think about tokens is a form of inter-process communication. In a scenario like 'view this document requires authorisation', the token is a way for the the 'decide whether to authorise' process to communicate some data to the 'view the document' process (that data being 'document-viewing is authorised'). Statements like 'bearer tokens allow hackers to impersonate a user' isn't congruent with what tokens are, or what they're for; in particular, tokens have no concept of "user", "logged in", "authentication", etc. They simply communicate data from one system to another. The author's complains would be better phrased like "Caching authorisation results is vulnerable to time-of-check-to-time-of-use problems"; that's true regardless of the underlying technology. Finally, I also consider tokens to be a 'last resort'. From a capability perspective, unauthorised clients should be unable to say what they want; for example, we can restrict access to a document by making its access URL secret and unguessable (we should also allow fresh URLs to be generated, and old ones to be revoked/deleted). That's (a) safer than telling everyone where the document is then having to decide which requests to allow/forbid, and (b) easier to use and integrate into other systems (since it's just a URL; no cookies, "are you a robot?" captchas, etc.). If we're faced with an action that can't be made secret on its own (like gating it behind an unguessable URL), then we can make it secret by requiring an extra "dummy" parameter; AKA a 'token'. Note that this is the complete opposite of what the author seems to be describing, which is: - Reaching for tokens first (rather than as a last resort) - Having them represent "data" which isn't related to the actions being performed (e.g. "this is person X", rather than "document Y is readable") - Using this one token to access everything, rather than using fine-grained action-specific authorisation
- jpgvm 5y agoThis is solved by mechanisms such as DPoP. https://datatracker.ietf.org/doc/html/draft-ietf-oauth-dpop https://datatracker.ietf.org/doc/html/draft-ietf-oauth-dpop
- drewcoo 5y agoSo logically, that's a lacking thesis. And, in fact, an intentionally misleading one. That said, I'm a big proponent of zero trust. My real question from this, though, is who actually does zero trust right? I'd really like to know. I would love to work there and prove it works. Ping me if you do that, please.
- shanehoban 5y agoI recently learned how to use Bearer tokens with a PHP JWT interface and disagree that they are `just awful` (I'm a FE dev for perspective). I have a setup of a 24 hour token that holds the necessary information to authenticate the user's requests (like a PHP session really), along with a 30 day refresh token. My Vue FE detects when a 401 status code is returned (using axios) and attempts to refresh the token. If this fails, the user is redirected to the login page. It works quite well IMO. This setup lets me authenticate cross domain requests without any trouble. I was previously used to doing everything same domain via standard PHP sessions.
- vlod 5y agoGenerally the problem is that if your computer gets stolen (or cookie/localstorage etc), the attacker has access to your account for 24 hours. i.e. until there's a check against a disabled-user-list (in the database). The progression then becomes to reduce it from 24 hours to say 5 minutes (to reduce the attack window, which may or may not be adequate). It then becomes almost the same as validating the user session on each request (not quite, but you start debating if using jwt is worth it at all).
- Sirened 5y agoWhy does the author assume we want to associate a bearer token with hardware at all? When my services issue a JWT, I am issuing a right to talk to my service. If you want to take that token and move it to your phone, neat good for you. If someone steals your laptop and dumps the secret, that's sure as hell not my problem to solve. The application layer is not the appropriate place to apply a mitigation for a user's laptop getting stolen (even if you in theory could).
- saagarjha 5y agoI get the feeling that the author is speaking from the context of corporate zero trust, where they would like certain policies enforced on an endpoint before it is allowed to access a service, and thus transferring the token to an unmanaged device is considered a problem.
- mjg59 5y agoYou're free to assert that it's not your issue to solve, and I'm free to assert that I'm not using your service as a result. It is possible to provide equivalent functionality without it being trivial to exfiltrate authentication tokens to other devices, and I can't see any good reasons for refusing to do so.
- nannal 5y agoYour expectations might be too high, would you like all applications to monitor if you enter a bad part of town and revoke tokens just in case?
- mjg59 5y agoNo, I'd like applications to check with me whether I was ok with the state of my user and their device.
- Sirened 5y agoIs this a wholehearted departure then from the whole "Simplicity Principle"? Not to be a complete ass, but in your view is there a defensible reason why every single layer of the entire network stack does not guarantee integrity? It would make things more reliable, after all you would still be guaranteed integrity even if TCP is broken! But we don't do that because we acknowledge that maybe we should be solving issues at the poignant location in the stack rather than just haphazardly shoving things in because we need said things in general. I'm not disagreeing with your underlying point, really. I do agree that authentication is broken in that it fails to provide the actual guarantees we think it does. This is what I was getting at with my point above about issuing a right to talk to my service--that is, in reality, all any practical authentication system can provide today. You simply can't be certain the TPM your service stashed it's keys is secure without forcing attestation (again, problematic). Therefore, as far as your service can assume, your client may have just published the keys for the world to see. This leaves you in no better a theoretical position and it does not solve any of the problems identified with any other auth mechanism purely because it is not fundamentally.
- vbezhenar 5y agoI don’t get this article. How are you supposed to validate hardware? There’s no API for that. You can bind session to IP but that wouldn’t work for modern mobile connections. Ideally hardware should have protected private key with manufacturer signature. And API to sign something. Then you can bind session to hardware. But that’s not available today.
- ecf 5y ago> How are you supposed to validate hardware? Ah, you’ve discovered the zero trust trap. Don’t worry, advocates will be happy to sell you an ultra expensive security option that breaks more often than it works.
- mjg59 5y agoYou don't verify the hardware directly. You provide a mechanism for client certificate validation (I issue the certs, I can assert that they're tied to hardware), and you provide a callback for validating device state (I define the validation policy, I compare that against the data that I have and say yes or no). It's not about services taking responsibility for this themselves, it's about providing mechanisms for customers to have their own policies enforced.
- 3np 5y agoYou are talking about SGX-style TEEs, is that correct? Effectively putting hardware manufacturers as ultimate issuers with corresponding ultimate authority (ie spoofing, revocation, tracking) Or if not, how would you envision it?
- _8j50 5y agoI agree with OP. The security model is similar to kerberos tickets or ntlm hashes. Revokable Private key authorizarion is the best way to go imho. I don't mean at the transport layer but at the HTTP/app layer. This should replace not just bearer tokens but authentication cookies as well. Each connection is authenticated by the final server. Hopefully you can store the private key on fido or tpm as well to make theft harder, forcing attackers to maintain persitent compromise of your host.
- josephcsible 5y ago> one of the core ideas of Zero Trust (that we verify that the client is in a trustworthy state on every access) A server verifying that a client device is "trustworthy" sounds horribly DRM-esque.
- spacemanmatt 5y ago<Yawn> Another "JWTs are awful" post that fails to coordinate cookies, browser security policy for cookies, and JWT expiry into the coherent security apparatus that many of us use without problems or fanfare. The anti-hype against JWTs is unjustified.
- aaomidi 5y agoI legitimately don't get the point with all of this. At the end of the day it's stored the same way on the client side. For any large service you need to have a database call anyway. Why is there so much written about effectively the same strategy?
- protontorpedo 5y agoI don't understand. Even if you had a cryptographic challenge mechanism to be verified by specialized hardware in the client, if I control the client then I must be able to "poke around in the API" from it anyway. I think your best bet to prevent this is to to detect abnormal client behaviour and block it.