Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

If we stipulate that, we're still left wondering what the utility is of a standard that creates affordances for the insecure defaults, as opposed to just designing it right from the beginning.


> utility is of a standard that creates affordances for the insecure defaults

You could make the same argument about Cookies.

> as opposed to just designing it right from the beginning

And generally, it's quite difficult to design it right from the beginning because one would often start with the wrong assumptions. Most standards evolve, and it should be acceptable.


No, that doesn't square up. It's like arguing "you could say the same thing about TCP, because it allows you to build JWTs, which are a bad protocol".


Not the same. HttpOnly/Secure cookies were added much later and was not the default. They should have been inaccessible to JS by default from the beginning, and this policy has been a source of countless attacks.


If memory serves me right, cookies were designed by Netscape in 1994 before JavaScript was even a thing. They were released in an early beta of Netscape (0.9 something), while Javascript was only added in Netscape 2.0. SSL 2.0 was only added in Netscape 1.0. So the HttpOnly/Secure attributes were not relevant to the first cookie design, which wasn't even a standard.

When the first cookie standard (RFC 2109) was released, the Secure attribute was added. You could argue they missed HttpOnly, but JavaScript itself was highly non-standard and underspecified mess during this period (and for a while later too). Almost nobody was thinking about XSS as far as I can tell, and that term was probably only coined at least 2 or 3 years later (by Microsoft researchers[1]). At 1997, the people who even considered XSS, probably only saw this as an HTML injection issue that can be fixed at the injection site and doesn't require any special protections against JavaScript code.

If you really want to point a finger at issues in the early cookie design, then you could talk about domain matches. Not making the port part of the matched domain and not allowing an explicit way to trigger an exact domain match with a specified domain was a mistake. And the confusing leading dot rules (probably for optimizing a substring match without parsing the domain components) was also a mistake.

But RFC 2109 was replaced with RFC 6265 and now RFC 6265bis (which is not released yet, but is mostly implemented by the big browsers). These RFCs fix most of the big issues we had with cookies, and do not shy away from breaking existing behavior: setting SameSite=Lax as the default and restricting SameSite=None to secure contexts broke A LOT of sites for improve security. The changes made in RFC 6265 to forbid multiple cookies in one header also broke many sites.

An equivalent approach in the JWT spec would be a new RFC that does the following:

1. Forbids implementing Unsecured tokens and removes alg="none".

2. Removes RSA and ECDSA (or at least deprecate them) and make Ed25519 the "Recommended+" signature algorithm. If we allow RSA and ECDSA for compatibility, they must be explicitly enabled with feature flags or some other marker that signals their insecurity and security advisories on their potential vulnerabilities must be attached.

3. Removes the entirity of JWE as it is currently implemented (to be replaced with encryption else that is NOT orthogonal to authentication).

3. Requires that HMAC secrets are specified as binary base64url data. They SHOULD be generated by a CSPRNG or a derived using a safe derivation method (such as HKDF-SHA256 with safe key material) and MUST be at least as long as the "security size" for the algorithm (i.e. 32 bytes for HS256, 48 bytes for HS384 and 64 bytes for HS512).

4. Makes the "exp" claim mandatory to set, and mandatory to verify.

5. Add a section with strict implementation guidelines for libraries, e.g. `parse()` functions that skip verifying the token should have a clear name like `inspect_without_verification()` or `dangerously_parse_without_verifying()` and `verify()` function should always receive a key that is strictly typed to a specific algorithm.

6. Remove or restrict the usage of fields that allow the JWT sender to dictate the keys used for verifying it, like "jku" or "x5c". For instance, the standard can mandate that when implementing these fields, the verifier MUST NOT accept any JWKS URLs that do not match one of the explicitly allowed patterns or X.509 certificates that are not signed by an explicitly trusted CA.

[1] https://www.youtube.com/watch?v=mKAWpFdVcPY


Spec writers and library authors are human? Who knew


PASETO and TLS 1.3 were also written by humans. TLS libraries (which are several orders of magnitude more complicated than JWT libraries) are also written by humans.

If you passionately care about security and misuse-resistance you CAN write a spec that will lead to fewer implementation issues.


You must be young if you're pointing to TLS libraries as an example of doing it right and not getting into trouble with insecure implementations and downgrade attacks. https://wiki.freebsd.org/LibreSSL


I wish I was young. Did I explicitly said TLS __1.3__ or did I not?

A lot of effort was put into making TLS 1.3 a stronger, less agile and more misuse-resistant standard than its previous iterations. And that effort worked.


I don't understand what this is meant to communicate. The standard is either good or it isn't. "Good effort" is not an engineering assessment.


Your objection is that they should be "designing it right from the beginning" but that applies to all realms of endeavour. The reason they didn't is human frailty.

If everyone simply designed everything right from the beginning we would live in nirvana.


I read an article about business which had this classification, "Would be weird if it worked", "Might work", and "Would be weird if it didn't work" and argued that you want to be in the last category.

In engineering we aspire to a slightly stronger standard: "I made it physically impossible to fuck this up."



Yeah I don't think they were aspiring to that


You've completely missed my point. I don't even accept the premise of the JWT standard. But the eventual migration to safer default settings, in a format that continues to expend implementation effort to support settings nobody should use, is in fact a practical engineering problem with the standard.


And they've published updates[0] and libraries have hardened their defaults and removed support for insecure values (e.g. alg='none'). I'm not sure what more you want?

I'd rather use a refined, battle-tested standard with lots of eyes on it than some new untested contender produced by a handful of upstarts ("look, we just designed it right from the beginning! This time it's perfect!") PASETO reeks of second-system syndrome.

