How to add Power Virtual Agent (PVA) Bot to a SharePoint page?


As you know the Power Virtual Agent (PVA) is a low-code and no-code solution. It is very easy to create a Bot quickly. Now, if you want this bot on the SharePoint page. There are a few options and their pros & cons.

In this article, I am going to list out all options. I will share the pros and cons of each option and share code where needed. This will help you guide your journey for a similar requirement.


There are a few prerequisites, based on which option you pick you will need to get one or more of the following resources.

  1. Power Platform Environment – Required for all options
  2. SharePoint Online tenant – Required for all options
  3. Visual Studio – Required for Options # 2
  4. Azure Web App & Azure Front Door– Required for Options # 2
  5. Visual Studio Code  – Required for Options # 3
  6. SharePoint Framework Development (SPFx) Environment Setup – Required for Options # 3

Below are the three options:

Option # 1: Put embedded code from the bot on an IFRAME on the SharePoint page.


  • Easy and quick
  • Easy to get embed code from the PVA Bot Channels.
  • Easy step to add the IFRAME on the SharePoint page


  • The embed code has the code and the token is exposed as public for the content owner. If this code with url is leaked anyone from outside of the organization network can access the Bot. If this Bot is meant to be internal to organization then this option will not work.

Option # 2: Use DirectLine (DL) Secret and get DL Token from Azure Web Site URL for IFRAME on the SharePoint page.

Basically, in this approach, the IFRAME will be still used on the SharePoint page. But the URL for the IFRAME will be from the internally controlled Web Site URL which will be blocked from public access using IP restrictions. The internal website will be configured with the Direct Line Secret. The website will get the Direct Line Token for doing secured communication with the Bot.


  • The bot will NOT be accessed by the public. It will be restricted by the website for the internal IP range only. Even if the URL is leaked it will be blocked by the IP Restriction on the Azure Front Door.
  • It used the Bot’s direct line Token as a protected communication mechanism.


Option # 3: Create an SPFx Application Customizer to put on the SharePoint page.


  • The bot will not be exposed to the public. The Direct Line Secret will be buried in the SPFx code & can not be seen


  • There is SPFx web part development and in future for maintenance (if needed).

Step By Step Solution:

Option # 1:

The following two steps will get your Bot on the SharePoint page quickly.

  1. This is an easy solution. All you need to do is to get the embed code from the Bot. Follow here.
  2. Once you get the code you add this to your SharePoint page. Follow here.

Option # 2:

This option will use Azure Web App and Azure Front Door. The Azure Front Door will allow to restriction of IP within the organization.

The Azure Web App is the ASP.NET Core solution. There are two components in the website, one is to UI and the other is API. The UI part is to show the Web Chat and API is to get the Direct Line Token from the Secret. The Direct Line Secret is stored in the configuration of the website or can be secured using a key vault.

TODO: Code to follow.

Option # 3:

TODO: Code to follow.


Based on the above article’s options and their pros and cons you will be able to decide what is right for your need. Option #1 is very easy and quick to Option # 3 to get modern ways to block the access.

Some helpful links for Bot development

Posted in Technical Stuff | Leave a comment

The tenant-wide flag DisableCustomAppAuthentication in relation to Access Control System (ACS)?


If you have used the Access Control System (ACS) and using its APP ID and APP Secret in the PnP.PowerShell module it may not work.

The Connect-PnPOnline will work fine but when I try to get any command to make it work you will get the following (401) Unauthorized error. I have given Full Control for the Site Collection.

PS C:\WINDOWS\system32> Get-PnPList -Connection $conn1
Get-PnPList : The remote server returned an error: (401) Unauthorized.
At line:1 char:1
+ Get-PnPList -Connection $conn1
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : WriteError: (:) [Get-PnPList], WebException
    + FullyQualifiedErrorId : EXCEPTION,PnP.PowerShell.Commands.Lists.GetList

PS C:\WINDOWS\system32>  
<AppPermissionRequests AllowAppOnlyPolicy="true">
	<AppPermissionRequest Scope="http://sharepoint/content/sitecollection" Right="FullControl"/>

So, what is going on?

The answer lies in the tenant-wide flag “DisableCustomAppAuthentication”. This is because ACS is retired, and it should not be used for the new application. It is still supported for backward compatibility, but it is recommended use the “Sites.Selected” permission.

