Description
When using the REST API to assign roles to users through Casbin, there’s a problem related to case sensitivity in the scope field (in this specific case, for libraries)
Example request: /api/authz/v1/roles/users/
{
"users": ["admin"],
"role": "library_admin",
"scope": "lib:openedx:csprob"
}
The actual library ID is lib:OpenedX:CSPROB, However, during validation in the serializer, the following check is performed:
if not scope.exists():
raise serializers.ValidationError(f"Scope '{scope_value}' does not exist")
Since the exists() method internally performs a case-insensitive lookup:
def exists(self) -> bool:
try:
library_key = LibraryLocatorV2.from_string(self.library_id)
ContentLibrary.objects.get_by_key(library_key=library_key)
return True
except ContentLibrary.DoesNotExist:
return False
In [1]: lib_id = "lib:openedx:csprob"
In [2]: library_key = LibraryLocatorV2.from_string(lib_id)
In [3]: ContentLibrary.objects.get_by_key(library_key=library_key)
Out[3]: <ContentLibrary: ContentLibrary (lib:Openedx:CSPROB)>
the validation passes, even if the scope value casing doesn’t match the real ID in the system. As a result, the policy is stored with the incorrect scope ID in the casbin_rule table.
Later, when a GET request or permission check is made, the stored policy doesn’t match because of the case mismatch; the system expects the exact lib:OpenedX:CSPROB, but finds lib:openedx:csprob.
Impact
- Policies are stored with incorrect scope identifiers.
- Authorization lookups and role retrieval fail due to casing mismatches.
- The issue could also affect other scope types (e.g., Course, Organization, etc.), not only Library.
Possible Approaches
- Normalize all scope IDs before saving policies (e.g., resolve them to their canonical forms or convert them to lowercase).
- Modify the
exists() function to return not only a boolean value but also the correct canonical identifier. It’s important to note that the same approach should be applied to all exists() methods of each new scope type.
Description
When using the REST API to assign roles to users through Casbin, there’s a problem related to case sensitivity in the scope field (in this specific case, for libraries)
Example request:
/api/authz/v1/roles/users/{ "users": ["admin"], "role": "library_admin", "scope": "lib:openedx:csprob" }The actual library ID is
lib:OpenedX:CSPROB, However, during validation in the serializer, the following check is performed:Since the
exists()method internally performs a case-insensitive lookup:the validation passes, even if the scope value casing doesn’t match the real ID in the system. As a result, the policy is stored with the incorrect scope ID in the
casbin_ruletable.Later, when a GET request or permission check is made, the stored policy doesn’t match because of the case mismatch; the system expects the exact
lib:OpenedX:CSPROB, but findslib:openedx:csprob.Impact
Possible Approaches
exists()function to return not only a boolean value but also the correct canonical identifier. It’s important to note that the same approach should be applied to allexists()methods of each new scope type.