tags : OAuth (Open Authorization)
FAQ
History
- First draft in 2012
- Final draft in 2015 : https://datatracker.ietf.org/doc/html/rfc7519
What JWT does differently than Web Sessions?
- Instead of an
opaque token
in a Cookie, we actually embed theuser_id
itself butsigned
. - The
signature
can only be generated by the server which has access to asecret
signature
=secret + payload + header
- When we send the JWT, we send the
signature + payload + header
. This way, if any ofpayload
orheader
is tampered,signature
won’t match. - The usecase is somewhat different too, think
stateless
v/sstateful
- More importantly, Web Sessions are very tightly knit with Cookies, whereas JWTs are not. While it’s a safe practice to store JWT in Cookies, it doesn’t have to be that always, depending on usecase, client can store JWT in memory, session-storage, others etc.
Example of a scene where JWT useful (Need to verify :))
- I made this up, idk if makes sense or is correct
- S:Server,C:Client,R:Resource
S
wants to giveC
access toR
R
does not trustC
.R
trustS
.S
will sign a token(jwt) and send it toC
,C
then use it to accessR
.R
will comply because, it sees that oh, this is approved byS
- Usually the
token(jwt)
is stored in a Cookie and with settings that allows it to be passed toR
. But in certain cases,token(jwt)
might be stored elsewhere and our application logic can make use of it.
S1 and S3 don’t trust each other but both trust S2, but how does S2 trust S1&s3 are legit servers asking for JWT
I am not 100% sure of this answer but guess this is where pre-shared keys/ mTLS comes in
What
- JWT is a format of a token.
- Signed but non-opaque, Web Sessions are opaque tokens
- Defines a container to transport data between interested parties.
- JWT is independent of OAuth (Open Authorization) and OIDC (OpenID Connect)
Concerns
Lot of blogposts on the internet bashing JWT, this is mostly about how often JWT gets misused and not flaw of JWTs itself. The following is just summary from the famous owasp cheetsheet.
Logging out
- This was what was mention in using JWT for stateful stuff. (Not recommended)
- If you really want to do it, here’s an idea from someone: “My favourite solution to this is keep a global list of JWTs that have been revoked before they expired (and remove the tokens after expiry). Instead of letting webservers hit a server to get this list, push the list to each server using a pub/sub mechanism.”
None hashing
- Some JWT libs consider tokens signed with
none
as valid. (BAD) - Sol
- Just use a proper JWT lib
- VAlidate the algorithm is what we expected it to be server side per req.
Token Sidejacking
Token got stolen, impersonation.
The idea is to basically add an user context
(Basically something that the only original user can have). i.e Even if they’re able to steal the JWT token somehow, they won’t be able to steal the user context
token from the hardened cookie.
tbh, this seems like reimplementation of Web Sessions to me, We cannot revoke stuff like in sessions
but with this we can sorta validate but this becomes more prominent when you think that JWT’s are not always meant to be stored in Cookies, in that sense a hardened user context
cookie can provide protection against XSS and hence prevent stealing as described below.
- We can use IP address for the
user-context
, but that’s not a great idea because it can change - Turns out,
a random string+strict cookie
is good enough. Let’s called it theSecure Fingerprint (Secure-Fpg)
cookie. ThisSecure-Fpg
is ouruser context
Client side
- Generate a random string(SHA256), put the raw value of this string into a Hardened Cookie
- Additionally, for the hardened cookie set
Expires
=None
, so that cookie is cleared when the browser is closed.Max-Age
<= value of JWT token expiry (never more)
- This becomes out
Secure-Fpg
. i.euser context
=Secure-Fpg
=raw random string+cookie
- Additionally, for the hardened cookie set
- In the actual JWT token, add a
hash
of theraw random string
. We can send the JWT token as a Cookie or however we desire.
Server side
- On the server side, we keep track of
Secure-Fpg
that we send. (Similar to Web Sessions) - On validation, we check the
user context
cookie against saveduser contexts
- Then we again calculate the hash for the
raw random string
- Then we verify the hash against the hash in the JWT token.
Token Information Disclosure
- JWT token data is base64 encoded but not encrypted
- We can use symmetric encryption if we want to here
Weak Token Secret
- If using weak secret for HMAC
- Attacker can take the JWT and then run an offline attack on it
- This will allow them to resign tokens
Usecases
Stateful application
- See Cookies and Web Authentication
- Use of JWTs for
stateful session management
is 99% of the time BAD, because JWT are designed to be stateless. - JWT is used by an application to allow a client to present a token representing the user’s “identity card” to the server and allow the server to verify the validity and integrity of the token in a secure way. (All this happens in a stateless way)
- Individual stateless JWT tokens cannot be invalidated.
- If you need (logout/access revocation etc), stateless would not work, you’ll need server side state. Just deleting the secure http-only cookie will just delete the token but not really invalidate it.
- You can use client side logic to enforce this or maybe change the jwt secret on the server!
- At this point you might as well use traditional stateful opaque sessions
Stateless application
- Short term authorization tokens
- Great for short term authentication between decentralized systems. Eg. 5 minute expiration between a web api and a websocket service.
- JWTs are good for API tokens
- Web Sessions on frontend, JWT on backend for service to service communication.
- JWT, when implemented well in stateless application can be a good candidate
- Handy in a distributed system or inside a trusted environment also. User-actions may cause requests to several http-endpoints(Microservices) that all have to somehow individually verify the authentication. In this case JWT can help not needed all these to have access to the Web Sessions data store, this become simple as the token will be signed by a trusted entity that the different services trust and they just need to have it’s public key(See PKI).
- See Ways to do it section
- Another example of stateless session using encrypted cookies: vvo/iron-session
Ways to do it
Auth
Use of JWT for Auth means using JWT for stateful stuff mostly which i am not super convinced of
Send it via Cookies
- Cookie Hardening
- Backend w proper CORS policy
Send it via HTTP Bearer token with TLS
- This is what applications which are not Browsers do afaik
- Can be vulnerable to XSS
Info exchange/delegation of access
Sent it in API response and let client decide
- Since the token is signed, we can just send it.
- The client can decide how they want to use it, this is more useful in the usecase of “Information Exchange” compared to Authentication.
Use on OIDC (OpenID Connect)
- OIDC does not mandate the use of JWT as the
ID token
(JAR) /access token
- In fact there’s no structure defined for the token, but using JWT has benefits.
- But OIDC tokens are transparent unlike OAuth(opaque tokens), So JWT fits!
- Allows other flows (hybrid or implicit) to be used.
- Good library support
- Can hold payload
- Signed token, so the RP can still trust it even though it’s been received via an untrusted channel.