From 18209e7efd0dc94ea1082b472b8acf38ee3f590b Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Fri, 4 Apr 2025 11:49:47 +0200 Subject: [PATCH] wip: Phantom tokens --- .ltex/ltex.dictionary.en-US.txt | 3 ++ .ltex/ltex.hiddenFalsePositives.en-US.txt | 2 ++ config/_default/config.toml | 2 ++ content/blogs/phantom-token/index.md | 34 ++++++++++++++++++++++- go.mod | 2 +- go.sum | 2 ++ 6 files changed, 43 insertions(+), 2 deletions(-) diff --git a/.ltex/ltex.dictionary.en-US.txt b/.ltex/ltex.dictionary.en-US.txt index e97cf4c..c1b07fb 100644 --- a/.ltex/ltex.dictionary.en-US.txt +++ b/.ltex/ltex.dictionary.en-US.txt @@ -13,3 +13,6 @@ syscalls alloced webdev NaN +perf +kyoo +SPOF diff --git a/.ltex/ltex.hiddenFalsePositives.en-US.txt b/.ltex/ltex.hiddenFalsePositives.en-US.txt index cd96f15..940b5df 100644 --- a/.ltex/ltex.hiddenFalsePositives.en-US.txt +++ b/.ltex/ltex.hiddenFalsePositives.en-US.txt @@ -1,2 +1,4 @@ {"rule":"GAMEBOY","sentence":"^\\QI recently mentioned on Twitter that I made a gameboy game with some friends during my first year of college.\\E$"} {"rule":"YOUTUBE","sentence":"^\\QBtw if you're interested, checkout Retro Game Mechanics Explained on youtube, especially his SNES series which is phenomenal.\\E$"} +{"rule":"A_INFINITIVE","sentence":"^\\QThe API that enqueues the compute could return you a jwt allowing you to access progress/results of said task.\\E$"} +{"rule":"A_INFINITIVE","sentence":"^\\QThe API that enqueues the compute could return you a JWT allowing you to access progress/results of said task.\\E$"} diff --git a/config/_default/config.toml b/config/_default/config.toml index 93c2867..b353942 100644 --- a/config/_default/config.toml +++ b/config/_default/config.toml @@ -5,6 +5,8 @@ googleAnalytics = "G-KK12E7TNEC" enableEmoji = true titleCaseStyle = 'none' +ignoreFiles = [".*/node_modules/.*"] + [pagination] pagerSize = 50 diff --git a/content/blogs/phantom-token/index.md b/content/blogs/phantom-token/index.md index 1998ce8..f18fc67 100644 --- a/content/blogs/phantom-token/index.md +++ b/content/blogs/phantom-token/index.md @@ -1,9 +1,41 @@ --- -title: "Phantom token" +title: "Jwt should not be persisted" description: "" date: 2025-03-26 draft: true tags: [] --- +It's easy to find online resources talking about the merits of JWT. You'll read stuff like "it's better for horizontal scaling", "it's better for perf since you don't need to hit the db on every request" or how it has better security. +Most of those resources either only talk about auth on a surface level or will introduce workarounds for JWTs shortcomings that negate its advantages. + +# A story about state + +The main benefits of JWT is that the token is stateful, so we can deduce the user's permissions without having to hit the db or an auth server. This is extremely valuable in a microservice context, without a JWT you'll have to ask db 50 times if you have 50 services. + +The biggest disadvantage is that the token is stateful. This means the token will drift-offs. If your user gains or loses permissions, is banned or revoked their session, the JWT is still valid and has the permissions at the time of creation. + +To mitigate those issues, some people will introduce deny-lists of JWT that should not be accepted by your servers. This re-introduces the initial problem of session: making a db call on each request (and on every service.) + + +# Single use JWTs + +Instead of creating sessions on top of JWTs, we can embrace what JWTs are good at: proving who you are & your permissions over something that doesn't change over time or that expires very quickly. + +For example, you could imagine an API that would compute something over a long period of time (say a week.) The API that enqueues the compute could return you a JWT allowing you to access progress/results of said task. +This simplifies auth handling for the compute service that now only has to verify the JWT & you have no risk of your permission changing or being revoked: the JWT only grants you access to a single compute that you started. + +# JWTs in microservices + +As stated previously, JWTs truly shines in microservices **as long as** you don't need to check for token invalidation on each service. There's a neat way to get this that I implemented recently for [kyoo's v5](https://github.com/zoriya/kyoo): phantom tokens! + +The concept is simple: +- use traditional sessions when communicating with the client +- use JWT when communicating across services +- when a user makes a request, have the gateway convert the session (after checking its validity) to a JWT + +You get the benefits of JWT (aka no call to db/auth service in every service) while having traditional sessions in the user's perspective (so no manual token refresh needed, no out-of-sync permissions & no token valid after session invalidation). +The main cons of this method are a SPOF on your auth service & bringing some logic to your gateway (especially for kyoo because for k8s releases we want to allow users to choose their gateway. Sorry @acelinkio :p) + + diff --git a/go.mod b/go.mod index eb4ebeb..1669aad 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,4 @@ module github.com/zoriya/blog go 1.21.7 -require github.com/nunocoracao/blowfish/v2 v2.78.0 +require github.com/nunocoracao/blowfish/v2 v2.84.0 diff --git a/go.sum b/go.sum index 8f8e1a0..9f6f219 100644 --- a/go.sum +++ b/go.sum @@ -4,3 +4,5 @@ github.com/nunocoracao/blowfish/v2 v2.75.0 h1:tCfhpeTmBcDqLy4JBEYfrQw/Ou24ZVAcic github.com/nunocoracao/blowfish/v2 v2.75.0/go.mod h1:4SkMc+Ht8gpQCwArqiHMBDP3soxi2OWuAhVney+cuyk= github.com/nunocoracao/blowfish/v2 v2.78.0 h1:rPNg+RGMpLwlOAhdlYUAGdUMxTVwhkZH8VrDnt+WGvs= github.com/nunocoracao/blowfish/v2 v2.78.0/go.mod h1:4SkMc+Ht8gpQCwArqiHMBDP3soxi2OWuAhVney+cuyk= +github.com/nunocoracao/blowfish/v2 v2.84.0 h1:WA/3+AD/2XRYhH7hJyjscQqJmRtuGrTfkIaSf6lvQvs= +github.com/nunocoracao/blowfish/v2 v2.84.0/go.mod h1:4SkMc+Ht8gpQCwArqiHMBDP3soxi2OWuAhVney+cuyk=