> ## Documentation Index
> Fetch the complete documentation index at: https://help.lobyco.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Admin portal chain and store level access

> Scope admin portal permissions to a chain or to individual stores.

Extension of the Admin Portal's standard RBAC to support restricting access to the Promotion Platform and Loyalty Membership products for specific stores or chains.

To restrict store managers’ access to data relevant only to their stores, each manager must have a store ID assigned in their Azure AD user profile. Since store ID is a custom claim, we use Azure AD extension properties to define and embed it in the authorization token. This allows the Lobyco Portal App to retrieve the store ID on login and enforce store-level data access.

There are three access scenarios:

* **Full Access:** The admin user can view data across all chains and stores. To grant this level of access, set either `chain_ids` or `store_ids` to '\*'. If a new chain or store is added, the user automatically gains access without requiring any changes to their permissions.
* **Chain manager:** The admin user has access to data for a specific chain/chains.
* **Store manager:** The admin user has access to data for a specific store/stores.

Chain or store-level access is implemented in three steps:

<Steps>
  <Step>
    ## Extension app creation

    To create new AD app navigate to 'App registrations' section of your Microsoft Entra ID (Active Directory) and click on 'New registration' link.

    <img src="https://mintcdn.com/lobyco-4c9fb3ad/wpdZgjvGMgh4Gbhy/images/00836bb52f2d315035992a2ddb4e86f0c5ad8325.png?fit=max&auto=format&n=wpdZgjvGMgh4Gbhy&q=85&s=db138965ad31775fd63350ef3325409e" alt="" width="990" height="635" data-path="images/00836bb52f2d315035992a2ddb4e86f0c5ad8325.png" />

    Created AD app should be:

    * Recommended name: `lobycoportal-extensions-{environment}`
    * Supported account types: Accounts in this organizational directory only (Single tenant)

    Then press 'Register' button.

    <img src="https://mintcdn.com/lobyco-4c9fb3ad/wpdZgjvGMgh4Gbhy/images/c8ef2cfb083b1a7abe56a443c2ac057bb4066a30.png?fit=max&auto=format&n=wpdZgjvGMgh4Gbhy&q=85&s=2f36e87fdf755a6b036254fef5a75cf5" alt="" width="1858" height="797" data-path="images/c8ef2cfb083b1a7abe56a443c2ac057bb4066a30.png" />

    There are no strict requirements for the Description field or the Expires dropdown. Select values that best suit your needs. Once the client secret is generated, make sure to save it securely, as it will be required in the following steps.

    <Frame>
      <img src="https://mintcdn.com/lobyco-4c9fb3ad/wpdZgjvGMgh4Gbhy/images/4IeMnKSY9tL0OqNCybu2.png?fit=max&auto=format&n=wpdZgjvGMgh4Gbhy&q=85&s=399031473f8186dcd429c38b910aab54" alt="" width="1003" height="394" data-path="images/4IeMnKSY9tL0OqNCybu2.png" />
    </Frame>

    ### Assign permissions

    Next navigate to 'API permissions' and create an 'Application' level User.ReadWrite.All MS Graph permission. It is needed for this AD app to be able to assign (write) custom claim (storeId) to users (store administrators) profiles:

    <img src="https://mintcdn.com/lobyco-4c9fb3ad/wpdZgjvGMgh4Gbhy/images/621617c04bfa492c1b62017e633856f62813bda5.png?fit=max&auto=format&n=wpdZgjvGMgh4Gbhy&q=85&s=6ae7d8da8e910c26e7bc78466489624f" alt="" width="1152" height="725" data-path="images/621617c04bfa492c1b62017e633856f62813bda5.png" />

    <img src="https://mintcdn.com/lobyco-4c9fb3ad/wpdZgjvGMgh4Gbhy/images/2ddf28920cd881229ab0d78d53d8fbd7b739eb79.png?fit=max&auto=format&n=wpdZgjvGMgh4Gbhy&q=85&s=ec1c5379ca7a1d6e36dbaf9346adc1ee" alt="" width="1124" height="546" data-path="images/2ddf28920cd881229ab0d78d53d8fbd7b739eb79.png" />

    ### Modify manifest

    Next navigate to 'Manifest' section in your app and change acceptMappedClaims property to true and accessTokenAcceptedVersion property to 2

    <img src="https://mintcdn.com/lobyco-4c9fb3ad/wpdZgjvGMgh4Gbhy/images/e9178260585dd12bf0538918df82b1052b775d0d.png?fit=max&auto=format&n=wpdZgjvGMgh4Gbhy&q=85&s=c1494bb8d56a647f4d42f2a25d86dbef" alt="" width="1822" height="797" data-path="images/e9178260585dd12bf0538918df82b1052b775d0d.png" />

    ### Add extension properties

    Add chain\_ids, store\_ids extension properties to the created extension app.

    First get the token with permissions by navigating in Azure AD Users section and pressing Refresh link and then grabbing it from the \$batch request headers.

    <img src="https://mintcdn.com/lobyco-4c9fb3ad/wpdZgjvGMgh4Gbhy/images/a054710bb2ae401ec24fdb6abd2d7674cd5e0457.png?fit=max&auto=format&n=wpdZgjvGMgh4Gbhy&q=85&s=3455acb5079953e0c9903c32ef00f618" alt="" width="1240" height="590" data-path="images/a054710bb2ae401ec24fdb6abd2d7674cd5e0457.png" />

    **Url:** `POST https://graph.microsoft.com/v1.0/applications/{extension app object id}/extensionProperties`

    **Request headers:**

    ```
    Content-Type: application/json 
    Authorization: Bearer {token received from step above}
    ```

    **Body:**

    ```json theme={"system"}
    {
     "name": "store_ids",
     "dataType": "string",
     "isMultiValued": true,
     "targetObjects": ["User"]
    }
    ```
  </Step>

  <Step>
    ## Configure Lobyco Portal enterprise application to map custom claims

    Click on Enterprise application menu item and search for the service principal: `{client_name}-lobycoportal-{environment}`. Navigate to 'Single sign-on' tab.

    <Frame>
      <img src="https://mintcdn.com/lobyco-4c9fb3ad/wpdZgjvGMgh4Gbhy/images/6o4ixzvUEnMX5jg7mnmL.png?fit=max&auto=format&n=wpdZgjvGMgh4Gbhy&q=85&s=b71d53e3681506bd5b85f59d2c1a7bd9" alt="" width="1531" height="748" data-path="images/6o4ixzvUEnMX5jg7mnmL.png" />
    </Frame>

    Press 'Edit' button and then 'Add new claim' button.

    <img src="https://mintcdn.com/lobyco-4c9fb3ad/wpdZgjvGMgh4Gbhy/images/e207309e1a828c94ec5a3b3360d0e696831567aa.png?fit=max&auto=format&n=wpdZgjvGMgh4Gbhy&q=85&s=d64f9ec491d9fdd1e9f2daad908c7ec9" alt="" width="1823" height="521" data-path="images/e207309e1a828c94ec5a3b3360d0e696831567aa.png" />

    <img src="https://mintcdn.com/lobyco-4c9fb3ad/wpdZgjvGMgh4Gbhy/images/33bf2420297b25280ef99cd7f834a6dff995b54a.png?fit=max&auto=format&n=wpdZgjvGMgh4Gbhy&q=85&s=43c25bb083eec8d3845ca4ca67665e1a" alt="" width="1817" height="667" data-path="images/33bf2420297b25280ef99cd7f834a6dff995b54a.png" />

    Make sure both `chain_ids` and `store_ids` claims are added and saved.
  </Step>

  <Step>
    ## Assign values to Azure AD users

    Go to Microsoft Entra ID -> All users . Type user email and navigate to user profile to extract User Object ID. Later it will be used get/assign user attributes via Postman.

    <img src="https://mintcdn.com/lobyco-4c9fb3ad/wpdZgjvGMgh4Gbhy/images/40e22c4dac1f24d056f3005c0ad9a3187f004419.png?fit=max&auto=format&n=wpdZgjvGMgh4Gbhy&q=85&s=69842626745b8dbec3070e67553ff575" alt="" width="1124" height="546" data-path="images/40e22c4dac1f24d056f3005c0ad9a3187f004419.png" />

    1. Copy the collection JSON from the [Postman collection](/integration/quick-start/admin-portal-chain-and-store-level-access/postman-collection) page and save it as a `.json` file.
    2. Open Postman and import the saved collection.
    3. Navigate to the collection's **Variables** tab and provide values for the following variables. After entering the values, make sure to press the **Save** button.

    | Variable name                        | Description                                                       |
    | ------------------------------------ | ----------------------------------------------------------------- |
    | tenant\_id                           | Tenant ID where store managers' user profiles are located         |
    | extension\_app\_id                   | Client ID of the previously created extension app                 |
    | extension\_app\_id\_without\_hyphens | The same ID as above, but with hyphens removed                    |
    | extension\_app\_secret               | Secret for the extension app                                      |
    | user\_object\_id                     | Object ID of the user to whom store or chain IDs will be assigned |

    4. Call imported collection endpoint in specified sequence:

       * **Step 1: Get extension app token:** Retrieves an access token using the extension app’s credentials, this step is a technical prerequisite for Steps 2 and 3, as the token is required to authenticate both requests.
       * **Step 2: Get user attributes:** Fetches the attributes of the target user to verify the user object and claim structure.
       * **Step 3: Assign custom claim to the user:** Sends a PATCH request to assign store\_ids or chain\_ids to the specified user. **Important:** The values used for store\_ids and chain\_ids must exactly match the IDs already imported into the Store Service. Example: providing access to single store with ID '12'

           <img src="https://mintcdn.com/lobyco-4c9fb3ad/wpdZgjvGMgh4Gbhy/images/f4216baa80be760eae41342596668c57b7e2ae39.png?fit=max&auto=format&n=wpdZgjvGMgh4Gbhy&q=85&s=0d9499d5a8be19e9ccfdcb2fa28e496f" alt="" width="1176" height="765" data-path="images/f4216baa80be760eae41342596668c57b7e2ae39.png" />

    Payload example to provide access to single chain with ID '1':

    ```json theme={"system"}
    {
        "extension_{{extension_app_id_without_hyphens}}_chain_ids": ["1"]
    }
    ```

    Payload example to provide access to multiple stores:

    ```json theme={"system"}
    {
        "extension_{{extension_app_id_without_hyphens}}_store_ids": ["12", "13"]
    }
    ```

    If access is later required for an additional store (for example, store ID 14), all store IDs must be specified in the list, not only the new one.

    ```json theme={"system"}
    {
        "extension_{{extension_app_id_without_hyphens}}_store_ids": ["12", "13", "14"]
    }
    ```

    To remove access from a specific store, its ID must simply be omitted from the list while all remaining store IDs are retained.

    * **Step 4: Get user attributes again:** Repeat Step 2 to verify that the custom claims were successfully assigned.

          <img src="https://mintcdn.com/lobyco-4c9fb3ad/wpdZgjvGMgh4Gbhy/images/eff6cc4b23e19c1991d23228af75f92beaadb278.png?fit=max&auto=format&n=wpdZgjvGMgh4Gbhy&q=85&s=4416858aba9002a134031c999304b360" alt="" width="724" height="440" data-path="images/eff6cc4b23e19c1991d23228af75f92beaadb278.png" />

    <Warning>
      **Important:** After assigning new claims to the user, they must re-login for the changes to be reflected in the token.
    </Warning>

    If a user logs into the Lobyco Portal but does not see any store-related data, [inspect the authorization token](/integration/quick-start/admin-portal-chain-and-store-level-access/troubleshooting-verifying-claims-in-the-auth-token).

    Verify that the expected claim (`store_ids` or `chain_ids`) is present and correctly populated. If the claim is missing, review the steps above to ensure it was assigned properly.
  </Step>
</Steps>