Set-SPOTenant -DisableCustomAppAuthentication $false

After disabling the above flag the PnP command works.


You can fix the ACS mechanism for your app temporarily, but it is “highly” recommended that you migrate the code to the new Authentication on the Azure AD.

Please see the following article for the “Sites.Selected” permission.

How does the MS Graph “Sites.Selected” permission work for granular permissions for SPO sites? | Pankaj Surti’s Blog

Posted in Technical Stuff | Leave a comment

How to get a list of Site Collection Admins for a SharePoint site?


My customer had a requirement to get the list of Site Collection Admins (SCAs) for any site within the tenant for anyone in the organization. The need of the user is to find additional information from the SCA.

This request can be on-demand from any user within the organization. The resolution is to have a tool for a user to request a site URL. Using the user’s Site URL request the tool can find out the SCAs for the site. The tool will fill out the Multi People field for the same request.

This tool as “Find SCAs Tool”


  • “FindSCARequestTracker” SharePoint List
  • Azure Logic
  • Azure Function
  • PnP.PowerShell

Step By Step Solution

Step # 1 : Create a “FindSCARequestTacker” SharePoint List

Internal NameDisplay NameColumn Type
TitleSite URLSingle line of text
ListOfSCAList Of SCAsMulti People field
StatusStatusRead Only – Choice field with New & Completed

The Status field default value is “New”.

Step # 2: “ProcessFindSCARequestTracker” Logic App

The logic app will trigger on items created or modified for the above SharePoint list. The trigger condition for this is to check only trigger the flow when the Status field is New.


There are only two actions in the flow. The first action is to make a call to an HTTP Trigger Azure Function. The second call is to Update the SharePoint item. The update is updating the “Status” field as Completed and the “ListOfSCA” field with the results from the Aure Function.

The Logic App with the two main actions.

Step # 3: “find-sca-by-site” Azure Function.

The “find-sca-by-site” Azure Function is set as an HTTPTriggered function. The input to the to the call is the JSON value with the Site URL. The output of this function is also JSON with the Claims array with the email address of the SCAs.

NOTE: You can refer to my previous post to set up Azure Function and Certificate. How to set up certificate in MAG Azure Function App for PnP.PowerShell?

NOTE: To get to the code for the above Azure function, please click here.

Please make sure the Azure AD app you create has the following permissions.

The Azure AD required permissions


The results after the Azure Logic App and Azure Function are executed for a request.


With help of the Azure resource to get the list of Site Collections Admins can be created as a Tool. This will help reduce SPO admins’ tasks and the tools can provide information on what a user needs.

Posted in Azure, PnP.PowerShell, SharePoint | Leave a comment

How to automate and govern the “Sites.Selected” permissions using a custom tool?


Earlier, I posted an article regarding the “Sites.Selected” MS Graph permission to create the granular permissions for sites. The following is the link for the article.

How does the MS Graph “Sites.Selected” permission work for granular permissions for SPO sites?

This is all great that granting and revoking “granular” permission for reading or writing for the site can be controlled by the Admins. However, there are some gaps such as how the governance can be maintained. It is the Admin’s additional task to execute the scripts and to maintain the list of the Azure AD applications, sites, and permissions. Additionally, based on the tenant size and to execute the users’ requests to get access to sites can be Admins nightmare.

This article will address the above weaknesses by giving you steps to design and develop a tool to maintain the users’ requests. Also will guide you to automate the granting and revoking sites permissions.

I named the tool Sites Selected Request Tracker (SSRT)


The following resources are required for the tool.

  1. Pnp.PowerShell – The PnP.PowerShell is used in the Azure Function to maintain the tracker list.
  2. Two SharePoint Lists – The SharePoint lists are required to track the list of Azure AD application IDs and the users’ permission requests.
  3. Azure Logic Apps – The Azure Logic Apps is required to trigger a flow on the request tracker list’s create or modify. Based on the grating or revoking trigger change it will also make a call to Azure Function.
  4. Azure Function – The Azure Function is required to execute the Grant and Revoke using the PnP.PowerShell. This is the real engine that will automate the task.
  5. Azure Key Vault – The Aure Key Vault is needed to store the Certificates for the Azure AD app. Please read the previous article for more information.

