Yeah, I don't want to disturb the upper
# spicedb
k
Yeah, I don't want to disturb the upper thread, so I'll start a new one, but the question is quite related. How should we work with
zedtoken
in a microservice architecture when permissions are granted/revoked by admins? For granting permissions, there is no big problem. You can grant the permission in one service and eventually send the
zedtoken
to another service or store it in a DB. It is acceptable if the user gets access a couple of seconds later. But what happens when we remove/revoke a permission? Revoking a permission should ideally take effect immediately. Imagine an admin revokes a user's permission in one service/pod. We then need to propagate the corresponding
zedtoken
to the service handling the user's queries as quickly as possible. If everything is handled within one microservice, we have the problem of storing the
zedtoken
in two databases (SpiceDB and our DB). Potentially, we could lose the latest
zedtoken
if our DB transactions fail. If the permission management and user queries are handled by different microservices, we have the same persistence problem, plus eventual consistency. We need to somehow transfer the
zedtoken
to another microservice, which could take some time depending on the implementation (Kafka, etc.). So, in this case, understanding whether a relation was deleted by an admin is not immediately possible unless we use
fully_consistent
for such queries. Am I missing something here? Is there a recommended pattern for handling
zedtoken
propagation in this kind of architecture, especially when permission revocation needs to take effect immediately? Thanks in advance.
y
is your system synchronous or eventually consistent? how do you currently handle dual writes when a request spans services?
k
Yeah, thanks for the answer. It depends. Part of our system is synchronous, but another is eventually consistent. We solve dual writes in a different way, but mostly with the outbox pattern.
y
that's similar to what we did at my old job
and that means that your system is eventually consistent for the most part
at my old job, access modifications were recorded in an admin service, and then that admin service wrote outbox messages that were picked up by the wrapping service for SpiceDB and then written to SpiceDB
is this about compliance requirements or something?
k
Thanks! What you wrote is correct, and I don't have any objections. What I'm trying to understand is this. Imagine your system is under attack and someone's JWT tokens have been stolen. You need to revoke that user's permissions immediately. With eventual consistency, you'll eventually propagate the new ZedToken. But imagine the outbox is down, or it's heavily delayed because of an attack or extreme load. In that case, the service performing authorization checks won't know about the latest ZedToken during read operations. It will have to wait until the ZedToken is delivered, or until the datastore-revision-quantization-interval expires before it starts seeing the updated permissions. How would you handle this scenario?
Or maybe I misunderstood something and got some concept wrong.
What I currently see is that for critical components, where permissions can be revoked, we always need to use
full_consistency
to ensure the latest state is read immediately. On the other hand, when we're granting permissions, using a ZedToken seems sufficient, since it's usually acceptable if access becomes available a little later. This wording makes the distinction between revocation (security-critical) and granting (latency-tolerant) much clearer.
y
are you referring to the new enemy problem?
like the idea that a user shouldn't be able to see anything post-revocation?
or are you concerned about the speed at which a request to revoke reaches SpiceDB?
k
> are you referring to the new enemy problem? > like the idea that a user shouldn't be able to see anything post-revocation? Yeah, sorry for confusing, I am probably about this one. Performance of SpiceDB is not a question. The question is how to immediately see revoked permissions if we are using ZedToken.
y
so one of the keys here is that if someone's permission is revoked, but they're using a zedtoken that lets them see a cached result, they aren't seeing anything new
like if someone makes a request to your web server and gets to see something in their browser, and you revoke their access but they still have the tab open, they'll continue to see whatever that information was
but if that information changes, they aren't going to be able to get any new information
it doesn't guarantee that the next request fails, but it does guarantee that the user won't be able to see anything that changed after the revocation
k
Yeah, for sharing photos if you already see them or sharing some documents if you saw them, it is probably okay. But, for example, if you restrict admin ability to approve withdrawals, it is a bit of a different kind of problem.
You probably want immediately to see this
y
right
so a withdrawal is something you're checking on the account, right?
when you revoke the access, you update the account's row with the zedtoken associated with that revocation
then when someone goes to make a withdrawal, the account row is fetched, and then the permission check is made with that zedtoken, which will reflect the revocation
if you're asking about how to ensure that the zedtoken gets back onto the account row in a timely fashion after the revocation, that's going to be an architectural decision within your application
k
Yes, that's exactly the question. It seems that it's technically impossible to propagate a ZedToken without some delay, so the only solution for these security-critical cases is to use
full_consistency
. No matter which pattern you choose, you end up with the same fundamental problem: you're writing to two different data stores. You first call
DeleteRelation
in SpiceDB and receive a ZedToken, and then you somehow need to persist or propagate that token. Whether you use an outbox, Kafka, or any other approach, there will always be a window where the token hasn't been stored or delivered yet, because those operations can't be performed atomically.
y
yeah, that's true. we have kicked around the idea of a zedtoken jar internally, where there's a layer of abstraction that lets you refer to a zedtoken via an ID or set of IDs, and changes that involve those IDs bump a cached revision such that the next request that references those IDs (by ID, rather than by zedtoken) picks up the most recent revision
but it isn't something we've started work on yet
it's also potentially something that you can do in your own application, but you'd still have the eventual consistency question, i think
k
Yes, I think so. Many thanks, @yetitwo! This conversation helped clarify things for me, and I now feel confident that I wasn't missing any key concepts on this topic. Thanks again for taking the time to answer my questions! Need to think a bit about this 🙂
y
sure thing!
5 Views