Show HN: PAST, a secure alternative to JWT
github.com
github.com
My only nit --- apart from the "auth enc seal sign" names, which aren't coherent --- is why do public key at all? Yes, Nacl supports it, but that doesn't mean the token format does. What's the use case for it? Who's asking for it? Specifically who? The overwhelming majority of JWT implementations I see aren't public key (except for the fact that the format is negotiated and might be tricked into being that).
Why not punt "seal" and "sign" into a "v3", when/if it's needed?
> Why not punt "seal" and "sign" into a "v3", when/if it's needed?
Would you be happier seeing something like this?
- v1: HMAC-SHA2, AES-CTR+HMAC-SHA2
- v2: RSA and all its sins
- v3: Libsodium crypto_aead_*
- v4: Libsodium crypto_{box,sign}_*
> What's the use case for it? Who's asking for it? Specifically who?The only use-case I'm aware of as of this morning is OAuth2 users who currently use JWT for access tokens. https://bshaffer.github.io/oauth2-server-php-docs/overview/j...
1. Give developers the minimum amount of knobs. If they need to choose between 'auth', 'enc', 'seal' and 'sign' it's still going to be confusing. In my case they can personally come to me and ask "Which version should I use? Which type should I use?", but it's not clear.
I'm still undecided whether supporting an unencrypted authenticated token is useful, but 'enc' should ideally be the default, with users going a little bit more out of their way to do anything else.
2. Asymmetrically signed payloads with an expiry are this strange bird that looks like a duck, quacks like a duck but unfortunately _are not a duck_. They're certainly useful, but when I was calling them 'tokens', my users were confused whether they should use them as access tokens.
It's great to have a simple and robust encoding format for packaging payloads with an Ed25519 signature, but it's better to clearly call it something other than 'token', or you'll end up with users deciding they should use asymmetric access tokens just because it makes the key more secure.
3. You want to have some mechanism to specify key ID or key version in the wrapper, because this allows you to do automatic key rotation gracefully. You can use the optional (AEAD) payload for that, but that wouldn't be entirely clear to the users how.
Let's say you want to rotate the key every week, but your longest token has a TTL of 24 hours: you will need to have a window where you would support two different encryption keys. In other rotation scenarios (e.g. rotating every 24 hours with longest token TTL being 30 days) you can have many more encryption keys supported concurrently. You can iterate and try all possible keys of course, but having key ID/version is much cleaner.
In my view, that's one of the big takeaways from early cryptographic protocols: complex handshake negotiations just won't be secure, so just don't. The other is that crypto code should ideally not contain any parsing at all.
e: Well that and the whole debacle on the level of primitives and operation modes of course.
No difference from the perspective of the token consumer. From the perspective of they token generator, it means rotating per-tenant keys rather than a single keypair.
Additionally, your TLS terminating stack is much better hardened than median in-app crypto code.
PAST mitigates the risk somewhat by hardcoding a public key system into its version. But I'm still recoiling from the kind of first-principles mixing of systems security and cryptography that happens when people find new reasons to deploy public key primitives.
Note that one of the first crypto bugs in JWT stemmed from how it used curve public key crypto.
For instance is there a good resource you use on what are good alternatives when you think you need to use PKI when in fact there are better alternatives?
Is there a good resource on how to use JWT correctly that you trust?
(Edited-tone, was a bit more aggressive but was pointing out the opportunity to educate instead of just say things are bad).
If you listen closely, some security wisdom could applies to a lot of specialties. For ex this quote is about authenticated encryption, but it's not really bad advice if you change the subject from encryption, to rolling your own web server:
"Authenticated encryption is something you should use as a complete package, implemented as a single unit by a well-reputed open source cryptographic library and not assembled piecemeal by people who do not specialize in cryptography."
So what's the difference then? The stakes are higher. Serve the wrong web page, you'll be working on a bug. Be careless with security primitives, you could make a fortune 500 stock price go down, or make your CEO have to issue a press release, which tends to not to reflect well on your performance review.
In this light, "finding new reasons" I would infer to mean deviating from established best practices in any way without a damn good reason, even then without that reason being challenged and vetted.
All of the creativity in security should be in the research. For production implementations I don't want any creativity. Ideally, I'd want prod to be the opposite of research: Conservative and uncreative, struggling to stay awake because it's so boring and uneventful.
If you just want a few examples of stuff that can go wrong that doesn't go wrong if you just use a stored token instead of crypto, or doesn't go wrong if at least you use symmetric crypto instead of asymmetric crypto:
- Some bugs are about negotiation, e.g. key material misuse between RSA and HMAC schemes in JWT.
- Some bugs are about cryptographic implementation, such as not reusing nonces for ECDSA or RSA padding oracles or RSA keygen vulns (see Infineon bugs a few months ago). These are almost exclusively in the asymmetric crypto camp.
- Some bugs are about specification issues, such as non-mandatory aud (audience) and exp (expiry). You don't have specification issues if your tokens are opaque random numbers. You have significantly less bad/fewer specification issues if your tokens are versioned and you don't allow negotiation.
https://storify.com/jcuid/thomas-h-ptacek-don-t-use-json-web...
https://news.ycombinator.com/item?id=13866883
https://kev.inburke.com/kevin/things-to-use-instead-of-jwt/
or go with the flow:
https://www.google.gr/search?q=ptacek+jwt&oq=ptacek+jwt&aqs=...
He has countless comments preaching against JWT and DNSSEC.
Mind you, I know the nickname, I know he is good with sec (I'd hire him to vet an app) and all but I don't know him IRL or ever heard of him before joining HN ... that's to say that he spent a lot of digital ink discussing these two topics here. The subset he's talking about, should amount for more than 50% of the regulars I guess.
The Storify link is slightly more useful but again doesn't really explain anything - it's just bullet points of "I think these things are bad in a standard" which is great if you already have the knowledge of those things. Utterly useless otherwise.
And if "implementation errors should lower your opinion of a specification" means we shouldn't use JWT, where does that leave us on WIFI, SSL, HTTP, speculative execution in pipelines, ...?
I'm criticizing JWT. Not you, or any other developer. If you don't understand or follow or agree with my criticism, that's OK. We can still live our lives.
That is not intended - it's more "I don't understand it, I'm happy to believe it's broken but all we get is Appeal To (self)Authority as to why rather than actual usefulness."
> If you don't understand or follow or agree with my criticism, that's OK. We can still live our lives.
Well, sure, but wouldn't you prefer to help people who don't understand by actually explaining something for once?
Do you have any good recommended primers that’d help me get it?
Or should I just get off my arse and finally do cryptopals? ;-)
I think you mean, "private" key is what you use when you have no other choice.
For example, this is how identity tokens from AWS Cognito are verified. They are RS256 JWTs signed with Cognito's private key, and any server can download Cognito's public key to validate that the tokens were issued by Cognito and haven't been subsequently altered (without having to make a network call to Cognito to request validation).
As someone who had to work with XML-DSIG, JWT seems less bad :)
If you have thousands, you end up spending a lot of time on key distribution if you need individually distributed secret keys.
What you get is that the peer can't forge tokens. But you're trying to authenticate to them; they already have full authority. So what are you fixing? (I'm not saying it's "nothing", but I am saying it's very little, and it's definitely plausible the increased risk isn't worth it.)
What do you mean by "tiers" here? The specificity of that word suggest you don't just mean "peers", but at the same time clearly symmetric systems win at nested delegation. (krb5, macaroons come to mind)
You get something you can show to a third party: 'see, the bank said their client was good for $10,000!' I can see where that might be useful.
That said, very few people want such a security scheme and as theoretically simple as it is on paper, it quickly ramps up to the real world complexity of PKI key management.
(I could see a small use for web APIs for developers and power users that allowed, for instance, Keybase-verified claims like HN account name/FB name/email, for very simple and easy to curl/iwr/httpie from the command line using Keybase-managed keys.)
I'm not sure if that small window of opportunity is worth the support complexity in PAST here, but given the model of support only specific versions, having them as separate verbs (sign/seal) makes it easy to block claims you don't expect. The one flipside from an API design standpoint that I see is that leaves a need for some sort of header like X-Accept-PAST: v2.auth
I've long considered the merits of a kerberos-like system built on top of something like nacl... But without out-of-the-box support from all kinds of systems... It'd essentially build down to ssh+certificates with expiration dates... So i've gathered "better CA for ssh" is the better product. And there are thankfully a couple of projects in that vein (teleport, netflix/bless, others?).
[ed: i should add: I think tptacek is absolutely right about public key systems being easier to get wrong; but part of that is also the problem domain: look at the history of security issues with Kerberos (both implementations and protocol evolution) for a great example. On the face of it NxN key exchange is "text book simple; should be easy to define, a little tricky to scale". Then there's replay, clock drift, (de)serialisation, nounces, large number of session keys (secure random numbers)...]
I agree that they're worth examining separately, but the more general point still stands that there is a lot more that can go wrong with sign than with aead. The arguments for broken RSA-encrypted cookies apply similarly to broken signed cookies. It's not clear to me for example that an invalid curve attack against seal is intrinsically worse than a nonce (ab|re)use bug against ECDSA.
I might be dropping "seal" entirely, as its utility isn't really a good fit for security tokens. (Sealing APIs can be very useful in other contexts, though.)
A simple closely related field: OAuth 2 token replay attacks. I auth against A with Facebook, A uses token to impersonate me against B. ISTR Google had basically the same bug. A median startup will not find that bug. Storing a random token in a database? Very likely they won't mess that one up. Also, if you do (let's say your randomness generator is MT as opposed to a CSPRNG), it's easy to fix, because you control the validation endpoint.
You can't say password based authentication is bad because some developers choose to store password in plain text. The blame squarely lies with the developer.
People implementing auth without willing to go a little deeper may hurt themselves.
Note: you probably still just want a random key in a database. And revocation is still an issue. But if you’re absolutely sure you want to mint tokens...
In general, I think that this is the wrong approach, because that means adding a database round-trip (which in a large system is almost certainly a network round-trip) for each and every API call. Notably, if the entire system is secured in depth (which large systems should be), it means adding a network round-trip for every layer of the API (e.g. one for the frontend server to validate the user, then another for a backend server to validate the frontend server). Using a stateful token[0] replaces that network round trip with a public-key or hash verification, which is much faster.
> revocation is still an issue
I think that generally revocation concerns are a bit overblown. Even with a database lookup on every request, there is a (small) amount of time that one is willing to act on out-of-date information (after all, the user's access could be disabled immediately after the lookup, before the action is performed). Almost every business has some window in which it is willing to act on old information: better to make it explicit than to leave it implicit.
I really like the long-lived stateless token-refresh token[1] and relatively short-lived stateful access token approach often seen in OAuth2 setups. E.g. an email provider might only bother refreshing a read-email access token every five minutes or so, but might wish to refresh a delete-email or send-email token more frequently (or require a database lookup each time).
[0] When I write 'stateful token,' I mean a token which is full of state; confusingly, some folks calls this a 'stateless token,' because the relying systems do not need to store or consult state.
[1] When I write 'stateless token,' I mean a token which carries no state and thus must be looked up in some form of database — a random key in a database would suffice.
In general, asking a database for set membership is not close to the slowest thing applications do.
> Notably, if the entire system is secured in depth (which large systems should be), it means adding a network round-trip for every layer of the API (e.g. one for the frontend server to validate the user, then another for a backend server to validate the frontend server). Using a stateful token[0] replaces that network round trip with a public-key or hash verification, which is much faster.
A handful of those set membership checks: still not the slowest thing applications do. (Also, I don't think it's a given that internal auth has to work the same way external auth does, for a bunch of reasons.)
> I think that generally revocation concerns are a bit overblown.
Without revocation, you can't log out of things, and you can't invalidate sessions after credential rotation. So unless you're saying tokens should be valid for some tiny number of seconds... in which case, it's questionable that you're buying a lot of performance for your drastically more complicated token scheme.
> Even with a database lookup on every request, there is a (small) amount of time that one is willing to act on out-of-date information (after all, the user's access could be disabled immediately after the lookup, before the action is performed). Almost every business has some window in which it is willing to act on old information: better to make it explicit than to leave it implicit.
Median response time is not comparable to usual token expiry times. If you do make them comparable, then you're making that DB check every time anyway. The entire point of the token is to do that less. You're right that it's implicit, but it's also "the fastest that it possibly ever could be", so that's not a bad kind of implicit.
If you really desperately want to make the check faster, why is JWT better than a local token cache?
From Jeff Dean's list of numbers every programmer should know[0], a round trip within the same datacenter takes on the order of 500,000 ns; a main memory reference is on the order of 100 ns. How often will an application be making an order of magnitude more than 5,000 main memory references to service a request? Sometimes, sure.
In our experience online validation completely dominates our workloads.
> I don't think it's a given that internal auth has to work the same way external auth does, for a bunch of reasons.
Oh, you're completely correct. It has upsides & downsides.
> Without revocation, you can't log out of things, and you can't invalidate sessions after credential rotation.
I pointed out that I like the use of stateless tokens, which can be revoked. In many cases 'log out' can just be destruction of the token. And in many cases it doesn't make sense to invalidate access just because credentials have rotated (in many more cases it does, which of course is perfectly supportable with stateless tokens).
> So unless you're saying tokens should be valid for some tiny number of seconds.
I'm not: I'm saying that in many cases there's no business need to assure revocation within $SMALLNUM seconds, and that the business costs of online validation utterly dominate the costs of running a service.
> If you really desperately want to make the check faster, why is JWT better than a local token cache?
There are only two hard things in computer science … cache invalidation is one of them.
I mean, it's a pithy saying, but TTL invalidation is a problem you have to solve with JWT too. Caching tokens is the easiest possible cache invalidation problem: definitionally, you know a priori exactly when the token is invalid.
That argument is only valid if your application doesn't touch disk and doesn't touch the network to go talk to some other service anyway.
Do you have a concrete description of what "online validation" specifically means for you, and how long it takes? How long does validating the token take instead?
Why? Adding another source of “slowness”[1] isn’t free just because other sources of “slowness” already exist, especially if it’s already close to being unacceptably slow as it is.
I mean, sure, if the request takes ten minutes anyway and the validation check takes a few seconds, nobody will notice, but if I’m doing, say, a single non-local database lookup for the request then adding a second one for verification doubles the time it takes to service the request.
[1] I’m not saying that a network round trip and database lookup are slow, just that for the sake of this argument, they are being considered slow.
Having said that, I do believe that what you’re saying is the right approach for 99.9% of use cases and I would imagine that in almost all cases the performance hit really is negligible.
Is it literally definitionally impossible that minted tokens have a useful application? No, of course not. But absent very specific cases I’m going to argue for the thing that’s safe, fast & simple :-D
- DC roundtrip: 0.5ms (per GP's own numbers)
- P256 ECDSA signature validation: 2ms [0]
I've seen this referenced a few times before but I don't understand why minting tokens is bad.
Also, isn't creating a random key as a token the same as minting one? or what is the correct context here for "minting tokens"?
Thanks!
When you generate a random key, you have to go ask a trusted third party what the data associated with that key is (and, therefore, if it's still valid).
Minting tokens is bad because it's drastically more complicated, has tons of failure modes, and most of the time you end up doing tons more database transactions anyway that are way more complicated than set membership (i.e. is this still a valid token?).
In this context then, what are your thoughts on minting tokens using Macaroons [0]? I ask because they seem to be of much lower complexity than JWTs since they just hash the data so no encryption algorithm negotiation or anything of the like, however they still meet your definition of minting a token.
Obviously it would depend on a case-by-case basis to prefer macaroons over say a random token or vice versa, but in general is chaining HMACS still considered "drastically more complicated"?
My uninformed opinion is that verifying a hash shouldn't be that bad but my security expertise is pretty much non-existent so it would be great to be schooled on this :)
It's amazing how seemingly simple things can get so complicated when talking about security.
Unfortunately that's where the simplicity of Macaroons end because even the official docs on libmacaroons have some weird choices, like encoding date in a ISO-like format (without timezone specifier at all). Also using UTF-8 is not that efficient if one could encode date as a number. Of course Macaroons are flexible and because the caveats are byte arrays you can use CBOR or whatever to conserve space. But then you lose compatibility. And you need compatibility if you want to utilize third party Macaroons (if a third party mints you a Macaroon with unknown caveat that makes the entire thing invalid). Third party Macaroons are the most powerful feature of the entire system but they introduce a lot of complexity: Macaroon references (look out for loops!), symmetric decryption and out of band communication needed to collect everything needed to authorize. That's why existing libraries allow only limited subset (e.g. no third party caveats referencing other third party Macaroons), and if you're writing a library (as I did) there is a lot of reverse engineering (e.g. libsodium is used in most libraries for symmetric encryption).
There are also some small things like de facto implementations using slightly different operations than the paper and a custom binary format. JWT just uses JSON and base64. (For the record I'm not a big fan of JWT).
What I like in Macaroons is the ability to further confine permissions. Sadly PAST doesn't seem to have something like this instead opting for a "safe JWT" way.
One of the issues that I saw being discussed on the forums was precisely the lack of a standard format for caveats and even some suggestions to create one.
I think it's a very cool project but for some reason I don't think it has caught on. Do you think if someone came up with a suitable standard built it would see broader use? or what is your take on the lack of interest (IMHO) for this awesome idea?
Edit: Any way I could contact you to discuss this a bit more, if you are open to it? :)
As for caveats there are two forces at place: some want simple format ("X op Y") but there is another way that I've explored in a PoC - use simple stack-based script system (similar to Bitcoin Script [0]), then you can encode some really interesting properties inside your tokens (like requiring hashes of different properties, or signatures) so it would be kind of a meta-authorization scheme where you can delay the decision (e.g. require EC signatures for some sensitive operations). Of course this brings additional complexity but on the other hand using caveats in "X op Y" form doesn't bring any benefits over JWT claims.
[0]: https://en.bitcoin.it/wiki/Script
The ultimate reason why I abandoned Macaroons (after working for some prototypes and creating a JS library for them) is just the amount of complexity needed to work with them. And remember - code working with Macaroons is being executed before the request is authorized (that's what they are for) so this code need to be carefully audited and any bug can have severe consequences.
Compare that with JWT, you can write a verifier in simple code (JSON and base64 are built-in in any language) and simple is easier to audit. In Macaroons you first need to decode base64, parse custom binary format, check consistency (no cycles in third-party caveats), decrypt third-party keys. Moreover there can be multiple Macaroons for given ID, you need to check if at least one satisfies the request. Better - check all of them and then see if at least one works (to protect against side-channel attacks). So there is some inherent complexity in the entire stack. Removing it would require some substantial work. IMHO that's why they are not widely used. Oh, did I mention the existing libraries have some rather significant issues [1]?
[1]: https://github.com/nitram509/macaroons.js/blob/master/src/ma...
So to answer your question: I would gladly see some standarization effort, but it needs to be really thorough to have good effect. Unfortunately Macaroons are already plagued by old cruft (e.g. third-party caveats ID are called "cid" and first party caveats are also called "cid" but they are completely different) that no-one wants to touch not to break existing code.
If you don't mind we can keep the discussion here, it's good for others to see (I got into Macaroons because of one of these threads) and it's google-able :)
The best part of using JWTs is that you can validate without a central database. If you need a central database for sessions anyway you might as well store the claims in it.
Only disadvantage I could see would be performance.
If you want something that avoids storing all tokens, you can use a blacklist. You don't even have to check for revocation on any call - you could perfectly use short-lived (say 10 minute) access tokens and force frequent refresh using a refresh token and then only check the refresh token calls.
Whether you want to use it or not is a matter of making the right trade-offs. Stateful tokens are simpler to implement on the surface, but you have to keep in mind that the database lookup itself could be vulnerable to timing attacks.
Unfortunately, most database-based token implementations I've seen perform lookup based on the token string, instead of looking up the user and then checking all of the user's tokens, one by one.
And if you're not a small startup and actually have to handle loads north of 10,000 QPS (some of us do), these stateful tokens become quite expensive.
I personally think renewable, short-lived tickets/tokens are a better evil - accept that a compromised session is valid for 10 minutes (5+worst-case/accepted clock drift).
A long-lived certificate can encode authorization + but needs a short-lived ticket to be valid ("an I'd card that says three star general and today's pass phrase").
If my server-side application sends a JWT with a "good" algorithm, and disallows any other alg's, wouldn't that prevent attacks?
Why do we need a whole new implementation?
It's completely possible to do secure things with JWT, especially if you control every producer and consumer, but it's not guaranteed.
There is always going to be someone who hardcodes the root password into a public GitHub repo.
The problem with JWT is IMO largely that things became too easy, so people coded without thinking. I'm not sure that's easy to prevent. I don't blame the JWT spec for mistakes that are so obvious.
JWT is safe, as long as it's setup correctly, but safe-by-default is a better option.
That being said, I'm not going to swap out my JWTs with PASTs. I know what algorithm I'm using, why I'm using it, it is safe, and I'm verifying them properly.
PAST at least moves that to a clear text prefix in the vx.scheme pattern. Theoretically, that doesn't even stop it from having a v0.none or some other dumb algorithm such as JWT allows in a bad version suite, but it does at least mitigate against decryption attacks.
So yes, I appreciate secure and easy-to-use implementations of that idea, but always going for how insecure JWTs are, just because there are easy ways to do it wrong, is like telling everybody that password logins are bad because some people implemented them in flash.
> Why do we need a whole new implementation?
I think the problem which many people have with JWT is that is not strict enough and does not define certain things. PAST uses the same idea, but does not allow that wide variety of different algorithms we could use with JWT. In my eyes it makes it easier to use, because you do not have to search for implementations with compatible and secure algorithms but just for implementations using the latest version of PAST.
It does not. Unless you have specifically hardened your server to refuse to even try verifying tokens which use "bad" algorithms, a client can still present a key signed with one of those algorithms, and attempting to verify it may pose a risk.
Should I still be worried? I get that JWT's algorithm flexibility is overall a bad thing, but if I only allow one, should I continue to worry?
Here's why:
- Some bugs are about negotiation, e.g. key material misuse between RSA and HMAC schemes. They don't affect you, because you don't negotiate.
- Some bugs are about cryptographic implementation, such as not reusing nonces for ECDSA. They don't affect you, because _HMAC-SHA256_ doesn't have most of these problems.
- Some bugs are about specification issues, such as non-mandatory aud (audience) and exp (expiry). Audience shouldn't be a problem for you, because the only audience is you and there's only one secret key, so you get automatic audience restriction via cryptographic binding. Expiry, well, that's on you.
Why did you use JWT to begin with? (What does minting tokens buy you?)
"Why did you use JWT to begin with? (What does minting tokens buy you?)"
Absolutely no compelling reason apart from:
- Never want to roll my own auth, and there were already libraries in elixir and ember to work with JWT, so easy to cobble together
- The HS512 stuff seemed secure enough
- Impression that JWT is generally where things are headed (although I made this decision 2 years ago)
- I can embed some attributes in the token that can be read from the client side
- I liked the idea of authenticating without using a database query.
A lot of these things haven't borne out in the last two years. I still make database queries during auth, and I still retrieve user metadata from an API in my client side. So just to clarify, I'm not attached to it in some way (I never am, to technical decisions). I mainly want to know if I should prioritize moving away from it or not.
Still don't have a great solution for revoking tokens before they expire.
At least it's stateless :)
Unless you're saying "my server process itself is stateful, all the state lives in the database": in which case, yes, but the tokens bought you nothing. If you have random tokens and you store them in the database you have the same situation with no crypto to mess up.
And yes, I realize now that I could accomplish much the same thing without using JWT (a decision made some time ago, when everyone was raving about JWT), but I've got bigger priorities than ripping up my auth system (which to the best of my knowledge is working acceptably well) ATM.
But I do plan to take a look at it and perhaps migrate to something else in the future :)
Sometimes there's so much passion here around implementing cool new things that, while those things are important, it can make it easier to forget that simplicity, and better outcomes on average, are not in any way lesser technical advancements. Simplicity also requires good taste to boot imo.
On a side note from one of your posts, doesn't it make you chuckle a little to think "If you've already decided to implement Javascript Object Signing and Encryption (JOSE), whether you want JSON Web Tokens, JSON Web Encryption (JWE), or JSON Web Signatures (JWS), you should question this decision. You're probably making a mistake.", given the massive growth they've seen over 2-3 years in some very high profile cloud systems? But what to do...onward and upward then. :)
Finally I appreciate the dispassionate viewpoints, i.e. "I'm not attached to it in some way (I never am, to technical decisions)". Always to pleasure to work on hard problems and debate with folks who have adopted that perspective.
Anyway, well done.
I am just trying to build apps, I could care less what protocol is in use, as long as it protects the users. Over the last few days of research (including coming across this HN thread https://news.ycombinator.com/item?id=13865459 from a few months ago) I can't help but feel a) trapped into using JWT and b) that is probably the wrong thing to use and I am going to regret it.
(The list is here: https://github.com/paragonie-scott/public-projects/issues/6)
99.9% of that time was spent trying to come up with a better name/acronym, without success. I decided to just give it a plain/obvious name until a better one surfaced.
Novice-Proof Security Tokens: NPST
Just Verify Valid Tokens: JVVT
Safer Security Tokens: SST
Note: the first one is my only real suggestion, the rest are just for fun. And you are right, it is surprisingly difficult to come up with a good name.
You could also drop the use mapping: change 'sign' to 'public-auth' and explain that it's a 'sign' operation (a.k.a. digital signatures)
Edit: Good job on PAST and your other projects. I often follow your GitHub activity and publications to check on what interesting you are working currently.
The rest of the points (i.e. the problems with the JOSE standards) are what PAST seeks to solve. The "do not misuse" problem is more complicated, and if I were to add e.g. "do not use this for stateless sessions" at the top in big red letters, that will only tell developers "this is unsafe, keep using JWT instead".
That's a good point. Maybe a header in the readme/docs like "Stateless Sessions", followed by "Using PAST/JWT/etc. for stateless sessions is a terrible idea, because kittens will die needlessly and painfully [ obviously using an actual summary of why ]. Don't just take my word for it, here are some resources explaining further..."
(It's also the first link in the README for the project this Show HN is linking to, FWIW)
I found some additional reasons from a page that was linked from that last link here: http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-fo...
* They take up more space
* You cannot invalidate individual JWT tokens
The other reasons seem a bit weaker.In your opinion, are those also the reasons why you wouldn't use PAST for stateless sessions?
Yep
Just because this specifies a format, doens't mean it's just a format :)
GP: Basically PAST is just limiting your options down to things we think are secure combinations and eliminating things we know are insecure. However it does this with WHAT it puts in the JSON, not that it's JSON vs anything else. As you said that's just serialization.
The extreme example of this is XML DSIG and XML canonicalization in general.
More details here: http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-fo...
Shockingly, the advice I've seen to protect against this by folks like Auth0 is "keep your tokens expiration low" or not mention it at all.
I don't imagine PAST gets around this, as it's more like misinformation around the storage mechanism, but I think it's worth mentioning in any "how to use" section about PAST or JWT.
So I've opened an issue to address it before v1.0.0 is tagged: https://github.com/paragonie/past/issues/14
How does PAST solve this? Is it even possible to get secure stateless auth?