tags : OAuth (Open Authorization)

FAQ

History

What JWT does differently than Web Sessions?

  • Instead of an opaque token in a Cookie, we actually embed the user_id itself but signed.
  • The signature can only be generated by the server which has access to a secret
    • signature = secret + payload + header
  • When we send the JWT, we send the signature + payload + header. This way, if any of payload or header is tampered, signature won’t match.
  • The usecase is somewhat different too, think stateless v/s stateful
  • 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 give C access to R
  • R does not trust C. R trust S.
  • S will sign a token(jwt) and send it to C, C then use it to access R.
  • R will comply because, it sees that oh, this is approved by S
  • Usually the token(jwt) is stored in a Cookie and with settings that allows it to be passed to R. 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

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 the Secure Fingerprint (Secure-Fpg) cookie. This Secure-Fpg is our user 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.e user context = Secure-Fpg = raw random string+cookie
  • In the actual JWT token, add a hash of the raw 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 saved user 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

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.