[0] https://www.rfc-editor.org/info/rfc8725/


I don't recommend PASETO either.


What do you recommend then? What technology has been designed, completed, then used for years without any updates or problems?


Bearer tokens are a dead end? You have to validate them anyway so traditional auth is the fallback.


https://fly.io/blog/api-tokens-a-tedious-survey/

tl;dr: most of the time you should use opaque random strings.


API tokens are a very small narrow part of the authorization universe. Having a shared secret relies on a trust relationship between the resource server and the identity provider that does not exist between, say, my SaaS backend and Google or Meta's login system.


The OP was talking about sessions (which include session cookies and API tokens). I'd argue these use cases are far more common for the average programmer than tokens and signatures that are used for federation, but I'll bite the bullet here:

JWT is a serviceable solution for service trust and federation. This use case often just requires a very-short-term token, so lack of revocation support is not an issue. Replay attacks are still an issue, but they can also be prevented with single-use nonces that are included in the token claims.

The OP's take (and my take as well) is that JWT is rarely the BEST solution for this use case. You kinda have to use it if you need to implement a standard that mandates JWT such as OpenID Connect. But OpenID Connect is a great example for a place where JWT was used, but was never really necessary. If you do use the authorization code flow securely (on the server side, with a strong client secret and proper CSRF protection) you don't need the ID token. In fact, you don't need to use any cryptography at all! Just like random session IDs, you've got a stateful solution that works reliably without any cryptography.

If you cannot do a series of authenticated network requests between HTTPS endpoints to verify trust, then a signed payload could be useful, but you've got better standards than JWS/JWT for that. That's all.


> If you do use the authorization code flow securely (on the server side, with a strong client secret and proper CSRF protection)

This restriction precludes all desktop clients, mobile clients, and webapp clients -- any place where you can't trust the client code to protect a secret.

I don't exactly disagree with you: Security becomes much easier once you rule out handling all the hard edge cases.


PKCE, OAuth 2.0 for Native Apps and the Device Code flow are a thing. In practice all of these clients work so well with OAuth 2.0, that the implicit and resource owner password credential grants have been removed from OAuth 2.1 and are the latest OAuth 2.0 BCP forbids the password grant and strongly recommends against the implicit grant.


... so, then, there is a need for something other than a shared opaque random string API key?

I feel like I'm being argued in a circle by a series of strawmen.


For what? For just authenticating a client application to a server without getting access to any user data? By all means. You usually don't need the client credentials in OAuth 2.0 if you don't want to use it.

But if you want access to user information, you can't just give access to an app that has a shared secret key to a all user data for every single users in the planet. You need to authenticate the user somehow, and sharing the user's password directly with the app is not a good idea for many reasons.

Even if you trust the app to be "written without any bugs", the moment you allow the password grant in OAuth, your service cannot use CAPTCHA, MFA or Passkeys efficiently. The password grant does not allow any of these, so this app that you've let through becomes the weakest link for all cybercrime groups that want to attack your service.


Random strings aren’t truly random, can be predicted, and don’t carry information that can be used elsewhere



Archived from 2018, it’d be more relevant to bring up a recipe about Oreo pie.


That’s dodging the question, and a very generic and blank recommendation.


Seems like a very specific recommendation?


I asked for a perfect tech in your eyes, that once created was never updated or improved upon.

*edit: a recommendation for random strings in most cases isn’t perfect


In what way? Random strings are basically the gold standard. A lot of token cryptography actually destroys value already present in the random string.


You keep arguing random strings are “basically” perfect for cryptography. I’d potentially read your research paper for strings if you cited it, but my main question is what technology do you think is perfect? I don’t want to hear about misplacing pseudo-random strings until I know your basis for a perfect technology that never improves from updates.

Edit: also there have been how many attacks have there been on pseudo-random generators?


There have been basically no practical attacks on the LRNG or on Windows CryptGenRandom and its subsequents over the last 20+ years. People have gone of out of their way to build userspace RNGs and blown their toes off, but getrandom/urandom have been rock solid.

I think "don't use Mersenne Twister as your RNG" is a much safer bit of load-bearing advice than "use precisely these safe settings for your JWTs".


I hear a lot of “basically” and “rock solid”, yet still no answer to my question or no “perfect” claim.

Edit: an impractical attack can still be used


Name the impractical attack that can be used on getrandom(), please.


1) https://cwe.mitre.org/data/definitions/338.html 2) if a system has partial entropy, output can be predictable https://www.netbsd.org/~riastradh/tmp/20200510/getrandom.htm... 3) the setting flag of GRND_INSECURE https://www.netbsd.org/~riastradh/tmp/20200510/getrandom.htm...

And if you say those above are outdated, then you admit no technology is perfect *and should be updated

You’re welcome


I don't think you understand the links you just presented me. Two of them are getrandom man pages from NetBSD, and one of them is a CWE, which documents a broad class of vulnerabilities --- the specific vulnerability here being "not using getrandom".

It's ok if you're totally unfamiliar with this space, but I'd recommend replacing some periods with question marks in your comments.


I’m not quite sure you can read. The two points with getrandom directly tie into the points made, and the cwe points to the larger vuln.

Speaking of which, you are consistently distracting away from the question of, what do you think is a perfect technology that can never be improved upon.

Edit: separate track, i will agree random strings can be useful if you agree technology should always be updated.

EditEdit:provide me a recipie of Oreo cookie smore pie


Not for long




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: