2024 was the year AI agents went from demos to production. With the Model Context Protocol (MCP) gaining adoption from Google, OpenAI, Microsoft, and countless others, we're seeing a fundamental shift in how applications interact with external services. And with that shift comes a whole new set of authorization challenges that we at Casbin have been thinking about.
Understanding How Casbin Matching Works in Detail
In this post, I will explain the design and implementation of RBAC using the Casbin library. For a SaaS platform dealing with multiple resource hierarchies and roles that inherit permissions from higher levels, Casbin provides a performant alternative to consider.
Introduction to RBAC
RBAC is a method of restricting access to resources based on the roles that individuals hold. To better understand how hierarchical RBAC works, let's take a look at Azure's RBAC system in the next section and then attempt to implement a similar system.
Understanding Azure's Hierarchical RBAC

There is a role called Owner for all resources in Azure. Suppose if I have the Owner role assigned to me at the subscription level, that means I am the Owner of all the resource groups and resources under that subscription. If I have Owner at the resource group level, then I am the Owner of all the resources under that resource group.
This image shows that I have Owner access at the subscription level. 
When I check the IAM of a Resource Group under this Subscription, you can see that I have inherited Owner access from the
subscription. 
So, this is how Azure's RBAC is hierarchical. Most enterprise software uses hierarchical RBAC because of the hierarchical nature of the resource levels. In this tutorial, we'll try to implement a similar system using Casbin.
How Does Casbin Work?
Before diving into the implementation, it is important to understand what Casbin is and how it functions at a high level. This understanding is necessary because each Role-Based Access Control (RBAC) system may vary based on specific requirements. By grasping the workings of Casbin, we can effectively fine-tune the model.
What is ACL?
ACL stands for Access Control List. It is a method in which users are mapped to actions and actions to resources.
The model definition
Let's consider a simple example of an ACL model.
[request_definition]
r = sub, act, obj
[policy_definition]
p = sub, act, obj
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
The request_definition is the query template of the system. For example, a request
alice, write, data1can be interpreted as "Can subject Alice perform the action 'write' on object 'data1'?".The policy_definition is the assignment template of the system. For example, by creating a policy
alice, write, data1, you are assigning permission to subject Alice to perform the action 'write' on object 'data1'.The policy_effect defines the effect of the policy.
In the matchers section, the request is matched with the policy using the conditions
r.sub == p.sub && r.obj == p.obj && r.act == p.act.
Now let's test the model on the Casbin editor
Open the editor and paste the above model in the Model editor.
Paste the following in the Policy editor:
p, alice, read, data1
p, bob, write, data2
and the following in the Request editor:
alice, read, data1
The result will be:
true
Visual representation of the ACL model, policy, and request matching

What is RBAC?
RBAC stands for Role-Based Access Control. In RBAC, a user is assigned a role for a resource, and a role can contain arbitrary actions. The request then checks if the user has the permission to perform the action on the resource.
The model definition
Let's consider a simple example RBAC model:
[request_definition]
r = sub, act, obj
[policy_definition]
p = sub, act, obj
[role_definition]
g = _, _
g2 = _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = r.sub == p.sub && g(p.act, r.act) && r.obj == p.obj
- The role_definition is a graph relation builder that uses a Graph to compare the request object with the policy object.
Now let's test the model on Casbin editor
Open the editor and paste the above model in the Model editor.
Paste the following in the Policy editor:
p, alice, reader, data1
p, bob, owner, data2
g, reader, read
g, owner, read
g, owner, write
and the following in the Request editor:
alice, read, data1
alice, write, data1
bob, write, data2
bob, read, data2
bob, write, data1
The result will be:
true
false
true
true
false
Visual representation of the RBAC model, policy, and request matching

