Documentation Index
Fetch the complete documentation index at: https://www.osohq.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
Impersonation lets users act on behalf of others—like support reps accessing customer accounts—by temporarily inheriting a subset of their permissions through a combination of impersonation facts and policy rules.
Implementation
There are two main components to impersonation:
- A fact that indicates whether a user is impersonating another user.
- A policy that grants permissions to users who are impersonating another user.
In our example, members with a “support” role need to impersonate admins.
actor User {
permissions = ["impersonate"];
"impersonate" if global "support";
}
global {
roles = ["support"];
}
resource Organization {
roles = ["admin", "member"];
permissions = ["read", "write"];
"member" if "admin";
"read" if "member";
"write" if "admin";
}
# a user can do anything some other user can do
# if they are allowed to impersonate that user and
# are currently impersonating them
allow(user: User, action: String, resource: Resource) if
other_user matches User and
has_permission(user, "impersonate", other_user) and
is_impersonating(user, other_user) and
has_permission(other_user, action, resource);
# we need to specify the default allow rule here
# because we added our own custom one above
allow(user: User, action: String, resource: Resource) if
has_permission(user, action, resource);
test "global support users can read user organizations via impersonation" {
setup {
has_role(User{"alice"}, "support");
has_role(User{"bob"}, "admin", Organization{"acme"});
has_role(User{"charlie"}, "member", Organization{"bar"});
is_impersonating(User{"alice"}, User{"bob"});
}
# bob can read as a member
assert allow(User{"bob"}, "read", Organization{"acme"});
# alice can impersonate bob
assert allow(User{"alice"}, "impersonate", User{"bob"});
# alice can read via Bob by impersonating bob
assert allow(User{"alice"}, "read", Organization{"acme"});
# charlie can read as a member
assert allow(User{"charlie"}, "read", Organization{"bar"});
# alice cannot read because alice is not impersonating charlie
assert_not allow(User{"alice"}, "read", Organization{"bar"});
}
In our test case:
- Alice is a customer support rep and is impersonating Bob.
- Bob is an admin of the acme organization.
- And so Alice can see anything Bob can.
Common scenarios
There are several ways to define who has permission to impersonate another user. Common ones include:
From a relationship with the user:
actor User {
permissions = ["impersonate"];
relations = { manager: User };
"impersonate" if "manager";
}
Or from a role on the organization:
actor User {
permissions = ["impersonate"];
}
resource Organization {
roles = ["member", "admin"];
}
# Organization admins can impersonate members
has_permission(user: User, "impersonate", other_user: User) if
org matches Organization and
has_role(user, "admin", org) and
has_role(other_user, "member", org);
The is_impersonating fact can be included as an ephemeral context fact or more durably synced to Oso Cloud.
- If included as a context fact, when a user “ends” an impersonation session, the application stops sending the impersonation context fact.
- If stored in Oso Cloud, you need to delete the persisted fact to end the impersonation.
Use context facts to scope impersonation to a single application or service, and persisted facts to share impersonation sessions across multiple services.