Architecture Diagram

The logical architecture diagram for the SSRT tool.

Architecture Diagram for the Sites Selected Request Tracker (SSRT)
Architecture Diagram for the Sites Selected Request Tracker (SSRT)

SharePoint List One – CustomerAppIDs Columns

This first list will have the list of all Azure AD apps (consented “Sites.Selected” permission). You can use the client secret or certificate. It is recommended to use the certificate for each Azure AD app.

Internal NameDisplay NameColumn Type
TitleApp ID GUIDSingle line of text
AppNameApp Display NameSingle line of text
SharePoint List One – CustomerAppIDs Columns

SharePoint List Two – SitesSelectedTracker Columns

This is the second list which keeps the track of the all the requests for sites. After adding the Azure AD app information in the first list, the Admins will add the sites for a specific Azure AD application with the Read or Write selection. Whenever the Admins makes change the item to Revoke the Logic App will revoke and delete the item from the tracker list.

Internal NameDisplay NameColumn TypeDescription
1TitleSite URLSingle line of textTo store url needs perms
2ApplicationIDApplicationIDLookupReference to app id and AppName columns from the above list.
3ReadWriteRead Or WriteChoiceRead or Write Choice. Default as Read.
4GrantRevokeGrant Or RevokeChoiceGrant or Revoke choice. Default as Grant
5ReadWriteCopyReadWriteCopySingle line of textUsed internally for the flow. Hidden from the user. Default is None
6GrantRevokeCopyGrantRevokeCopySingle line of textUsed internally for the flow. Hidden from the user. Defaultis Grant.
7RecordEngineStepsRecordEngineStepsEnhanced rich textUsed internally for the flow. Hidden from the user to enter. Engine uses to add steps description.
SharePoint List Two – SitesSelectedTracker Columns

“ProcessReadWrite” Azure Logic Apps

  • The Logic Apps triggers on the item create or modified on the SitesSelectedTracker.
  • Trigger conditions is
    • To Check ReadWrite to ReadWriteCopy are not equal OR
    • To Check GrantRevoke to GrantRevokeCopy are not equal.
  • If the above condition is met then the Azure Logic App makes a call to the “SPOSiteSelected” Azure Function with the following parameters.
# The following request body is passed to the Azure Function.
  "Action": "@{triggerBody()?['GrantRevoke']?['Value']}",
  "ClientAppID": "@{triggerBody()?['ApplicationID']?['Value']}",
  "DisplayName": "@{triggerBody()?['ApplicationID_x003a_AppName']?['Value']}",
  "Permission": "@{triggerBody()?['ReadWrite']?['Value']}",
  "SiteURL": "@{triggerBody()?['Title']}"

NOTE: To get to the code for the above Azure function, please click here.

“SPOSitesSelected” HTTPTriggered Azure Function

NOTE: You can refer to my previous post to set up Azure Function and Certificate. How to setup certificate in MAG Azure Function App for PnP.PowerShell?

NOTE: To get to the code for the above Azure function, please click here.


As described Sites Selected Request Tracker (SSRT) tool, it addresses the governance and automation issues for the “Sites.Selected” permission.

There is a PnP Sample WebPart for something you may want to explore which may meet your need.

Sites Selected Admin client-side web part

Posted in Azure, PnP.PowerShell, SharePoint | 1 Comment

How to resolve “The attempted operation is prohibited because it exceeds the list view threshold.” for Remove-PnPWeb?


A customer got the following error for removing a sub-site.

PS C:\Temp> Remove-PnPWeb -Identity testcaa -Force
Remove-PnPWeb : The attempted operation is prohibited because it exceeds the list view threshold.
At line:1 char:1
+ Remove-PnPWeb -Identity vacaa -Force
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : WriteError: (:) [Remove-PnPWeb], ServerException
    + FullyQualifiedErrorId : EXCEPTION,PnP.PowerShell.Commands.RemoveWeb

PS C:\Temp>

Clearly, the issue was due to a large list or lists present in the sub-site. Since the entire subsite needs to be deleted with the large list, to eliminate the above error the large list must be deleted first.

