Published on

# Let’s stop using JWTs client side

Authors

OAuth2, OIDC, and their foundation, the JWT, has been an industry standard for many years, with no sign of slowing down.

There are two types of access tokens in the OAuth flow, opaque and JWT (JWS more precisely). The problem with latter is the inherent leakiness. There is a massive debate amongst the community — where some consider JWT for auth as insecure as it leaks information (by b64 decoding the body), others argue that you shouldn’t put sensitive info in there at all.

Introduce: the split token flow comes in, a solution that satisfies both camps.

This flow suggests to use the signature of the JWT access token on the client side, and storing the header and claims of the JWT server side. Thus, we get the flexibility of JWTs by being able to store session information in JWT claims, and we get the security of an Opaque access token.

That's really it. There are some IAM solutions shouting about it as well, such as Curity.

Here's a link to a guide that shows a real world example implemented with Tyk.

$curl https://my-auth-server/auth/realms/tyk/protocol/openid-connect/token \ -d grant_type=client_credentials \ -d client_id=efd952c8-df3a-4cf5–98e6–868133839433 \ -d client_secret=0ede3532-f042–4120-bece-225e55a4a2d6 { "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJlbWFpbCI6ImhlbGxvQHdvcmxkLmNvbSJ9.EwIaRgq4go4R2M2z7AADywZ2ToxG4gDMoG4SQ1X3GJ0", "expires_in":300, "not-before-policy":0, "scope": "email profile", ... }  So here we get a JWT access token back: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJlbWFpbCI6ImhlbGxvQHdvcmxkLmNvbSJ9.MEwIaRgq4go4R2M2z7AADywZ2ToxG4gDMoG4SQ1X3GJ0  We can plug that into jwt.io and see the Base64 decoded payload: Clearly, the access token can contain sensitive information that we don’t want to leak. ## Split Token Flow The split token flow adds an API gateway or service such as Tyk in the middle that does the following: 1. Service/API Gateway receives the request from client 2. forwards it the IAM solution & receives the access token 3. Splits it, returning the signature to the client only, and storing in a local cache/key value store, where the key is the signature and the value is the whole JWT So the request now looks like this: $ curl http://api-gw.com/auth/token \
-d grant_type=client_credentials \
-d client_id=efd952c8-df3a-4cf5–98e6–868133839433 \
-d client_secret=0ede3532-f042–4120-bece-225e55a4a2d6

{