Seiichi Arai
11/10/2025, 9:58 AM{
"__data_use_debugger": true,
"__input_use_debugger": true,
"allow": false,
"allowing_sources": [],
"debug": {
"abac": {
"allow": false,
"code": "no_matching_rules",
"matching_resourcesets": [
"Draft_Blog",
"User",
"__autogen_Blog"
],
"matching_usersets": [
"Draft_Blog",
"User",
"__autogen_Blog"
],
"reason": "user 'seiichi1101_user' does not match any rule that grants him the 'read' permission on the given resource of type 'Blog'",
"support_link": "<https://docs.permit.io/errors/no_matching_rules>"
},
"rbac": {
"allow": false,
"code": "user_not_synced",
"reason": "user 'seiichi1101_user' is not synced and therefore has no known role assignments",
"support_link": "<https://docs.permit.io/errors/user_not_synced>"
},
"request": {
"action": "read",
"resource": {
"attributes": {
"is_paid": false,
"is_published": false,
"owner": "seiichi1101_user",
"type": "Blog"
},
"type": "Blog"
},
"tenant": "default",
"user": {
"attributes": {
"is_staff": false,
"roles": [],
"subscription_plan": "free",
"tenants": []
},
"key": "seiichi1101_user",
"synced": false
}
}
},
"debugger_activated": true
}
As you can see in the log and screenshot, access is denied even though I’ve set up the User Sets, Resource Sets, and policy assignments in the Policy Editor.
It says "user 'seiichi1101_user' does not match any rule that grants him the 'read' permission on the given resource of type 'Blog'",.
My expectation is that the user with key: "seiichi1101_user" should be allowed to access the resource set MyBlog, because its resource condition is configured as "resource.owner" - "equals" - "user.key" and the policy is assigned accordingly.
Is there anything I’m missing here?Ask Inkeep
11/10/2025, 9:58 AMAsk Inkeep
11/10/2025, 9:58 AM"synced": false) and has no role assignments (1) (2) (3) . This is preventing the ABAC rules from matching properly.
The debug message indicates "user 'seiichi1101_user' is not synced and therefore has no known role assignments" . For ABAC ownership patterns to work correctly, the user needs to be properly synced in Permit.io's system .
To fix this issue, you need to sync your user. Here's how to do it based on the documented examples:
permit.api.users.sync({
email: "<mailto:seiichi1101_user@example.com|seiichi1101_user@example.com>",
key: "seiichi1101_user",
first_name: "User",
last_name: "Name",
attributes: {},
}) ;
(1) (3)
Additionally, when creating resource sets for ownership patterns, ensure the condition uses the correct reference format:
{
"allOf": [
{
"resource.owner": {
"equals": {
"ref": "user.key"
}
}
}
]
}
(2) (3)
The key point is using { "ref": "user.key" } rather than just "user.key" to properly reference the user's key attribute in the comparison .
After syncing the user, your ABAC rules should properly evaluate the ownership condition and grant access when resource.owner matches the user's key.
To help our engineers investigate further:
1. Which Workspace / Project / Env are you using?
2. What calls are you performing (as SDK code or CURL) ?
3. Which PDP version are you running?
4. Could you share relevant logs from your PDP?Ask Inkeep
11/10/2025, 9:58 AMAsk Inkeep
11/10/2025, 10:03 AMSeiichi Arai
11/10/2025, 10:04 AMref but output is still same.
{
"allOf": [
{
"allOf": [
{
"resource.owner": {
"equals": {
"ref": "user.key"
}
}
}
]
}
]
}Alon Boshi
11/10/2025, 10:21 AMSeiichi Arai
11/10/2025, 10:25 AMseiichi1101
Projcet: Default Project
Env: ProductionAlon Boshi
11/10/2025, 10:26 AMand what calls are you performing
Seiichi Arai
11/10/2025, 10:28 AMconst hasPermission = await permit.check(
{
key: username,
attributes: userAttrs,
},
action,
{
type: resource,
attributes: resourceAttrs,
},
);
• recorded in the log
"request": {
"action": "read",
"resource": {
"attributes": {
"is_paid": false,
"is_published": false,
"owner": "seiichi1101_user",
"type": "Blog"
},
"type": "Blog"
},
"tenant": "default",
"user": {
"attributes": {
"is_staff": false,
"roles": [],
"subscription_plan": "free",
"tenants": []
},
"key": "seiichi1101_user",
"synced": false
}
}Alon Boshi
11/10/2025, 10:56 AMThomas
11/10/2025, 8:11 PMseiichi1101 user (as opposed to seiichi1101_user) in the directory, and when you make
{
"action": "read",
"resource": {
"attributes": {
"is_paid": false,
"is_published": false,
"owner": "seiichi1101",
"type": "Blog"
},
"type": "Blog"
},
"tenant": "default",
"user": {
"attributes": {
"is_staff": false,
"roles": [],
"subscription_plan": "free",
"tenants": []
},
"key": "seiichi1101",
"synced": false
}
}
you get
{
"allow": true,
"debug": {
"abac": {
"allow": true,
"allowing_rules": [
{
"resourceset": "resourceset_My_5fBlog",
"userset": "userset_User"
}
],
"code": "allow",
"reason": "user 'seiichi1101' matched 'userset_User' userset conditions, the given resource matched the 'resourceset_My_5fBlog' resourceset conditions, users matching 'userset_User' userset conditions has the 'read' permission on resources of type 'Blog' matching 'resourceset_My_5fBlog' resourceset conditions"
},
"request": {
"action": "read",
"resource": {
"attributes": {
"is_paid": false,
"is_published": false,
"owner": "seiichi1101",
"type": "Blog"
},
"type": "Blog"
},
"tenant": null,
"user": {
"attributes": {
"is_staff": false,
"key": "seiichi1101",
"roles": [],
"subscription_plan": "free",
"tenants": []
},
"key": "seiichi1101",
"synced": true
}
}
},
"result": false
}Seiichi Arai
11/11/2025, 7:30 AMseiichi1101_user , I was able to confirm that the resource matches the resource set My Blog.
However, this behavior feels a bit unintuitive to me.
In other cases where I don’t use { "resource.owner": { "equals": { "ref": "user.key" } } } in the ResourceSets, it hasn’t been necessary to register the user, and both the UserSets and ResourceSets still matched correctly.
Also, in the permit.check request, I'm already passing user.key to the PDP (e.g. "user": { "key": "seiichi1101_user" }), so I would expect it to use that value.
Is this behavior dependent on how OPA works internally? From what I can see, the PDP seems to simply forward the request to OPA: https://github.com/permitio/PDP/blob/main/horizon/enforcer/api.py#L484Alon Boshi
11/11/2025, 9:09 AMAsk Inkeep
11/11/2025, 9:09 AMAsk Inkeep
11/11/2025, 9:09 AM{ "ref": "user.key" } in resource set conditions, the PDP needs the user to be synced to properly evaluate the condition .
For ownership patterns via list on resource, the documented approach shows passing the owners list as a resource attribute :
const permitted = await permit.check(userKey, "read", {
type: "file", // The resource name
attributes: {
owners: [
"d08c85a349994aeb89a3f02c08bdb340", // user-1
"48fb889360604253a5189580b48694cf", // user-2
],
},
}) ;
The key difference is that when using dynamic references like { "ref": "user.key" }, the PDP needs to resolve the user's actual attributes from the synced data . This is why unsynced users can't match these conditions - the PDP doesn't have the necessary user data to evaluate the reference.
For simpler attribute matching without references (like static values) , the attributes passed directly in the permit.check() call are sufficient (2) . But when you're referencing user properties in resource set conditions, the user must be synced for the PDP to access those properties.
This is indeed how OPA works internally - it needs all the data available to evaluate complex conditions with references between user and resource attributes (1) .Ask Inkeep
11/11/2025, 9:09 AMSeiichi Arai
11/11/2025, 2:51 PMref on the Permit.io side, but not in OPA itself.
As far as I understand, OPA can compare input user.key directly in the policy without any user sync.