skills/a6-plugin-wolf-rbac/SKILL.md
Skill for configuring the Apache APISIX wolf-rbac plugin via the a6 CLI. Covers integration with the Wolf RBAC server for role-based access control, token management, login/user-info/change-password API endpoints, permission checking flow, and multi-application setup.
npx skillsauth add moonming/a6 a6-plugin-wolf-rbacInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
The wolf-rbac plugin provides Role-Based Access Control (RBAC) by integrating
with the Wolf RBAC server. It enables
centralized authentication and fine-grained URL+method permission checking
across multiple applications without modifying backend services.
Priority: 2555 (authentication plugin, runs in rewrite phase).
http://127.0.0.1:12180)https://github.com/iGeeky/wolf/blob/master/quick-start-with-docker/README.md| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| server | string | No | http://127.0.0.1:12180 | Wolf RBAC server URL |
| appid | string | No | unset | Application ID registered in Wolf console |
| header_prefix | string | No | X- | Prefix for injected headers (UserId, Username, Nickname) |
Note: Configure on the Consumer, not the Route. Route config is empty {}.
V1#<appid>#<wolf_jwt_token>
Example: V1#restful#eyJhbGciOiJIUzI1NiIs...
?rbac_token=V1%23app%23token (URL-encoded)Authorization: V1#app#tokenx-rbac-token: V1#app#tokenx-rbac-token=V1#app#tokenThe plugin registers three endpoints (must be exposed via public-api plugin):
Authenticate and obtain rbac_token.
Request:
{
"appid": "restful",
"username": "test",
"password": "user-password",
"authType": 1
}
authType: 1 = password (default), 2 = LDAP (Wolf v0.5.0+)Response (200):
{
"rbac_token": "V1#restful#eyJhbGci...",
"user_info": {"id": "749", "username": "test", "nickname": "test"}
}
Get authenticated user details. Requires valid rbac_token.
Response (200):
{
"user_info": {
"id": 749,
"username": "test",
"nickname": "test",
"permissions": {"USER_LIST": true},
"roles": {}
}
}
Change password. Requires valid rbac_token.
Request:
{"oldPassword": "old", "newPassword": "new"}
1. Client sends request with rbac_token
2. APISIX parses token → extracts appid + wolf_token
3. Matches appid to Consumer configuration
4. Calls Wolf server: GET /wolf/rbac/access_check
- appID, resName (URL), action (HTTP method), clientIP
5. Wolf checks user roles/permissions for the resource
6. Success → inject X-UserId, X-Username, X-Nickname headers
7. Failure → return 401 (invalid token) or 403 (no permission)
Retry behavior: Up to 3 retries for 5xx Wolf server errors, 100ms between retries.
a6 consumer create -f - <<'EOF'
{
"username": "wolf_rbac",
"plugins": {
"wolf-rbac": {
"server": "http://127.0.0.1:12180",
"appid": "restful"
}
}
}
EOF
a6 route create -f - <<'EOF'
{
"id": "protected-api",
"uri": "/api/*",
"plugins": {
"wolf-rbac": {}
},
"upstream": {
"type": "roundrobin",
"nodes": {"backend:8080": 1}
}
}
EOF
a6 route create -f - <<'EOF'
{
"id": "wolf-login",
"uri": "/apisix/plugin/wolf-rbac/login",
"plugins": {
"public-api": {}
}
}
EOF
a6 route create -f - <<'EOF'
{
"id": "wolf-userinfo",
"uri": "/apisix/plugin/wolf-rbac/user_info",
"plugins": {
"public-api": {}
}
}
EOF
a6 route create -f - <<'EOF'
{
"id": "wolf-changepwd",
"uri": "/apisix/plugin/wolf-rbac/change_pwd",
"plugins": {
"public-api": {}
}
}
EOF
curl -X POST http://127.0.0.1:9080/apisix/plugin/wolf-rbac/login \
-H "Content-Type: application/json" \
-d '{"appid":"restful","username":"test","password":"user-password"}'
curl http://127.0.0.1:9080/api/users \
-H "Authorization: V1#restful#<token_from_step_6>"
# App 1 consumer
a6 consumer create -f - <<'EOF'
{
"username": "wolf_app1",
"plugins": {
"wolf-rbac": {
"server": "http://127.0.0.1:12180",
"appid": "app1"
}
}
}
EOF
# App 2 consumer
a6 consumer create -f - <<'EOF'
{
"username": "wolf_app2",
"plugins": {
"wolf-rbac": {
"server": "http://127.0.0.1:12180",
"appid": "app2"
}
}
}
EOF
Each appid in the token determines which Consumer (and which Wolf application)
is used for permission checking.
a6 consumer create -f - <<'EOF'
{
"username": "wolf_custom",
"plugins": {
"wolf-rbac": {
"server": "http://127.0.0.1:12180",
"appid": "myapp",
"header_prefix": "Wolf-"
}
}
}
EOF
Injected headers become: Wolf-UserId, Wolf-Username, Wolf-Nickname.
version: "1"
consumers:
- username: wolf_rbac
plugins:
wolf-rbac:
server: "http://127.0.0.1:12180"
appid: restful
routes:
- id: protected-api
uri: /api/*
plugins:
wolf-rbac: {}
upstream_id: api-backend
- id: wolf-login
uri: /apisix/plugin/wolf-rbac/login
plugins:
public-api: {}
- id: wolf-userinfo
uri: /apisix/plugin/wolf-rbac/user_info
plugins:
public-api: {}
- id: wolf-changepwd
uri: /apisix/plugin/wolf-rbac/change_pwd
plugins:
public-api: {}
After successful authentication, these headers are added to both request (upstream) and response (client):
| Header | Example | Description |
|--------|---------|-------------|
| {prefix}UserId | X-UserId: 749 | Wolf user ID |
| {prefix}Username | X-Username: admin | Wolf username |
| {prefix}Nickname | X-Nickname: administrator | URL-encoded nickname |
| Status | Message | Cause |
|--------|---------|-------|
| 401 | Missing rbac token in request | No token in any supported location |
| 401 | invalid rbac token: parse failed | Token format not V1#appid#jwt |
| 401 | Invalid appid in rbac token | No Consumer with matching appid |
| 401 | ERR_TOKEN_INVALID | JWT expired or signature invalid |
| 403 | ERR_ACCESS_DENIED | User lacks permission for URL+method |
| 500 | request to wolf-server failed | Wolf server unreachable or error |
Authorization header over query parameter (avoids logging tokens)HttpOnly and Secure flags when using cookieslimit-req on login endpoint to prevent brute forceip-restriction for additional network-level security| Symptom | Cause | Fix |
|---------|-------|-----|
| 400 "appid is missing" on login | Missing appid in login request body | Include appid field |
| 400 "appid not found" | No Consumer configured with that appid | Create Consumer with matching appid |
| 401 on every request | Token expired or not passed correctly | Re-login to get fresh token; check token location |
| 403 "ERR_ACCESS_DENIED" | User not authorized for URL+method in Wolf | Configure permissions in Wolf console |
| 500 "request to wolf-server failed" | Wolf server down or unreachable | Verify Wolf server URL and connectivity |
| Login endpoint returns 404 | Not exposed via public-api | Create route with public-api plugin for login URI |
tools
Core skill for working with the a6 CLI — the Apache APISIX command-line tool. Provides project conventions, command patterns, architecture overview, and development workflow. Load this skill when working on a6 source code, adding new commands, writing tests, or modifying any a6 component.
tools
Recipe skill for implementing multi-tenant API gateway patterns using the a6 CLI. Covers tenant isolation via Consumer Groups, host/path/header-based routing, per-tenant rate limiting, context forwarding with proxy-rewrite, and declarative config sync workflows for multi-tenant management.
tools
Recipe skill for configuring mutual TLS (mTLS) using the a6 CLI. Covers SSL certificate management, upstream mTLS to backend services, client certificate verification, and end-to-end mTLS setup from client through APISIX to upstream.
tools
Recipe skill for configuring upstream health checks using the a6 CLI. Covers active health checks (HTTP probing), passive health checks (response analysis), combining both, configuring healthy/unhealthy thresholds, and monitoring upstream node status.