Authorization in APISIX Using Casbin
소개
APISIX is a high-performance, scalable, cloud-native API gateway built on Nginx and etcd, and an Apache Software Foundation project. It ships with many plugins for authentication, monitoring, routing, and more. Plugins are hot-reloaded without restarts, so you can change behavior on the fly.
When you need authorization beyond simple checks, the authz-casbin plugin can help. It is an APISIX plugin built on Lua Casbin that enforces flexible authorization using models such as ACL, RBAC, and ABAC. Casbin is an authorization library (originally in Go, now ported to many languages); Lua Casbin is the Lua port. We proposed the plugin in the APISIX repo (#4674); after review and improvements, it was merged (#4710).
This post shows how to implement Role-Based Access Control (RBAC) in APISIX using authz-casbin.
Note: Casbin handles authorization only. Use another plugin or your own logic for authentication (identifying the user).
모델 생성
The plugin authorizes each request using three parameters: subject, object, and action. The subject comes from a header (e.g. username: alice), the object is the URL path, and the action is the HTTP method.
Suppose we have three paths: /, /res1, and /res2. We want a model like this:

So: any user (e.g. jack) can access /; users with the admin role (e.g. alice, bob) can access everything; and non-admin users are limited to GET. Here is a model that does that:
[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)
정책 생성
For the scenario above, the policy could be:
p, *, /, GET
p, admin, *, *
g, alice, admin
g, bob, admin
The matcher means:
(g(r.sub, p.sub) || keyMatch(r.sub, p.sub))— The request subject either has the policy subject as a role or matches it viakeyMatch. ForkeyMatchand other built-ins, see Lua Casbin BuiltInFunctions.keyMatch(r.obj, p.obj)— The request path matches the policy object.keyMatch(r.act, p.act)— The request method matches the policy action.
Enabling the plugin on a route
After creating the model and policy, enable the plugin on a route via the APISIX Admin API. Using file paths:
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": "/*"
}'
The username field is the header name that carries the subject (e.g. if the header is user: alice, set "username": "user").
To use inline model and policy text instead of files, use the model and policy fields:
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": "/*"
}'