paragonie / paseto

Platform-Agnostic Security Tokens
https://paseto.io
Other
3.23k stars 108 forks source link

body and footer questions #83

Closed veqryn closed 2 years ago

veqryn commented 6 years ago

I became interested in your paseto standard after feeling a bit uneasy about JWT's, but I have a few questions and wasn't sure how else to ask but to make a github issue (feel free to add the answers to your documentation).

  1. Is the body and its claims always encrypted? If not, when it is it not encrypted?

  2. Is the footer always unencrypted?

  3. Is the footer signed?

  4. If you want the website frontend to see certain claims or data, would you advise putting that in a json objected in the footer, instead of into the body?

  5. Is the footer validated against anything? Or is it just a grab bag of whatever I want to put in it, including nothing?

  6. Which claims are "built into the standard" and are expected to be validated or read by the implementing libraries?

  7. Should Paseto be used for sending session id's and non-confidential data about the user to the website frontend, to be stored in secure cookies? (ie: what most people use JWT's for)

paragonie-scott commented 6 years ago
  1. Is the body and its claims always encrypted? If not, when it is it not encrypted?

As documented here, the body is encrypted for v1.local, v2.local, ...

Local-scoped tokens means that the issuer is also the verifier, and you're storing encrypted data.

Public-scoped tokens means that the issuer is a third party, and therefore the contents are only needed to be signed.

  1. Is the footer always unencrypted?

Yes.

  1. Is the footer signed?

Yes, it is always authenticated.

  1. If you want the website frontend to see certain claims or data, would you advise putting that in a json objected in the footer, instead of into the body?

From the documentation:

Thus, if you want unencrypted, but authenticated, tokens, you can simply set your payload to an empty string and your footer to the message you want to authenticate.

Conversely, if you want to support key rotation, you can use the unencrypted footer to store the Key-ID.

If you want data to be unencrypted, but signed, in a local-only environment, you can dump everything in the footer and the payload can be empty.

  1. Is the footer validated against anything? Or is it just a grab bag of whatever I want to put in it, including nothing?

For local tokens, it is included in the authentication tag attached to the ciphertext. For public tokens, it's included in the signature calculation. This prevents attacks based on footer truncation or malleability.

However, beyond that, you can do whatever you want with it.

  1. Which claims are "built into the standard" and are expected to be validated or read by the implementing libraries?

This was being documented in the RFC draft. The Markdown source is available online, but at some point the compiled .txt output was erroneously removed from the Git repository. (Note to self: Re-add this.)

I've copied the table below in case the RFC changes so you can have a point-in-time copy for future reference:

Registered Claims

The following keys are reserved for use within PASETO. Users SHOULD NOT write arbitrary/invalid data to any keys in a top-level PASETO in the list below:

Key Name Type Example
iss Issuer string {"iss":"paragonie.com"}
sub Subject string {"sub":"test"}
aud Audience string {"aud":"pie-hosted.com"}
exp Expiration DtTime {"exp":"2039-01-01T00:00:00+00:00"}
nbf Not Before DtTime {"nbf":"2038-04-01T00:00:00+00:00"}
iat Issued At DtTime {"iat":"2038-03-17T00:00:00+00:00"}
jti Token ID string {"jti":"87IFSGFgPNtQNNuw0AtuLttP"}
kid Key-ID string {"kid":"stored-in-the-footer"}

In the table above, DtTime means an ISO 8601 compliant DateTime string. See [#keyid-support] for special rules about kid claims.

Any other claims can be freely used. These keys are only reserved in the top-level JSON object.

The keys in the above table are case-sensitive.

Implementors (i.e. library designers) SHOULD provide some means to discourage setting invalid/arbitrary data to these reserved claims.

For example: Storing any string that isn't a valid ISO 8601 DateTime in the exp claim should result in an exception or error state (depending on the programming language in question).

We prefer ISO 8601 over UNIX Timestamps because of i18n and timezone issues.

  1. Should Paseto be used for sending session id's and non-confidential data about the user to the website frontend, to be stored in secure cookies? (ie: what most people use JWT's for)

See Was "Stateless Session Tokens" one of Paseto's Design Goals? from the documentation.

veqryn commented 6 years ago

Thanks for the answers. I have a clarification to ask and a couple more questions:

Should Paseto be used for sending session id's and non-confidential data about the user to the website frontend, to be stored in secure cookies? (ie: what most people use JWT's for)

See Was "Stateless Session Tokens" one of Paseto's Design Goals? from the documentation.

Question 7 above was actually about stateful session tokens. Right now we are using JWT's to store what is basically a session id and some non-confidential data about the client that is useful to the front end browser. The id is just a key-id or jid that looks up a key and a reference to the customer in a table. The other data includes the customer name, id, audience, etc. The JWT gets stored in secure cookies. Is this a good application for Paseto to replace JWT in?

Is the body and its claims always encrypted? If not, when it is it not encrypted?

As documented here, the body is encrypted for v1.local, v2.local, ... Local-scoped tokens means that the issuer is also the verifier, and you're storing encrypted data. Public-scoped tokens means that the issuer is a third party, and therefore the contents are only needed to be signed.

Why are local-scoped tokens always encrypted, and public-scoped tokens unencrypted? Wouldn't it make more sense to have both an encrypted section (you call it the body right now) and an unencrypted section (you call it the footer currently) for both local and public tokens? There is no reason why a public token couldn't use asymmetric encryption on the body, and I'm sure some people would want that.

I also feel it would make more sense to call them symmetric and asymmetric tokens (ie: v2.sym.<...>, and v1.asym.<...>), as the words local and public can be a bit misleading.

Is the footer validated against anything? Or is it just a grab bag of whatever I want to put in it, including nothing?

For local tokens, it is included in the authentication tag attached to the ciphertext. For public tokens, it's included in the signature calculation. This prevents attacks based on footer truncation or malleability. However, beyond that, you can do whatever you want with it.

Right now the body is JSON, while the footer is just whatever. I highly suggest for v3 that you make the footer mandatory JSON as well. One of the biggest things I see people using JWT's for is adding additional claims to be read by the browser. Having the footer be JSON will make that a lot easier!

Can I also suggest that those validated registered claims be allowed to appear in the footer instead of the body? In other words, the implementations should look for those claims (ex: exp) in the body, and if any aren't there then it also looks for those claims in the footer.

thanks!

paragonie-scott commented 6 years ago

Is this a good application for Paseto to replace JWT in?

Neither standard was designed for this use-case, and it's dangerous to use JWT this way. At least with PASETO you can reduce your risk to protocol vulnerabilities, but the fundamental lack of revocation is still a problem.

Why are local-scoped tokens always encrypted, and public-scoped tokens unencrypted?

Because for a local-scoped token (i.e. the issuer is the verifier), where the end user is basically a data mule for an opaque ciphertext blob, it makes sense to encrypt.

For claims signed by a third party, adding public-key encryption adds a ton of overhead to the protocol. How do you ensure the third-party uses the correct public key? Do you sign-then-encrypt, or encrypt-then-sign?

If we wanted to solve the 100% problem, sure, we could bolt public-key encryption into the protocol, but almost nobody needs it.

paragonie-security commented 2 years ago

Public-key encryption is solved in PASERK.