The g - Role to action mapping table has a Graph mapping the role to action. This Graph can be coded as a list of edges, as shown in the policy which is a common way of representing a Graph:
g, reader, read
g, owner, read
g, owner, write
p indicates a normal policy that can be compared using the == operator. g is a Graph-based comparison function. You can define multiple Graph comparators by adding a numerical suffix like g, g2, g3, ... and so on.
What is Hierarchical RBAC?
In Hierarchical RBAC, there are more than one type of resources and there is an inheritance relationship between the resource types. For example, "subscription" is one type and "resourceGroup" is another type. A sub1 of type Subscription can contain multiple resourceGroups (rg1, rg2) of type ResourceGroup.
Similar to the resource hierarchy, there will be two types of roles and actions: Subscription roles and actions, and ResourceGroup roles and actions. There is an arbitrary relationship between the Subscription role and ResourceGroup role. For example, consider a Subscription Role sub-owner. This role is inherited by a ResourceGroup Role rg-owner, which means that if I am assigned the sub-owner role on Subscription sub1, then I automatically also get the rg-owner role on rg1 and rg2.
The model definition
Let's take a simple example of the Hierarchical RBAC model:
[request_definition]
r = sub, act, obj
[policy_definition]
p = sub, act, obj
[role_definition]
g = _, _
g2 = _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = r.sub == p.sub && g(p.act, r.act) && g2(p.obj, r.obj)
- The role_definition is a graph relation builder which uses a Graph to compare the request object with the policy object.
Now let's test the model on the Casbin editor
Open the editor and paste the above model in the Model editor.
Paste the following in the Policy editor:
p, alice, sub-reader, sub1
p, bob, rg-owner, rg2
// subscription role to subscription action mapping
g, sub-reader, sub-read
g, sub-owner, sub-read
g, sub-owner, sub-write
// resourceGroup role to resourceGroup action mapping
g, rg-reader, rg-read
g, rg-owner, rg-read
g, rg-owner, rg-write
// subscription role to resourceGroup role mapping
g, sub-reader, rg-reader
g, sub-owner, rg-owner
// subscription resource to resourceGroup resource mapping
g2, sub1, rg1
g2, sub2, rg2
And paste the following in the Request editor:
alice, rg-read, rg1
The result will be:
true
Visual representation of the RBAC model, policy, and request matching

The g - Role to (Action, Role) Mapping table has a graph mapping the role to the action, role mapping. This graph can be coded as a list of edges, as shown in the policy, which is a common way of representing a graph:
// subscription role to subscription action mapping
g, sub-reader, sub-read
g, sub-owner, sub-read
g, sub-owner, sub-write
// resourceGroup role to resourceGroup action mapping
g, rg-reader, rg-read
g, rg-owner, rg-read
g, rg-owner, rg-write
// subscription role to resourceGroup role mapping
g, sub-reader, rg-reader
g, sub-owner, rg-owner
The g2 - Sub to RG Mapping table has a graph mapping subscription to resourceGroup:
// subscription resource to resourceGroup resource mapping
g2, sub1, rg1
g2, sub2, rg2
Subject Matching Visual representation

Action Matching Visual representation

Object Matching Visual representation

