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
stringor a userobjectrepresenting the user attempting to perform an action. - Action - a
stringrepresenting the action a user is attempting to perform. - Resource - a
stringorobjectrepresenting the target resource. This could refer to a resource type, a specific resource instance (e.g.,document:123), or an object wheretypespecifies the resource type andkeyspecifies the resource instance. - Context (optional) - a context object that can be used to pass additional data to custom policy.
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(e.g. the identity from your authentication -jwt._subId) - An
actionthis user will attempt to perform - The
resourcefor 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 user attributes
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 resource attributes
attributes: {
hasApproval: "true",
},
// the tenant the resource belongs 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}`);
- Another example, access a document with id
doc1.txt:
await permit.check(userId, "assign", `document:doc1.txt`);
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.