{"id":28028395,"url":"https://github.com/permitio/permit-fe-sdk","last_synced_at":"2026-02-08T15:03:35.578Z","repository":{"id":193102299,"uuid":"511238443","full_name":"permitio/permit-fe-sdk","owner":"permitio","description":"Official Permit.io FE SDK lets you easily integrate Permit.io advanced permissions into your frontend application.","archived":false,"fork":false,"pushed_at":"2026-02-08T00:17:42.000Z","size":153,"stargazers_count":11,"open_issues_count":1,"forks_count":6,"subscribers_count":4,"default_branch":"main","last_synced_at":"2026-02-08T09:07:30.168Z","etag":null,"topics":["example"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/permitio.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-07-06T17:49:14.000Z","updated_at":"2026-02-08T00:17:47.000Z","dependencies_parsed_at":"2023-09-06T20:25:33.966Z","dependency_job_id":"46a8dbc3-aef5-49ee-9d52-97385f62bef2","html_url":"https://github.com/permitio/permit-fe-sdk","commit_stats":null,"previous_names":["permitio/permit-fe-sdk"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/permitio/permit-fe-sdk","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/permitio%2Fpermit-fe-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/permitio%2Fpermit-fe-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/permitio%2Fpermit-fe-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/permitio%2Fpermit-fe-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/permitio","download_url":"https://codeload.github.com/permitio/permit-fe-sdk/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/permitio%2Fpermit-fe-sdk/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29234154,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-08T14:18:14.570Z","status":"ssl_error","status_checked_at":"2026-02-08T14:18:14.071Z","response_time":57,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["example"],"created_at":"2025-05-11T07:13:10.734Z","updated_at":"2026-02-08T15:03:35.493Z","avatar_url":"https://github.com/permitio.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# permit-fe-sdk\n\n## Overview\n\nThis package lets you easily integrate Permit.io advanced permissions into your frontend application. It is integrated\nwith [CASL](https://casl.js.org/v5/en/) and so can be used with any frontend framework.\n\n## Installation\n\n```bash\nnpm install permit-fe-sdk\nyarn add permit-fe-sdk\n```\n\n## Usage\n\n### Setting Up a Backend Route to Fetch Permissions\n\n#### 1. **Example Server**\n\n- Refer to the `demo_server` folder for a sample server configuration.\n\n#### 2. **Communication with PDP**\n\n- The server interacts with the PDP (Policy Decision Point) to fetch permissions for the current user.\n- **Note**: It's essential to ensure the PDP is not exposed to the frontend.\n\n#### 3. **Available Endpoints**\n\n- **GET Endpoint**:\n    - Purpose: Fetch permissions for a specific resource and action associated with the current user.\n- **POST Endpoint (Recommended)**:\n    - Purpose: Retrieve permissions in bulk for multiple resources and actions for the current user.\n\n#### 4. **Recommendation**\n\n- Using the POST endpoint is preferable as it reduces the number of requests between the frontend and backend, offering\n  a more efficient data retrieval process.\n\n### Using the SDK in Your Frontend\n\n#### Available Demo Apps\n\n- **React**: Check out the [demo app for React](https://github.com/permitio/fe-demo-react).\n- **Angular**: Refer to the [demo app for Angular](https://github.com/permitio/fe-demo-angular).\n\n#### Integration with Other Frontend Frameworks\n\nIf you're working with a different frontend framework, consult\nthe [CASL documentation](https://casl.js.org/v5/en/guide/intro). It provides guidance on importing data into CASL\nability. This SDK can then help generate the necessary data for CASL.\n\n#### Integration Guide for React:\n\nYou can create a React component called an `AbilityLoader` to handle this:\n\n```javascript\nimport { Ability } from '@casl/ability';\nimport { Permit, permitState } from 'permit-fe-sdk';\n\nconst getAbility = async (loggedInUser) =\u003e {\n  const permit = Permit({\n    // This is the unique userId from your authentication provider in the current session.\n    loggedInUser: loggedInUser,\n    backendUrl: '/api/your-endpoint',\n  });\n\n  await permit.loadLocalState([\n    { action: 'view', resource: 'statement' },\n    { action: 'view', resource: 'products' },\n    { action: 'delete', resource: 'file' },\n    { action: 'create', resource: 'document' },\n  ]);\n\n  const caslConfig = permitState.getCaslJson();\n\n  return caslConfig \u0026\u0026 caslConfig.length ? new Ability(caslConfig) : undefined;\n};\n```\n\n#### Custom request headers\n\nIf needed, the SDK allows you to pass custom headers to the backend. This can be useful for passing authentication\ntokens or other necessary information.\n\n```javascript\nconst permit = Permit({\n  loggedInUser: loggedInUser,\n  backendUrl: '/api/your-endpoint',\n  customRequestHeaders: {\n    Authorization: 'Bearer your-token',\n  }\n});\n```\n\n\u003e **Note:** `customRequestHeaders` is deprecated and will be removed in the next major version.\n\u003e Headers will be configured via `axiosConfig.headers` instead. See the migration guide below.\n\n#### Axios configuration (CORS, timeouts, etc.)\n\nFor advanced use cases like CORS with credentials or custom timeouts, you can pass\nany [Axios request config](https://axios-http.com/docs/req_config) options:\n\n```javascript\nconst permit = Permit({\n  loggedInUser: loggedInUser,\n  backendUrl: '/api/your-endpoint',\n  axiosConfig: {\n    withCredentials: true,  // Enable CORS credentials\n    timeout: 10000,         // Request timeout in ms\n  },\n});\n```\n\n\u003e **Important:** Currently, `axiosConfig.headers` is **not supported** - any headers passed via `axiosConfig` will be\n\u003e ignored. You must use `customRequestHeaders` for custom headers in the current version.\n\u003e\n\u003e **In the next major version**, `customRequestHeaders` will be removed and headers will be configured via\n\u003e `axiosConfig.headers`. To prepare for this migration:\n\u003e\n\u003e ```javascript\n\u003e // Current version (use customRequestHeaders for headers)\n\u003e const permit = Permit({\n\u003e   loggedInUser: loggedInUser,\n\u003e   backendUrl: '/api/your-endpoint',\n\u003e   customRequestHeaders: { Authorization: 'Bearer token' },\n\u003e   axiosConfig: { withCredentials: true },\n\u003e });\n\u003e\n\u003e // Next major version (headers via axiosConfig)\n\u003e const permit = Permit({\n\u003e   loggedInUser: loggedInUser,\n\u003e   backendUrl: '/api/your-endpoint',\n\u003e   axiosConfig: {\n\u003e     headers: { Authorization: 'Bearer token' },\n\u003e     withCredentials: true,\n\u003e   },\n\u003e });\n\u003e ```\n\n### Understanding Access Control Models with `loadLocalStateBulk`\n\nWhen working with access control in your application, it's crucial to understand the differences between various policy\nmodels: Role-Based Access Control (RBAC), Attribute-Based Access Control (ABAC), and Relationship-Based Access Control (\nReBAC). Each of these models has its own way of determining permissions, which affects how you should configure and pass\ndata to the loadLocalStateBulk function in your application.\n\n#### Common Usage of loadLocalStateBulk\n\nThe `loadLocalStateBulk` function allows you to load multiple permission checks at once, optimizing the performance of\nyour application by reducing the number of backend calls. Below is a general example demonstrating how different access\ncontrol models can be integrated into a single bulk request.\n\n```javascript\nconst getAbility = async (loggedInUser) =\u003e {\n  const permit = Permit({\n    // This is the unique userId from your authentication provider in the current session.\n    loggedInUser: loggedInUser,\n    backendUrl: '/api/your-endpoint',\n    // Pass ABAC user attributes.\n    userAttributes: { user_attr1: 'attr_value' },\n  });\n\n  await permit.loadLocalStateBulk([\n    // RBAC example\n    { action: 'view', resource: 'statement' },\n    { action: 'view', resource: 'products' },\n    { action: 'delete', resource: 'file' },\n\n    // ABAC example\n    {\n      action: 'view',\n      resource: 'files_for_poland_employees',\n      userAttributes: {\n        department: 'Engineering',\n        salary: '100K',\n      },\n      resourceAttributes: { country: 'PL' },\n    },\n\n    // ReBAC example\n    { action: 'create', resource: 'document:my_file.doc' },\n  ]);\n};\n```\n\nLet's break this down into smaller policy-based chunks:\n\n#### Role-Based Access Control (RBAC)\n\nRBAC assigns permissions to users based on their roles within an organization. This is a straightforward model where\naccess rights are predetermined by the user's job function.\n\n##### Example RBAC Usage with `loadLocalStateBulk`\n\nFor RBAC, you typically pass the action and resource without any additional attributes:\n\n```javascript\nawait permit.loadLocalStateBulk([\n  { action: 'view', resource: 'statement' },\n  { action: 'view', resource: 'products' },\n  { action: 'delete', resource: 'file' },\n]);\n```\n\nIn this example:\n\n- `action` represents the type of operation (e.g., 'view', 'delete').\n- `resource` represents the object being acted upon (e.g., 'file', 'products').\n\n#### Attribute-Based Access Control (ABAC)\n\nABAC is more dynamic than RBAC. It grants access based on user attributes, resource attributes, and environment\nconditions. This model is particularly useful when access control needs to be fine-grained.\n\n##### Example ABAC Usage with loadLocalStateBulk\n\nFor ABAC, you include additional userAttributes and resourceAttributes to specify the conditions under which access is\ngranted:\n\n```javascript\nawait permit.loadLocalStateBulk([\n  {\n    action: 'view',\n    resource: 'files_for_poland_employees',\n    userAttributes: {\n      department: 'Engineering',\n      salary: '100K',\n    },\n    resourceAttributes: { country: 'PL' },\n  },\n]);\n```\n\nIn this example:\n\n- `userAttributes` defines attributes associated with the user, such as department or salary.\n- `resourceAttributes` specifies attributes tied to the resource, like the country of operation.\n\n#### Relationship-Based Access Control (ReBAC)\n\nReBAC (Relationship-Based Access Control) determines access permissions based on the relationships between users and\nresources. This model is particularly useful when permissions need to reflect complex relationships, such as group\nmemberships or ownership of specific resources.\n\n##### Example ReBAC Usage with `loadLocalStateBulk`\n\nIn ReBAC, you not only specify the action and the resource but also include a resource instance key to identify the\nspecific instance of the resource that the relationship pertains to. This key is essential to precisely define the\naccess control based on the user's relationship to that particular instance.\n\nFor example, consider a document management system where permissions are defined based on whether a user is the owner of\na document or a member of a group that has access to it.\n\n```javascript\nawait permit.loadLocalStateBulk([\n  {\n    action: 'create',\n    resource: 'document:my_file.doc', // `document` is the resource type, `my_file.doc` is the resource instance key\n  },\n]);\n```\n\nIn this example:\n\n- `action` specifies the operation to be performed (e.g., 'create').\n- `resource` consists of two parts:\n    - `Resource type` (e.g., 'document')\n    - `Resource instance key` (e.g., 'my_file.doc')\n\nThe resource instance key (`my_file.doc` in this case) identifies the specific document that the user is allowed to\ncreate or manage based on their relationship with it.\n\nTo check permissions based on relationships in ReBAC, you can use the permit.check function. This function checks\nwhether a user has the necessary relationship to perform an action on a resource instance.\n\nFor example, to check if a user is a member of a specific group that has access to a resource:\n\n```javascript\npermit.check(userId, action, {\n  type: 'member_group', // Specifies the relationship type\n  key: group, // Specifies the particular group key\n});\n```\n\nOr, using shorthand object notation:\n\n```javascript\npermit.check(userId, action, `member_group:${group}`);\n```\n\nBy including the resource instance key and defining relationships precisely, ReBAC enables fine-grained control over who\ncan perform what actions on specific resource instances based on their relationship with those resources.\n\n#### Integrating RBAC, ABAC, and ReBAC in a Single Request\n\nThe flexibility of the loadLocalStateBulk function allows you to mix different access control models in a single\nrequest. This can be particularly powerful in applications that require a combination of role-based, attribute-based,\nand relationship-based access controls.\n\n##### Combined Example\n\nHere is how you can combine all three models in one bulk call:\n\n```javascript\nawait permit.loadLocalStateBulk([\n  // RBAC examples\n  { action: 'view', resource: 'statement' },\n  { action: 'view', resource: 'products' },\n  { action: 'delete', resource: 'file' },\n\n  // ABAC example\n  {\n    action: 'view',\n    resource: 'files_for_poland_employees',\n    userAttributes: {\n      department: 'Engineering',\n      salary: '100K',\n    },\n    resourceAttributes: { country: 'PL' },\n  },\n\n  // ReBAC example\n  { action: 'create', resource: 'document:my_file.doc' },\n]);\n```\n\nBy passing a structured array to `loadLocalStateBulk`, you can efficiently manage permissions across different models\nwithout needing separate function calls for each model type.\n\n### Applying Abilities to the Signed-In User\n\nAfter performing the necessary policy checks, the next step is to ensure that the current user is authenticated. Once\nconfirmed, you should assign the abilities returned from the checks to the user. This allows your application to enforce\nthe correct permissions based on the user's access rights.\n\n```javascript\nif (isSignedIn) {\n  getAbility(user.id).then((caslAbility) =\u003e {\n    setAbility(caslAbility);\n  });\n}\n```\n\nIf you would like to see how the normal or bulk local states should be handled in your API - refer to the `demo_server`\nfolder for a sample server configuration.\n\n## Deprecation Notices\n\n### Deprecated exports from `service.ts`\n\nThe following functions exported from `permit-fe-sdk/service` are **deprecated** and will be removed in the next major version:\n\n- `getBulkPermissionFromBE` - Use the `Permit` instance methods instead\n- `getPermissionFromBE` - Use the `Permit` instance methods instead\n- `generateStateKey` - Internal utility, will be made private\n\nThese functions were originally exposed for advanced use cases but are now considered internal implementation details.\nPlease migrate to using the `Permit()` factory function and its returned methods (`loadLocalState`, `loadLocalStateBulk`, `check`, etc.).\n\n```javascript\n// Deprecated approach (do not use)\nimport { getBulkPermissionFromBE } from 'permit-fe-sdk/service';\n\n// Recommended approach\nimport { Permit } from 'permit-fe-sdk';\nconst permit = Permit({ loggedInUser, backendUrl });\nawait permit.loadLocalStateBulk([...]);\n```\n\nFor any questions, please reach out to us in\nthe [Permit community](https://permit-io.slack.com/join/shared_invite/zt-nz6yjgnp-RlP9rtOPwO0n0aH_vLbmBQ).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpermitio%2Fpermit-fe-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpermitio%2Fpermit-fe-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpermitio%2Fpermit-fe-sdk/lists"}