When a request is submitted to Casbin, this matching happens for all the policies. If at least one policy matches, then the result of the request is true. If no policy matches the request, then the result is false.
Conclusion
In this tutorial, we learned about how different authorization models work and how they can be modeled using Casbin. In the second part of this tutorial, we will implement this in a demo Spring Boot Application and secure the APIs using Casbin.
使用 Casbin 在 APISX 中授权
简介
APISIX 是一个基于Nginx 等的高性能和可缩放云端本地的 API 网关。 这是Apache Software 基金会的一个开放源码项目。 除此以外,APIIX 非常好的是在可以用于实现认证等功能的插件中建立的许多强大的支持。 监视、路由等。 APISIX中的插件被热重新加载(未重启) 这一事实使其非常活跃。
但在使用 APISIX时,可能会出现您想要在应用程序中添加复杂的授权逻辑的情况。 Authz-casbin可能会帮助您。 authz-casbin 是基于 Lua Casbin 的APIIX 插件,它允许基于各种访问控制模型的强大授权。 Casbin 是一个支持访问控制模型的授权库,例如ACL、RBAC、ABAC。 它最初是用Go编写的,已被移植到许多语言,Lua Casbin是Casbin的Lua实现。 Authz-casbin的开发始于我们在APISIX 存储库中提出了一个新的授权插件(#4674),核心成员同意了这个插件。 经过一些有助益的审查导致了一些重大变化和改进,最终合并了PR (#4710)。
在这个博客中, 我们将使用authz-casbin 插件来显示您如何在 APISIX中实现基于角色访问控制的授权模式。
备注: 您将需要使用其他插件或自定义工作流来验证用户,因为Casbin只会进行授权而不是身份验证。
创建模型
插件使用三个参数授权任何请求 - 主题(subject)、对象(object) 和动作(action)。 这里的主题是用户名头的值,可能是 [用户名:别名]。 然后,对象是正在访问的 URL 路径和正在使用的请求方法。
让我们说我们想要在路径上用三个资源创建一个模型 - / /res1 和 /res2。 我们希望有这样的模式:

这将意味着所有用户 (*) 都像 jack 可以访问首页 (/)。 并且拥有 管理员 权限的用户,比如 `和bob可以访问所有页面和资源 (例如res1和res2)。 另外,让我们限制没有任何管理员权限的用户仅使用 GET` 请求方法。 在这种情况下,我们可以将模式定义为:
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[role_definition]
g = _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = (g(r.sub, p.sub) || keyMatch(r.sub, p.sub)) && keyMatch(r.obj, p.obj) && keyMatch(r.act, p.act)
创建策略
根据上述设想,策略将是:
p, *, /, GET
p, admin, *, *
g, alice, admin
g, bob, admin
来自模型的匹配器是指:
(g(r.sub, p.sub) || keyMatch(r.sub, p.sub)): 请求的主题作为策略的主题或请求的主题与策略的主题匹配keyMatch。keyMatch是在 Lua Casbin 中构建的。 您可以在这里查看函数的描述和更多可能有用的函数keyMatch(r.obj, p.obj): 请求的对象匹配策略的对象(URL路径在这里)。keyMatch(r.act, p.act): 请求的动作与策略的动作匹配(HTTP 请求方法在这里)。
启用路由插件
创建模型和策略后,您可以使用APISIX Admin API在路由上启用它。 要使用模型和策略文件路径启用它:
curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"plugins": {
"authz-casbin": {
"model_path": "/path/to/model.conf",
"policy_path": "/path/to/policy.csv",
"username": "username"
}
},
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"uri": "/*"
}'
在这里,用户名字段是您将要在主题中传递的标题名称。 例如,如果您将通过用户名头以 user: Alice, 您将使用 "username": "user".
对于使用模型/策略文本而不是文件,您可以使用 模型 和 策略 字段替代:
curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"plugins": {
"authz-casbin": {
"model": "[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[role_definition]
g = _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = (g(r.sub, p.sub) || keyMatch(r.sub, p.sub)) && keyMatch(r.obj, p.obj) && keyMatch(r.act, p.act)",
"policy": "p, *, /, GET
p, admin, *, *
g, alice, admin
g, bob, admin",
"username": "username"
}
},
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"uri": "/*"
}'
启用使用全局模型/策略的插件
在某些情况下,您可能希望跨多个路由使用单个模型和策略配置。 您可以首先发送PUT请求,通过以下方式将模型和策略配置添加到插件的元数据中:
curl http://127.0.0.1:9080/apisix/admin/plugin_metadata/authz-casbin -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -i -X PUT -d '
{
"model": "[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[role_definition]
g = _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = (g(r.sub, p.sub) || keyMatch(r.sub, p.sub)) && keyMatch(r.obj, p.obj) && keyMatch(r.act, p.act)",
"policy": "p, *, /, GET
p, admin, *, *
g, alice, admin
g, bob, admin"
}'
然后在某些路由上启用相同的配置,使用管理员API发送请求:
curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"plugins": {
"authz-casbin": {
"username": "username"
}
},
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"uri": "/route1/*"
}'
这将添加插件元数据配置到路由中。 您也可以轻松地更新插件元数据配置,通过更新模型和政策配置重新发送插件元数据请求, 插件将使用插件元数据自动更新所有路由。
应用案例
- 此插件的主要用途是在您的 API 中执行授权。 您可以轻松地将此插件添加到您正在使用的任何API路径中,并使用您的授权模型和策略配置。
- 如果您想要为您的所有API使用单一授权模式,您可以使用全局模式/策略方法。 这使得更新策略对所有路由都很容易,因为您只需要更新元数据等。
- 如果你想对每个不同的路由使用不同的模型,你可以使用路由方法。 当不同的 API 路由拥有不同的用户权限时,这是有用的。 当您处理更大的策略时,您也可以使用这个策略,因为当过滤多条路由时,它会使授权变得更快。
Yang Luo - 谷歌开源同行奖金得主
今天,我们很高兴地宣布,Casbin 的创始人Yang Luo因其在 2019 年第三季度在 Casbin、Npcap 和 Nmap 上的工作而被授予 "谷歌开源同行奖金得主"。