The following code can be useful to remove the items from the large list and it allowed to delete the list. Once all large lists were deleted the subsite was successfully deleted.

$action = "Delete"
# TODO Change your site or subsite URL
$siteUrl = https://[YOUR TENANT]
# TODO Change the list name 
$listName = "Contoso Community Care Data" 
Connect-PnPOnline –Url $siteUrl -UseWebLogin
$Stoploop = $false
[int]$Retrycount = "0"

write-host $("Start time " + (Get-Date))
do {
  try {

    if($action -eq "Delete")
      $listItems= Get-PnPListItem -List $listName -Fields "ID" -PageSize 1000  
      $itemIds = $lisItems | Foreach {$_.Id}
      $itemCount = $listItems.Count
      while($itemCount -gt 0)
        $batch = New-PnPBatch
        #delete in batches of 1000, 
        #if itemcount is less than 1000 , all will be deleted 
        if($itemCount -lt 1000)
          $noDeletions = 0
          $noDeletions = $itemCount -1000
        for($i=$itemCount-1;$i -ge $noDeletions;$i--)
          Remove-PnPListItem -List $listName -Identity $listItems[$i].Id -Batch $batch 
        Invoke-PnPBatch -Batch $batch
        $itemCount = $itemCount-1000
   Write-Host "Job completed"
   $Stoploop = $true

  catch {

    if ($Retrycount -gt 3){

       Write-Host "Could not send Information after 3 retrys."

       $Stoploop = $true


    else {

      Write-Host "Could not send Information retrying in 30 seconds..."

      Start-Sleep -Seconds 30

      Connect-PnPOnline –Url $siteUrl -interactive

      $Retrycount = $Retrycount + 1

While ($Stoploop -eq $false)
write-host $("End time " + (Get-Date)) 


To delete any site the large lists items and list must be deleted first. Once that is done the site or subsite can be deleted.


PnP Batch Add or Delete items from very large list, i.e. more than 300k items – Microsoft Tech Community

The fastest way to create SharePoint list items – Waldek Mastykarz

Posted in SharePoint, SharePoint 2010, SharePoint 2013 | Leave a comment

How does the MS Graph “Sites.Selected” permission work for granular permissions for SPO sites?


To provide granular access for the sites the Azure Access Control (ACS) was used in the past. The app id and secret can be created using the add-ins, more info is described here. Note: Please check ACS retirement info.

Now with the new Sites.Selected MS Graph permission you can use the granular level permission. This blog post is just to simplify and demonstrate the use of PnP PowerShell to create granular permissions.

For example, if the customer wants to have access to a few sites as a read permissions the “Site.Selected” permission techniques can be used to meet the need.

Step by Step Solution

Step # 1 Create Azure AD app with MS Graph Sites.FullControl.All permission

NOTE: Make sure you select MS Graph not SharePoint, as it also has the same permission but that is not valid.

Please make a note of the application id.

Admin App

Step # 2 Create Azure AD app with MS Graph Sites.Selected permission

Add SharePoint Sites.Selected permission also if you are using PnP.PowerShell.

Step # 3 Create a PFX and CER certificate using PnP PowerShell.

New-PnPAzureCertificate -OutPfx pnpSites-Selected.pfx -OutCert pnpSites-Selected.cer -CertificatePassword (ConvertTo-SecureString -String "pass@word1" -AsPlainText -Force)

The above command will create two files, store them in the known directory.

Step # 4 Upload the CER file to the Azure AD app created in Step #1 i.e. Admin app.

Step # 5 Using PnP PowerShell command Grant-PnPAzureADAppSitePermission

$adminAppId = "9a6f4c8a-e9cf-44fd-b3ad-4413ed66a2ce"; #admin-app TODO to replace
$clientAppId = "ca2a60c7-d09a-4875-841b-117a02b504fd"; #client-app

$tenantPrefix = "M365x162783"; # replace with your tenant id TODO to replace
$tenantName = $tenantPrefix +"";
$spoTenantName = "https://" + $tenantPrefix + "";

# site to apply granular permission, 
# it can be repeated for more than one sites
$site2apply = ""

$password = (ConvertTo-SecureString -AsPlainText 'pass@word1' -Force)

$adminConn = Connect-PnPOnline -Url $spoTenantName -ClientId $adminAppId -CertificatePath 'c:\Temp\pnpSites-Selected.pfx' -CertificatePassword $password  -Tenant $tenantName

#### GRANT
Grant-PnPAzureADAppSitePermission -AppId $clientAppId -DisplayName "Thisapp" -Permissions Read -Site $site2apply -Verbose

Step # 6 To check the client app has an access to read lists of the site

$clientAppId = "ca2a60c7-d09a-4875-841b-117a02b504fd"; #client-app

$tenantPrefix = "M365x162783"; # replace with your tenant id TODO to replace
$tenantName = $tenantPrefix +"";

$site2apply = ""

$clientConn = Connect-PnPOnline -Url $site2apply -ClientId $clientAppId -CertificatePath 'c:\Temp\pnpSites-Selected.pfx' -CertificatePassword $password  -Tenant $tenantName


Click here to see the code for how to read all lists using non-PnP command i.e. REST calls.

Step # 7 To change the permission from “Read” to “Write”.

NOTE: The following code is an extension from the above code variables set in the above steps.

#### GET
$perms = Get-PnPAzureADAppSitePermission -Site $site2apply

#### SET
Set-PnPAzureADAppSitePermission -Site $site2apply -Permissions Write -PermissionId $perms.Id

Step # 8 To revoke the permission.

NOTE: The following code is an extension from the above code variables set in the above steps.

#### GET
$perms = Get-PnPAzureADAppSitePermission -Site $site2apply

Revoke-PnPAzureADAppSitePermission -Site $site2apply -PermissionId $perms.Id


The granular access to sites using Sites.Selected can be achieved using the PnP.PowerShell module.

Please see the next follow up article.

I have used code REST related call in Step # 6 from Srinivas’s blog

Use Microsoft Graph to Set Granular Permissions to SharePoint Online Sites for Azure AD Application – DEV Community

Controlling app access on a specific SharePoint site collections is now available in Microsoft Graph – Microsoft 365 Developer Blog

Posted in PnP.PowerShell, SharePoint | 4 Comments

How to get raw data from PFX certificates?


This article will show the step-by-step PowerShell commands to read the raw data from the certificate.

Prerequesite is you need to create a sample PFX file. It is very easy to create such files using the PnP Powershell module.

## create C:\Certs and run the following command.

New-PnPAzureCertificate -OutPfx wildcard.pfx -OutCert wildcard.cer -CertificatePassword (ConvertTo-SecureString -String "pass@word1" -AsPlainText -Force)
# the following command will be used to read the PFX file and get the cert value.

$pfxPath = "C:\Certs\wildcard.pfx"
$pfxPass = "pass@word1"
$stsCertificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 $pfxPath, $pfxPass, 20
$binCert = $stsCertificate.GetRawCertData()
$credValue = [System.Convert]::ToBase64String($binCert)

Now using the above $credValue you can use to connect to the PnP Online. Assuming you have created an Azure AD app, added the required permissions, and added the above-created cert to the app.

$HashArgs = @{
    Url = ""
    ClientId = "GUID-OF-AAD-APP"
    CertificateBase64Encoded = $certValue
    Tenant  = "
$conn = Connect-PnpOnline @HashArgs -ReturnConnection


An easy and simple way to securely connect to the SPO tenant or site using PnP

Posted in PnP.PowerShell, SharePoint, Technical Stuff | Leave a comment

Application Lifecycle Management (ALM) for Power Platform (PP) 2 of 3

Application Lifecycle Management (ALM) for Power Platform (PP) 1 of 3

Application Lifecycle Management (ALM) for Power Platform (PP) 3 of 3

You will have two build pipelines and one release pipeline.

1. Create two build pipelines

Follow the following steps to create a pipeline.

Click on Newpiple

Select the “Use the classic editor” link

Select Azure Repos Git. Select the Team project, Repository, and branch main.

Select “Empty Job”

Name the pipeline

2. Add SolutionName as Build variable

Set the variable as SolutionName for build and release pipelines.
Select “Selectable at queue time” and “Selectable at release time”

3. Create “Export Dev Solution” Build pipeline

Export Dev Solution Build pipeline

Please make sure you have “Allow scripts to access the OAuth token” is checked for the Agent Job.

** Use the values from here to put in the actions input **

Power Platform Export Solution 
Solution Name : $(SolutionName)
Solution Output File : $(Build.ArtifactStagingDirectory)\$(SolutionName).zip

Power Platform Unpack Solution 
Solution Input File = $(Build.ArtifactStagingDirectory)\$(SolutionName).zip
Target Folder to Unpack Solution : $(Build.SourcesDirectory)\$(SolutionName)

Command Line Script

Display name: Command Line Script

Script :
echo commit all changed
git config ""
git config "Automatic Build"
git checkout main
git add --all
git commit -m "solution init"

echo push code to new repo
git -c http.extraheader="AUTHORIZATION:bearer $(System.AccessToken)" push origin main

To make the above script work you must give the contribute allow access to the Build service under project settings. 
Please refer to 1 of 2 (Prerequisites) step # 6 "Add Build Service as Contribute Allow permission for the new repository"

4. Create “Build QA Environment FilesBuild Pipeline

Build QA Environment Files
Power Platform Pack Solution 

Source Folder of Solution to Pack = $(Build.SourcesDirectory)\$(SolutionName)
Solution Output File = $(Build.ArtifactStagingDirectory)\$(SolutionName).zip
Type of Solution : Unmanaged

Power Platform Import Solution 
Solution Input File = $(Build.ArtifactStagingDirectory)\$(SolutionName).zip

Power Platform Export Solution 
Solution Name : $(SolutionName)
Solution Output File : $(Build.ArtifactStagingDirectory)\$(SolutionName)

Publish Artifact: drop

Path to publish = $(Build.ArtifactStagingDirectory)
Artifact name = drop
Artifact publish location = Azure Pipelines

Reference: Predefined variables – Azure Pipelines | Microsoft Docs

5. Create Release to production

To create release pipeline follow the steps.

Click on Pipelines->Rlease.

Click on “New pipeline”

Select “Empty Job”

Select “Add an artifact”

Select Project.

Select Source (build pipeline) as “Build QA Environments”

Select Default version as “Latest”

Type Source alias as “Build”

Add an artifact

Now select Stage 1 and add two shown actions.

Release to production
Power Platform Import Solution 
Service connection: PROD

Solution Input File = $(System.DefaultWorkingDirectory)/Build/drop/$(SolutionName)

The following code can be used in your Power Apps to extract the environment variable.

        txtEnvVar: LookUp(
            'Environment Variable Values',
            'Environment Variable Definition'.'Schema Name' = "new_RuntimeEnvironment"

To Change the environments variables for the managed solution.

The managed solution will be in locked mode and you will not be able to change the environment variables. The following are the steps to change the environments variables.

Navigate to the PROD environments using Power Platform Admin Center

Click on the Tables under Dataverse on the left side menu

Search for ‘Environment Variable Value’

‘Environment Variable Value’ table

Click on the ‘Environment Variable Value’ table and navigate to the ‘Data’ tab (as shown below)

Click on the Data tab
Click on Edit to change the value and click Save & Close

For more details follow the following lab materials.

Microsoft Power Platform Build Tools for Azure DevOps

Microsoft Power Platform Build Tools for Azure DevOps – Power Platform | Microsoft Docs

Application Lifecycle Management (ALM) for Power Platform (PP) 3 of 3

Posted in Power Apps, Power Apps, Power Automate | 1 Comment

Application Lifecycle Management (ALM) for Power Platform (PP) 1 of 3

This is a three-part series of blog articles. Part1 (this one) article covers prerequisites to set up ALM in Azure DevOps. Part2 article covers the Power Platform Build Tools to build and deploy the solution. Part3 article covers the  Microsoft Power Platform CLI to build and deploy the solution.

For both Part2 or Part3 approaches, you will need the following steps completed as a prerequisite. From numbers 1 to 5 you will need as a prerequisite for both approaches.

If you are following the Part2 approach you will additionally need numbers 6 and 7 as a prerequisite.


1. Create a free Azure DevOps subscription.

Follow this article to get a free five-user Basic Plan Azure Subscription.

Azure DevOps Basic Plan is free for up to 5 users

2. Create three Power Platform Environments for DEV, PRE PROD, and PROD.

The three power platform environments.

3. Create an Azure AD app

Create an Azure AD app with the permissions

Need following delegated permissions and consented by Global Admin

  • Dynamic CRM / user_impersonation / Access Common Service as organization users
  • PowerApps Runtime Service / user_impersonation / Common Data Service
  • PowerApps.Advisor / Analysis.All

Note: Save the ClientId, ClientSecret & TenantId information of the Azure AD app. You will need this later.

4. Add Application users to the Power Platform environment

Navigate to Power Platform Admin Center using

Click on the environment name. Click on Settings

Select Users + permissions and click on Application users

Click on New app user then click on Add an app

Select the Azure AD app created from the above step. Click Add and next screen click Create.

Add application users to Power Platform Environments

Using the above created Azure AD app add the application user for the Power Platform. Set the role as System Administrator. This application user will be used in the automation of the build and release pipelines.

5. Add Build Service as Contribute Allow permission for the new repository

Click on Project Settings

Click on Repositories under Repos

Select the repository in this case CRM446838

Select Security tab

Select the “{Project name} Build Service (pankajsurti)” Note: your project name and user name will be different.

Select Contribute as Allow/

Add Contribute allow permission for the repository

6. Add Power Platform Build Tools extension for Azure DevOps. (Part2)

NOTE: ONLY needed for PART2.

Power Platform Build Tools

7. Add Service Connection in Azure DevOps (Part2)

NOTE: ONLY needed for PART2.

Click on Project Settings

Click on Service connections under Pipelines

Click on Create service connection

Select “Power Platform” and click Next

Add Service URL, Tenant ID, Application ID, Client secret of Application ID, and provide a name of the service connection such DEV, PREPROD or PROD depending on whatever environment URL you are connecting to.

Add service connection


This completes this blog post. Once executing prerequisites you can refer to Part2 or Part3 depending on what tool you want to use for your need.

The ALM is documented in detail here.

Posted in Power Apps, Power Apps, Power Automate | 1 Comment

How to find {sitesId} to pass to MS Graph API call?


SharePoint related MS Graph API call requires {sitesid}, for example for the following API call we need {sitesId}

Create permission – Microsoft Graph v1.0 | Microsoft Docs

POST /sites/{sitesId}/permissions


Login to your SharePoint site. Go to Graph Explorer,, enter the following request call, assuming tenant as m365x162783 and site as Test1.$select=id

You will get a response something like the following.

    "@odata.context": "$metadata#sites(id)/$entity",
    "id": ",2e0ad342-19b2-4116-b6a5-2dc4867cb498,0efde304-9646-43d8-8eee-5b1a55ab17f1"

What you get back in the id is in this format:

The Graph Explorer request-response


This is a simple way to get this sites-id information for any future MS Graph API calls if you may want to explore using PostMan or RESTClient.

However, if you want to make this call in your code you will need an access token and make a similar call as above to get the information.

$tenantPrefix = "m365x162783";
$clientId = "Client-ID";
$clientSecret = "Client-Secret";
$tenantName = $tenantPrefix +"";
$tenantDomain = $tenantPrefix +"";

#Provide site url
$sitePath = ""
$siteName = $sitePath.Split("/")[4]

# use splatting
$ReqTokenBody = @{
Grant_Type    = "client_credentials"
Scope         = ""
client_Id     = $clientID
Client_Secret = $clientSecret
$TokenResponse = Invoke-RestMethod -Uri "$TenantName/oauth2/v2.0/token" -Method POST -Body $ReqTokenBody

$apiUrl = ''+ $tenantDomain +':/sites/'+ $siteName +'?$select=id,displayName'
try {
  $spoResult = Invoke-RestMethod -Headers @{Authorization = "Bearer $($Tokenresponse.access_token)"} -Uri  $apiUrl -Method Get 
  Write-Host "Site:" $spoResult.displayName
catch {
  Write-Output "Failed to enumerate the site"
  Write-Host "StatusCode:" $_.Exception.Response.StatusCode.value__ 
  Write-Host "StatusDescription:" $_.Exception.Response.StatusDescription 

# NOTE THE SITES-ID is passed for the next call.
$apiUrl = ''+ $ +'/permissions'
Posted in MS Graph, SharePoint | 3 Comments