Permit.check()
permit.check()
is the main Authorize
function to enforce permissions in your application.
The permit.check()
function expects the following arguments in its basic form:
- User - a user ID
string
or a userobject
representing the user attempting to perform an action. - Action - a
string
representing the action a user is attempting to perform. - Resource - a
string
orobject
representing the resource the user is attempting to perform the action on. A resource could point to a resource type or to a specific resource instance. - Context (optional) - a context object that can be used to pass additional data to the policy evaluation.
The permit.check()
function returns a boolean
value, indicating whether the user is permitted to perform the action on the resource.
To maintain the least code changes in your application, you should carefully choose the most granular permit.check()
function implementation that fits your use case.
The following examples demonstrate common permit.check()
usage with a varied level of granularity:
Basic RBAC Check
The simplest enforcement point you can create using the permit.check()
function is a Role-based Access Control (RBAC) policy.
To enforce RBAC, permit.check()
requires three parameters to be passed:
- A unique
userId
- An
action
this user will attempt to perform - The
resource
for which we want to manage access to.
While all examples on this page are written in JavaScript (Node.js SDK), the permit.check() function exists in all Permit SDKs.
const permitted = await permit.check("john@permit.io", "create", "document");
if (permitted) {
console.log("John is PERMITTED to create a document");
} else {
console.log("John is NOT PERMITTED to create a document");
}
Tenants
Tenants are silos of resources and users.
Tenants can be passed as part of the resource
object inside the permit.check()
function.
const permitted = await permit.check("john@permit.io", "create", {
type: "document",
tenant: "companyA",
});
Say you have two tenants - Tenant A
and Tenant B
. The same user can be part of both tenants, with a different role in each one.
I.e., The user can be admin
in Tenant A
and editor
in Tenant B
.
Attributes
Sometimes, you might require more granular policies than simple RBAC. That's when Attribute Based Access Control (ABAC) comes into play. Specific user or resource attributes might be required to determine the conditions of when your authorization check should pass. Each attribute is compared against a pre-defined value. If all of these comparisons pass, the authorization check will be approved.
Attributes can be declared as part of the user
, resource
, or tenant
.
You can learn more about passing data into Permit here
const permitted = await permit.check(
// the user object
{
// the user key
key: "john@permit.io",
// just-in-time attributes on the user
attributes: {
location: "England",
department: "Engineering",
},
},
// the action the user is trying to do
"create",
// Resource
{
// the type of the resource (the resource key)
type: "document",
// just-in-time attributes on the resource
attributes: {
hasApproval: "true",
},
// the tenant the resource belong to
tenant: "companyB",
}
);
Just-In-Time (JIT) Attributes
JIT attributes are a way of passing dynamic values to pre-declared attributes as part of the permit.check()
function.
Passing JIT attributes is useful when an attribute can match more than a single value.
There are multiple ways of defining attributes within Permit. You can find a complete guide for them here.
A policy such as:
A document can only be accessed by users from EU and UK
Would be represented using JIT attributes in the following manner:
const permitted = await permit.check(
{
key: "john@smith.com",
attributes: {
location: location, // With location being a variable extracted from your logged user
},
},
"access",
"document"
);
Relationships
In cases where you want to manage access based on the relationships between identities and resources. That's where Relationship Based Access Control (ReBAC) comes in.
The structure of relationships between identities and resources can be defined via the UI or API.
In the code example below, we check if John
has the assign
permissions on a member group resource (Defined in Permit beforehand).
await permit.check(userId, "assign", `member_group:${group}`);
Using the Context Object
If you are using custom policy code and need to pass additional data to the policy evaluation, you can use the context
object.
await permit.check(user, "create", "document", {
context: {
// additional data to be passed to the policy evaluation
totalDocuments: 100,
},
});
Using the API
While the easiest way to call the permit.check()
function is to use one of our SDKs, you can also call the Permit PDP directly.
The API endpoint for the permit.check()
function is /allowed
.
curl -X POST https://<your-permit-pdp-url>/allowed \
-H "Content-Type: application/json" \
-d "Authorization: Bearer <your-permit-api-key>" \
-d '{
"user": "john@doe.me",
"action": "create",
"resource": {
"type": "document",
"tenant": "companyA"
},
"context": {}
}'
When calling the permit.check()
API, ensure that you are calling either your deployed Permit PDP or the Permit cloud PDP. The api.permit.io
is not supported for the permit.check()
API.