We talk about this in our design principles [1]. But I'll give you a summary here too. We often use GitHub as an typical use case [2].
In GitHub you might be able to merge a PR in a repository because you are the repo owner, or you were invited to it. Or because you're an organization admin, and the repo is in the same organization. (These are all common scenarios in b2b saas apps).
When a user attempts to merge a PR (or hits the API) you need to make that authorization decision based on what the application knows about the user.
So how do you allow the policy to access this information? Your options are basically: (a) you make it possible for the policy engine to independently lookup the data. You are now building a distributed monolith, since any change to the data requires updating both the policy engine and the application. (b) You send the relevant data into the policy decisions. Knowing what data you need to send to the policy is another form of coupling.
OPA is sort of a combination of (a) and (b). There is an API for sending authorization data to it, and you can also send data along with a request.
The problem is that the line between authorization and business logic is _so blurry_. Me being a member of a github org is fundamental application logic. But also crucial to making authorization decisions.
Because of this, traditionally people write this logic as a part of the application code. Normally a bunch of `if` statements. This is hard logic to abstract well in an app, because it's normally a bunch of conditionals and a decision flow. Which it turns out prologs/logic-based languages are great at solving (same conclusion OPA folks reached).
So given all this, the balance we wanted to strike was: decoupling the logic, but not the data. If your app already defines what a User is, what a Repository is, how a User becomes a Member of a Repository, then write your policy over those things, instead of re-implementing all of that logic elsewhere.
That being said, there are cases where the OPA-style decoupling works fine since there isn't the same kind of business logic/authz logic distinction. Or where the decision is being made over the entire input by default (things like checking terraform files, or other infra use cases).
In GitHub you might be able to merge a PR in a repository because you are the repo owner, or you were invited to it. Or because you're an organization admin, and the repo is in the same organization. (These are all common scenarios in b2b saas apps).
When a user attempts to merge a PR (or hits the API) you need to make that authorization decision based on what the application knows about the user.
So how do you allow the policy to access this information? Your options are basically: (a) you make it possible for the policy engine to independently lookup the data. You are now building a distributed monolith, since any change to the data requires updating both the policy engine and the application. (b) You send the relevant data into the policy decisions. Knowing what data you need to send to the policy is another form of coupling.
OPA is sort of a combination of (a) and (b). There is an API for sending authorization data to it, and you can also send data along with a request.
The problem is that the line between authorization and business logic is _so blurry_. Me being a member of a github org is fundamental application logic. But also crucial to making authorization decisions.
Because of this, traditionally people write this logic as a part of the application code. Normally a bunch of `if` statements. This is hard logic to abstract well in an app, because it's normally a bunch of conditionals and a decision flow. Which it turns out prologs/logic-based languages are great at solving (same conclusion OPA folks reached).
So given all this, the balance we wanted to strike was: decoupling the logic, but not the data. If your app already defines what a User is, what a Repository is, how a User becomes a Member of a Repository, then write your policy over those things, instead of re-implementing all of that logic elsewhere.
That being said, there are cases where the OPA-style decoupling works fine since there isn't the same kind of business logic/authz logic distinction. Or where the decision is being made over the entire input by default (things like checking terraform files, or other infra use cases).
[1] https://docs.osohq.com/more/design-principles.html#separatio...
[2] https://www.osohq.com/post/building-the-github-authorization...