## Entitlements quickstart Harness the power of Frontegg's robust Entitlements Engine directly into the heart of your React application, allowing you to effortlessly implement sophisticated, role-based, and attribute-based access controls with just a few lines of code. br Prerequisites @frontegg/js@6.175.0 br ### Configuring Entitlements with Vanilla JS Use the following code to configure entitlements with Vanilla JS. See [`contextOptions`](/ciam/sdks/components/fronteggappoptions#contextoptions) for more information. ```typescript import { initialize } from "@frontegg/js"; const app = initialize({ contextOptions: { baseUrl: //.. , clientId: //.. , }, entitlementsOptions: { enabled: true, }, }); ``` See [`entitlementsOptions`](/ciam/sdks/components/fronteggappoptions#entitlementsOptions) for more information. br Entitlements functions An exception will be thrown if you don’t enable entitlements and try to use the functions. ### Entitlements functions The following functions can be used after configuring Entitlements with `@frontegg/js`. - `useFeatureEntitlements` - checks whether a user is entitled to feature access. - `usePermissionEntitlements` - checks whether a user is entitled to permission. - `useEntitlements` - checks whether a user is entitled to a feature or permission. ### Custom attributes Frontegg allows you to create **custom attributes** for users (learn more about creating [custom attributes](/ciam/guides/authorization/entitlements/feature-based/feature-flags#attributes-for-targeting)). Attributes can be used for [Feature Flagging](/ciam/guides/authorization/entitlements/feature-based/feature-flags) purposes and in Entitlement API calls within a `customAttributes` object. The `customAttributes` object is optional and comprised of key-value pairs with possible values of `string | number | boolean | Date`, like so: br ```typescript app.getFeatureEntitlements('feature-x', { attr1: 'val1', attr2: 'val2' }); ``` br ```typescript import { Entitlement, CustomAttributes } from '@frontegg/types'; getFeatureEntitlements(key: string, customAttributes?:CustomAttributes) => Entitlement getPermissionEntitlements(key: string, customAttributes?:CustomAttributes) => Entitlement getEntitlements(options: EntitledToOptions, customAttributes?:CustomAttributes) => Entitlement ``` br ### Using the `subscribeStateChanged` function Under the hood, Frontegg uses `redux` to manage our state. When using redux’s `store.subscribe`, redux doesn’t promise that the callback will be called when changes happen ("...Redux adds a change listener. It will be called any time an action is dispatched, and some part of the state tree **may potentially** have changed" [redux docs](https://redux.js.org/api/store#subscribelistener)), so we encourage that you use `subscribeStateChanged` to ensure that the callback performs when changes occur. The following example shows how to use exposed functions for user subscription to receive store updates: br ```typescript app.store.subscribeStateChanged((state) => { if (state.auth.isAuthenticated) { const { isEntitled: isFeature1Entitled, justification: justificationFeature1, } = app.getFeatureEntitlements("feature1"); const { isEntitled: isPermission1Entitled, justification: justificationPermission1, } = app.getPermissionEntitlements("permission1"); const { isEntitled: isFeature2Entitled, justification: justificationFeature2, } = app.getEntitlements({ featureKey: "feature2" }); const { isEntitled: isPermission2Entitled, justification: justificationPermission2, } = app.getEntitlements({ permissionKey: "fe.connectivity.*" }); } }); ``` br A full example including HTML: br ```typescript
Feature 1 entitled UI
Feature 1 NOT entitled UI
; ``` ```typescript app.store.subscribeStateChanged((state) => { const isAuthenticated = state.auth.isAuthenticated; let styleHtml = ""; if (isAuthenticated) { styleHtml += '[fe-state="isAuthenticated"] { }'; styleHtml += '[fe-state="!isAuthenticated"] { display: none; }'; } else { styleHtml += '[fe-state="isAuthenticated"] { display: none; }'; styleHtml += '[fe-state="!isAuthenticated"] { }'; } if (isAuthenticated) { const { isEntitled, justification } = app.getFeatureEntitlements( "feature1" ); if (isEntitled) { styleHtml += '[fe-state="isEntitled"] { }'; styleHtml += '[fe-state="!isEntitled"] { display: none; }'; } else { styleHtml += '[fe-state="isEntitled"] { display: none; }'; styleHtml += '[fe-state="!isEntitled"] { }'; } } style.innerHTML = styleHtml; }); ``` br Note that `subscribeStateChanged` is called for every store change. If you want to call `subscribeStateChanged` for specific changes only, then you can do the following: br ```typescript let previousEntitlementsState; app.store.subscribeStateChanged((state) => { const entitlementsState = state.auth.user?.entitlements; if (entitlementsState !== previousEntitlementsState) { previousEntitlementsState = entitlementsState; console.log("entitlements change - do something"); } }); ``` br ### Load on demand You can also load entitlements on demand by using the `loadEntitlements` function, exposed from the `FronteggApp`: ```typescript app.loadEntitlements(); ``` br You can then pass a callback to let you know that the request was completed: ```typescript app.loadEntitlements((isSucceeded) => console.log(`request ${isSucceeded ? 'succeeded' : 'failed'}`)) ```