原始授予信可以访问 这里。
谷歌开源同伴奖金计划被描述为:
正如谷歌同伴奖金用于表彰超越一切的谷歌同事一样,开源同伴奖金也表彰对开源做出杰出贡献的外部人员。
适用于 2019 获胜者 的公告可在以下网址获取:
https://opensource.googleblog.com/2020/01/announcing-2019-second-cycle-google.html
Yang 和 Casbin 被列为具有相关影响的开源开发人员和项目,如 Git、TensorFlow、V8、CPython、LLVM、Apache 项目、Angular 或 Jenkins。
我们很高兴看到 Casbin 因其对开源和云安全的贡献而获得认可!
感谢你!Casbin!
正在重新编写我们的文档
今天,我们已将Casbin的文档从 GitHub Wiki 迁移到此网站的 Docs 文档, 由 Docusaurus 提供支持。 Docusaurus提供了许多优秀的功能,例如更好的 Markdown风格,全文搜索,版本设置,翻译。
文件尚不完善,仍然需要调整。 源代码在 GitHub: https://github.com/casbin/casbin-website-v2 上托管。
欢迎任何贡献或建议!
node-Casbin:Casbin家庭新成员
今天,我们成功地将Casbin移植到 Node.js,命名为: node-Casbin
node-Casbin 分享了类似的用法和 API 与其他Casbin 的实现。 Express、 Koa2 和 Egg.js 的中间件已准备好使用 。 序列化的存储适配器也已准备好。
希望它能够很好地满足您的需要:)
Casbin 服务器已启动!
我们的一些客户询问Casbin是否可以用作服务而不是库。 答案是 当然可以。 今天,我们启动了 Casbin Server 项目,作为 访问控制作为服务 的具体解决方案。
Casbin Server 正在由我们的核心团队积极开发。 它有以下几个特点:
- 纯粹是由Golang开发的。
- 可以管理数以千计的 Casbin 实例,这样您就可以将策略执行逻辑从多个服务移动到一个Casbin 服务器。
- gRPC 被用于与 Casbin 服务器通信。 我们还考虑在不久的将来添加 RESTTful 支持。
- 为非开发者管理员提供了一个友好的网站管理员门户,用于管理所有细节,如Casbin实例、模型、政策存储和负载平衡。
源代码托管在 GitHub 上: https://github.com/casbin/casbin-server
欢迎任何问题或合并请求 :)