Instead of suggesting paseto, auth0 blog clearly says how to mitigate the vulnerability by using kid and specifically mentioning which algorithm during validation. I think most of the implementation do this way.
> You should really consider not using JWT for new designs that don't a priori need to interop with JWT.
If you're trying to make the argument that because they can be insecure, we should not use JWTs. Thats not really a great argument for most people. JWTs provide a lot of value, and the idea of having some secure, validatable, and no network required check for authentication, or transporting information. Is too valuable for businesses. So we all use JWTs, they are a decent standard.
At the very least you should propose an alternative that people use besides JWTs if you're going to vaugly hand wave about the scary security issues of 2021 firebase, and 2020 Npm packages reported by Auth0.
Just as an aside but I would never say this, this is why people hate security teams. I'm a security 'expert' with 15+ years in the industry including speaking at DEFCON, Blackhat, and all that.
I had no idea about these issues and have never heard of PASETO until now! I'm actually a few months in into my startup and we are using JWT for a lot of stuff so this is very relevant. Thanks for sharing! But if I can't keep up with everything then devs who don't do this all day simply cannot.
it's not common knowledge in hn because 99pct here is stuck with jwt, which only exist to sell auth SaaS subscriptions to people coding on nodejs, were the middle ware to habdle auth cannot talk to a database. it's crazy.
I built something similar for Neon[1]. We went with the route that the user sessions for JWT RLS had very few privileges, and that the context was managed by our ingress/connection pool. In our case, all incoming queries had to come via our sql-over-http interface, but that was mostly just to reduce scope rather than being integral to the security.
The general idea is that the connection pool ingress is trusted to provide the context properly, but the client is not. The pool would generate a random JWK for each connection and each request would use a newly signed JWT and the token ID is strictly monotonic, which makes any attempts for the client to smuggle their own token contexts in near impossible.
The JWTs the pool signs for each transaction will contain the claims that were correctly validated from the client.
A `DISCARD ALL` before returning the connection to the available pool will clear the context so it cannot be re-used and a new context must be provided fresh.
I did something similar about 20 years ago, although not using JWT.
The application supplied a session token when first querying the database. The database would make a call to the authentication server to verify it and obtain the roles associated with that session. If it had not seen that combination of roles before, it would build and cache access tables for them (needed for performance when using views for row level security). Then any further queries using that token were fast. This also worked with connection pooling.
It had some rough edges; we had to run periodic cleanup jobs to remove stale cached access tables and tokens. And even with them, enforcing row level security consumed about 30% of the database server performance!
But, it did work and remained in service for about 7 years. Eventually, they replaced it with something much simpler. I had left and nobody understood it anymore. Which I guess is a separate issue about doing unusual things with tech...
We do something similar except we use an existing OAuth flow and simply add custom attributes to the authorization token. That authorization token is then sent along with requests to various services and these attributes are picked out and then used to apply policies or output filtering as appropriate.
As a suggestion I would look to name the properties of your current token in such a way where they could be compatible with the embedded case.
https://github.com/tvondra/jwt_context/blob/10be23c0651f1099...
https://github.com/tvondra/jwt_context/blob/10be23c0651f1099...
https://github.com/tvondra/jwt_context/blob/10be23c0651f1099...
Oh look, the typical setup for a classical JWT vulnerability.
Prior art:
https://auth0.com/blog/critical-vulnerabilities-in-json-web-...
https://github.com/firebase/php-jwt/issues/351
You should really consider not using JWT for new designs that don't a priori need to interop with JWT.
PASETO is less likely to create sadness: https://paseto.io
Instead of suggesting paseto, auth0 blog clearly says how to mitigate the vulnerability by using kid and specifically mentioning which algorithm during validation. I think most of the implementation do this way.
The auth0 blog recommends an incomplete mitigation.
The correct fix is to never trust the header for which algorithm you're using.
https://infosec.exchange/@sophieschmieg/115132001021790785
Aside: this was very informational for me, thanks!
> You should really consider not using JWT for new designs that don't a priori need to interop with JWT.
If you're trying to make the argument that because they can be insecure, we should not use JWTs. Thats not really a great argument for most people. JWTs provide a lot of value, and the idea of having some secure, validatable, and no network required check for authentication, or transporting information. Is too valuable for businesses. So we all use JWTs, they are a decent standard.
At the very least you should propose an alternative that people use besides JWTs if you're going to vaugly hand wave about the scary security issues of 2021 firebase, and 2020 Npm packages reported by Auth0.
> At the very least you should propose an alternative that people use besides JWTs
PASETO: https://paseto.io
I thought this was common knowledge on HN?
> if you're going to vaugly hand wave about the scary security issues of 2021 firebase, and 2020 Npm packages reported by Auth0.
These are issues caused by the JWT standard.
https://paragonie.com/blog/2017/03/jwt-json-web-tokens-is-ba...
> I thought this was common knowledge on HN?
Just as an aside but I would never say this, this is why people hate security teams. I'm a security 'expert' with 15+ years in the industry including speaking at DEFCON, Blackhat, and all that.
I had no idea about these issues and have never heard of PASETO until now! I'm actually a few months in into my startup and we are using JWT for a lot of stuff so this is very relevant. Thanks for sharing! But if I can't keep up with everything then devs who don't do this all day simply cannot.
Okay fair. I just see it come up in every thread about JWT security, so I felt like I would be Captain Obvious for calling it out.
it's not common knowledge in hn because 99pct here is stuck with jwt, which only exist to sell auth SaaS subscriptions to people coding on nodejs, were the middle ware to habdle auth cannot talk to a database. it's crazy.
The JWT standard is known to be full of nonsense. Acting like this is some non-issue is hilariously disconnected from reality.
I built something similar for Neon[1]. We went with the route that the user sessions for JWT RLS had very few privileges, and that the context was managed by our ingress/connection pool. In our case, all incoming queries had to come via our sql-over-http interface, but that was mostly just to reduce scope rather than being integral to the security.
The general idea is that the connection pool ingress is trusted to provide the context properly, but the client is not. The pool would generate a random JWK for each connection and each request would use a newly signed JWT and the token ID is strictly monotonic, which makes any attempts for the client to smuggle their own token contexts in near impossible.
The JWTs the pool signs for each transaction will contain the claims that were correctly validated from the client.
A `DISCARD ALL` before returning the connection to the available pool will clear the context so it cannot be re-used and a new context must be provided fresh.
[1] https://github.com/neondatabase/pg_session_jwt/
I did something similar about 20 years ago, although not using JWT.
The application supplied a session token when first querying the database. The database would make a call to the authentication server to verify it and obtain the roles associated with that session. If it had not seen that combination of roles before, it would build and cache access tables for them (needed for performance when using views for row level security). Then any further queries using that token were fast. This also worked with connection pooling.
It had some rough edges; we had to run periodic cleanup jobs to remove stale cached access tables and tokens. And even with them, enforcing row level security consumed about 30% of the database server performance!
But, it did work and remained in service for about 7 years. Eventually, they replaced it with something much simpler. I had left and nobody understood it anymore. Which I guess is a separate issue about doing unusual things with tech...
PostgREST has been doing this for a long time https://docs.postgrest.org/en/v13/references/auth.html#jwt-b...
We do something similar except we use an existing OAuth flow and simply add custom attributes to the authorization token. That authorization token is then sent along with requests to various services and these attributes are picked out and then used to apply policies or output filtering as appropriate.
As a suggestion I would look to name the properties of your current token in such a way where they could be compatible with the embedded case.