How to create Site Columns using field schema xml in Power Automate?

Summary

This is a very simple blog to create site column using Schema XML. The Schema XML can be extracted with PnP.PowerShell. First manually create the Site Column on your site. After you are happy with the created fields you can extract the information using the Save-PnPSiteTemplate. Anyhow, this post is to create the site columns in consistent way to various sites.

Step By Step

#1 Create a Manually Triggered Power Automate flow.

#2 Create Compose action, rename to something like ComposeSchemaXML. Add the following xml in the “Inputs” of compose action.

Field Schema Definition

<Field Type="Text" DisplayName="Description" Description="A Sample description field." Required="FALSE" EnforceUniqueValues="FALSE" Indexed="FALSE" MaxLength="255" Group="MyCustomFields" StaticName="reqDescription" Name="reqDescription"></Field>

#3 Call the “Send an HTTP request to SharePoint” action with the following information.

Method: POST

Uri: _api/web/fields/createfieldasxml

Headers:

{
   "accept": "application/json;odata=verbose",
   "content-type": "application/json;odata=verbose"
}

Body

{
  "parameters": {
    "__metadata": { "type": "SP.XmlSchemaFieldCreationInformation" },
    "SchemaXml": '@{outputs('ComposeSchemaXML')}'
  }
}

Conclusion

This post may a simple and short post for you. It may give you a quick ways to create the multiple site columns in a consistent way.

Please make a note:

To check if the site column exists or not you can make GET call with the following uri

_api/web/fields/GetByInternalNameOrTitle(‘reqDescription ‘)

To delete the existing site column you make a POST call with above uri with headers as following.



{
   "accept": "application/json;odata=verbose",
   "content-type": "application/json;odata=verbose",
   "IF-MATCH":"*",
   "X-HTTP-METHOD":"DELETE"
}

Posted in Power Automate, Uncategorized | Leave a comment

How to setup certificate in MAG Azure Function App for PnP.PowerShell?

Summary

The PnP.PowerShell supports PowerShell Core. There are few things you must do to make the PowerShell Code to work in Azure Function App. In this article, I will go through the steps by step all pre requisites.

Step by Step Process

Step # 1 Create the certificate files or acquire commercial certificate

# Change your tenant name

Register-PnPAzureADApp -ApplicationName "MyPnPApplication" -Tenant "GOV963094.onmicrosoft.com" -CertificatePassword (ConvertTo-SecureString -String "password" -AsPlainText -Force) -Username admin@GOV963094.onmicrosoft.com -DeviceLogin

# Note: make a note of PFX file and password you will need in step 3.

The above command will provide the DEVICE code to log in to the Azure Portal. You will be asked to consent the requested permissions for “Group.readWrite.All”, “User.ReadWrite.All”, “AllSites.FullControl”, “Site.FullControl.All” & “User.ReadWrite.All.

Once the consent is provided the command will create the Azure AD application and returns the application id. The command also creates the two certificate filed <Name of App>.PFX and <Name of App>.CER.

Consent dialog

Step # 2 Create and configure the Azure Function App

Go to Azure Portal and create the Azure Function App. Select PowerShell Core as runtime stack.

Create Azure Function App with PowerShell Core runtime stack

Create a Timer Function

  1. Click on functions
  2. Click Add
  3. Select Timer Trigger
  4. Click Add button.
Create a Timer Azure function

Configure the profile.ps1

Click on “App Files” -> Select profile.ps1

Add the EnvironmentName for your scenario. If it is commercial you do not need to pass the Environment Variable. Please refer here for more information.

Connect-AzAccount -EnvironmentName AzureUSGovernment -Identity
Configure profile.ps1

Configure requirements.ps1

Click on “App Files” -> Select requirments.psd1

Add the following line for PnP.PowerShell.

# This file enables modules to be automatically managed by the Functions service.
# See https://aka.ms/functionsmanageddependency for additional information.
#
@{
    # For latest supported version, go to 'https://www.powershellgallery.com/packages/Az'. 
    # To use the Az module in your function app, please uncomment the line below.
    'Az' = '6.*'
    'PnP.PowerShell' = '1.*'
}
Configure requirements.ps1

Step # 3 Upload the certificate on Azure Function App

Click on “TLS/SSL Settings” -> “Private Key Certificates (.pfx)

Click on “Upload Certificate”

Select the PFX file created in the Step # 1 and provide the password as you have used in the Step # 1.

Upload PFX to the Azure function App.

Step # 4 Add the WEBSITE_LOAD_CERTIFICATES configuration parameter

Click on the “Configuration”

Add WEBSITE_LOAD_CERTIFICATES with value of “*”.

Modify the configuration.

Step # 5 Import the certificate to Azure Key Vault

On Azure Portal for the Azure Key Vault

Click on “Certificates” -> “Generate/Import”

On the next dialog select Import and select the certificate created in the Step # 1.

Finally click on Create. This will add the certificate in the Azure Vault.

Step # 6 Create Azure Function App’s System assigned Identity

On the Azure portal got the Azure Function App.

Click on the “Identity” under Settings -> “System Assigned”

Turn the Status to On

Make a note of the “Object ID” GUID. Copy to the clipboard you will need it.

Step # 6 Provide Access Policy to Azure Function App in Azure Key Vault

On the Azure Portal, navigate the Azure Key Vault.

Click on “Access Policies” under Settings -> “Vault access policy” radio button for the permission model.

Click on the “Add Access Policy” link.

For the “Add Access Policy” dialog

Select “Certificate Management”

Select “Get and List” for the Certificate permissions.

Select “Secret Management”

Select “Get and List” for the Secret permissions.

Finally select the “Select Principal”

In the select permission paste the GUID copied from the earlier step for the system assigned identity.

Click on Select Button and accept all the dialog by clicking Add.

This will add the Access Policy for the the Azure Key Vault. This gives an access to the Certificate in Azure Vault for the Azure Function App using managed identity.

Access Policy

Step # 7 Final step to access the and connect to SPO admin size using certificate.

Please make a note, the import thing in the code is to get the certificate base encode. Once we get it from the Azure Key Vault it is now next step to use the connect command to connect to the any site or admin site.

# Input bindings are passed in via param block.
param($Timer)

$tenant             = "GOV963094";
$RequestWebUrl      = $("https://{0}-admin.sharepoint.com/" -f $tenant)
$GRAPH_APP_ID       = "7c244c08-9875-4ffe-b39d-34f9b6853f6b"
$KeyVaultName       = "my-spo-key-vault"
$KeyVaultSecretName = "storedcertificate"

# get the PFX secret from the key vault
$kvSecret = Get-AzKeyVaultSecret -VaultName $KeyVaultName -Name $KeyVaultSecretName
$certificateBase64Encode = '';
$ssPtr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($kvSecret.SecretValue)
try {
	$certificateBase64Encode = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($ssPtr)
} finally {
	[System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($ssPtr)
}
# Using Splat to convert
$HashArguments = @{
	Url                      = $RequestWebUrl
	ClientId                 = $GRAPH_APP_ID
	CertificateBase64Encoded = $certificateBase64Encode
	Tenant                   = $("{0}.onmicrosoft.com" -f  $tenant)
}
$RequestSitesConnection = Connect-PnPOnline @HashArguments  -ReturnConnection

###
### DO SOME WORK 
###
Disconnect-PnPOnline -Connection $RequestSitesConnection





Conclusion

There are many steps but it is listed here step by step for the reference. For any reason you miss the step please refer it back.

Posted in MS Graph, PnP.PowerShell | 3 Comments

DOs and DON’Ts for Performant PowerApps

Summary

I have watched multiple MVP’s video talking about PowerApps performance. Here I want to make this as a list of DOs and DON’Ts for PowerApps performance.

Limit data connections

DO: Use less data connectors in your app.

DON’T: Don’t connect to more than 30 data sources from the same app.

Limit the number of controls

DO: Use a gallery instead of individual controls.

DON’T: Don’t add more than 500 controls to the same app.

Optimize the OnStart property

DO: Use Concurrent function to reduce the overall time to load data in parallel

DON’T: Don’t load data in sequential ways.

Cache lookup data

DO: Use the Set function to cache data from lookup tables locally.

DON’T: Don’t repeatedly retrieving data from the source using Lookup.

Avoid control dependency between screens

DO: Write global variables to transfer control’s properties info from one screen to other.

DON’T: Don’t create formula dependencies between screens. e.g. Control property value of other screen in the formula.

Delegation

DO: Where possible, use functions that delegate data processing to the data source.

DON’T: Don’t retrieving data to the local device for processing. This is an resources intensive step.

Republish apps regularly

DO: Republish the apps frequently to take an advantage of any latest features.

DON’T: Don’t keep the app published only once when launched. Publishing it frequently has advantage plus it will keep multiple versions.

Enable DelayOutput on all Text input controls

DO: Set DelayedOutput to true for a text box control. This will help in performance if the text box value is used as search to filter gallery.

DON’T: Don’t keep DelayedOutput as false (default) this will impact the performance when the text box is used as search to filter gallery. With false it will do a filter for every character user types.

Use Spinner to load Gallery Data

DO: For Gallery controls set DelayItemLoading set to true, and LoadingSpinner set to LoadingSpinner.Controls

DON’T: Don’t simply load the data in the gallery.

Avoid Lookups in the Gallery

DO: In the Gallery controls do set a global variable for objects. e.g. Set Office365Users.MyProfile().GivenName to set some variable.

DON’T: Don’t simply load the objects using Lookup within the gallery.

First value of Filter Vs Lookup

DO: Do use the Lookup to return a single result. This scans the data set until it gets the first match and stops scanning after the match.

LookUp(Employees, StartsWith(Title,"Pankaj")).Position

DON’T: Don’t use the First to get to one single record. Scans the entire data set using Filter to get the matched data.

First(Filter(Employees, StartsWith(Title,"Pankaj"))).Position

Conclusion

The above listed performance tips are at multiple places. I wanted to keep this list as clear and concise for the simplicity.

Performance considerations with PowerApps
Building Performant Power Apps by Reza Dorrani
The master class on building performant apps

Posted in Uncategorized | Leave a comment

How to remove SCA users from Site Collection Admins?

Summary

This is kind of similar requirement from my previous blog article.

How to remove users from multiple Azure AD Groups?

But in this article I will provide only the code for removing the Site collection Admins from SharePoint Site. The steps for running this code is same as the above article.

$Users2Remove = (
    "BobK.GOV963094.onmicrosoft.com",
    "DebraB.GOV963094.onmicrosoft.com"
)

$ClientId = "7c244c08-9875-4ffe-b39d-34f9b6853f6b"
$Tenant = "gov963094.onmicrosoft.com" # replace your tenant name

Import-Csv C:\Contoso\teamSites.CSV | 
    ForEach-Object {
        try
        {
            $newSiteUrl = $_.SiteURL
            $newSiteConn = Connect-PnPOnline -ClientId $ClientId -Url $newSiteUrl -Tenant $tenant -CertificatePath 'MyPnPApplication.pfx' -ReturnConnection

            # Get the site collection administrators  
            $scaColl = Get-PnPSiteCollectionAdmin -Connection $newSiteConn
            foreach($sca in $scaColl)  
            {          
                Write-Host $sca.LoginName
                $modifiedLoginName = $sca.LoginName
                $modifiedLoginName = $modifiedLoginName -replace "i:0#.f\|membership\|", ""
        
                if ( ( $Users2Remove -contains  $modifiedLoginName ) -eq $true )
                {
                    Write-Host $("Remove {0}" -f $sca.LoginName)
                    Remove-PnPSiteCollectionAdmin -Owners $sca.LoginName
                    Write-Host $("Removed..")
                }
            }         
        }
        catch
        {
            $ErrorMessage = $_.Exception |  Out-String
            Write-Host $("Exception {0}" -f $ErrorMessage);
        }
        finally
        {
            Write-Host $("Disconnecting to {0}" -f $newSiteUrl);
            Disconnect-PnPOnline -Connection $newSiteConn
            Write-Host $("Disconnected to {0}" -f $newSiteUrl);
        }
    }

Posted in Uncategorized | Leave a comment

How to remove users from multiple Azure AD Groups?

Summary

For my customer there were many Modern Team Sites in the tenant. These sites had 4 to 5 users present in the Owners group. These users were added when the sites were originally created by a automated script. But later these users were not needed and must be removed from the Azure AD owners group. The following is the step by step solution and script to remove the users from owners group.

Step by Step Solution

Step # 1 Install PnP.PowerShell and run following command.

# Change your tenant name
Register-PnPAzureADApp -ApplicationName "MyPnPApplication" -Tenant "GOV963094.onmicrosoft.com" -Username admin@GOV963094.onmicrosoft.com -DeviceLogin

The above command will prompt you to provide the device code and user credentials. It will also create PFX and CER certificates in the folder.

You will need to consent to the required permission. The following dialog box will consent the app. Click on Approve.

This created an Azure AD application in your tenant with the permissions for “Group.readWrite.All”, “User.ReadWrite.All”, “AllSites.FullControl”, “Site.FullControl.All” & “User.ReadWrite.All”.

Step # 2

First, create a CSV file named “teamSites.CSV”. Put all the site urls for the team sites.

SiteURL
https://gov963094.sharepoint.com/sites/Test1
https://gov963094.sharepoint.com/sites/Test2

Now execute the following script, modify the users2Remove array according to your users information. The script will read the above CSV file and iterate over each site and remove the users from the Azure AD owners group.


$Users2Remove = (
    "BobK.GOV963094.onmicrosoft.com",
    "DebraB.GOV963094.onmicrosoft.com"
)

$ClientId = "7c244c08-9875-4ffe-b39d-34f9b6853f6b"
$Tenant = "gov963094.onmicrosoft.com" # replace your tenant name

Import-Csv C:\Contoso\teamSites.CSV | 
    ForEach-Object {
        try
        {
            $newSiteUrl = $_.SiteURL
            $newSiteConn = Connect-PnPOnline -ClientId $ClientId -Url $newSiteUrl -Tenant $tenant -CertificatePath 'MyPnPApplication.pfx' -ReturnConnection

            $splitedSiteUrls = $newSiteUrl -split "/"

            $relativeUrl = $splitedSiteUrls[$splitedSiteUrls.Length - 1]

            $owners = Get-PnPAzureADGroupOwner -Identity $relativeUrl 

            foreach($owner in $owners)  
            {          
                if ($owner.UserPrincipalName.Length -gt 0 ) 
                {
                    if ( ( $Users2Remove -contains  $owner.UserPrincipalName ) -eq $true )
                    {
                        Remove-PnPAzureADGroupOwner -Identity $relativeUrl -Users $owner.UserPrincipalName
                    }
                }
            }
        
        }
        catch
        {
            $ErrorMessage = $_.Exception |  Out-String
            Write-Host $("Exception {0}" -f $ErrorMessage);
        }
        finally
        {
            Write-Host $("Disconnecting to {0}" -f $newSiteUrl);
            Disconnect-PnPOnline -Connection $newSiteConn
            Write-Host $("Disconnected to {0}" -f $newSiteUrl);
        }
    }



Conclusion

The above script is an automated ways to remove the users from the owners group from multiple team sites.

Posted in PnP.PowerShell | 1 Comment

How to always return array object in PowerShell?

Summary

I have a PowerShell Script, I get all items from the SharePoint list. After getting all items I want to filter by a condition so I used the Where-Object as following.

# fyi, % -> ForEach-Object
[array]$items = Get-PnPListItem @HashArguments | `
  %{New-Object psobject -Property `
  @{ 
    Id                          = $_.Id; 
    reqStatus                   = $_["reqStatus"];
  }} | `
  select ID, 
    reqStatus

[array]$PendingFilteredItems  = $items | Where-Object {$_.reqStatus -contains 'Active'}  | Sort-Object -Property Id

if ( ($PendingFilteredItems -ne $null) -and ($PendingFilteredItems.Count -gt 0) )
{
   # ... further processing for array count is greater than zero
}

All worked fine, the condition was hitting for greater than zero items. But issue came when the item left in the SharePoint list as one item. I always got a “PSCustomObject” as a type for the PendingFilteredItems.

How to always return and array for any number of items left?

Basically I had to add an [array] type for the variable. It is highlighted in the above code.

Conclusion

I know it is simple post for such a solution. If you read this and fix the issue at your side this will save lot of time. I will be happy that you saved some time.

Posted in Uncategorized | Leave a comment

Get-PnPListItem errors “The attempted operation is prohibited because it exceeds the list view threshold.” for over 5,000 items.

Summary

I have written Site Provisioning Engine in Azure Function using PnP.PowerShell. There is request list name “Master Site Inventory”. This list grew in size over time. The provisioning engine was working fine but it stopped working with above error.

After doing the analysis the error was clearly for the request list size grew over 5,000 items.

The issues was using the CAML query to get items from the list using Get-PnPListItem. I used the CAML Query so I can only get items where RequestStatus is equal to Approved.

$strQuery = "
  <View>
    <Query>
      <Where>
        <Eq>
          <FieldRef Name='RequestStatus' />
          <Value Type='Text'>"Approved"</Value>
        </Eq>
      </Where>
    </Query>
    <ViewFields>
      <FieldRef Name='RequestStatus' />
      <FieldRef Name='Title' />
    </ViewFields>
  </View>"

$HashArguments = @{
  Url            = $webUrl
  ClientId         = $env:GRAPH_APP_ID
  CertificateBase64Encoded = $certificateBase64Encode
  Tenant           = $("{0}.onmicrosoft.com" -f  $tenant)
}

# use splatting to pass parameter.
$conn = Connect-PnPOnline @HashArguments  -ReturnConnection

$HashArguments = @{
  Connection    = $conn
  List      = "MasterSiteInventory” 
  # Query       = $strQuery <---- This is an issue, NO CAML QUERY
}

[array]$items = Get-PnPListItem @HashArguments  -PageSize 1000 | `
		%{New-Object psobject -Property `
		@{ 
		  Id           = $_.Id; 
		  RequestStatus    = $_["RequestStatus"];
		  Title        = $_["Title"]; 
		 }} | `
         	 select ID, 
	        	RequestStatus,
			Title,
$FilteredItems  = $items | 
                  Where-Object {$_.RequestStatus -contains 'Approved'}  | 
                  Sort-Object -Property Created

How was it resolved?

Basically, the CAML query for the large list such as over 5,000 items the Get-PnPListItem will fail with the above error.

The resolution is, user the PageSize of some number and get “ALL” items from the list. After getting all items, apply filter to the returned items.

Conclusion

There are number information on the web for this error. I want to put this resolution just too the point without any noise. Basically, stop using CAML query to get items for large list. Get everything and filter it.

NOTE: Since you are getting all items from the list, make sure you are getting only required columns in my case I just need Id and RequestStatus Column. Once I filter the items from all items I then get rest of the field for the filtered array. This will help in the performance.

Posted in Uncategorized | Leave a comment

How to create a SharePoint List using Power Automate?

Summary

Many times the application I have built requires the list to be created on a Site. I found in GitHub sample app (by April Dunnam) to create this list(s) using REST call in Power Automate. I will document this approach for creating a ‘ Room Occupancy Tracking’ list and two fields.

Step by Step

Basically you will need the Send HTTP Call.

#1 To create a brand new list

Section of Send HTTPSection Value
Site Addresshttps://contoso.sharepoint.com/sites/OccupancyTracker
MethodPOST
Uri/_api/web/lists
Send HTTP call to create a brand new list
---- Headers ----

{
   "Accept": "application/json;odata=verbose",
   "Content-Type": "application/json;odata=verbose"
}



---- Body    ----
{
   "__metadata": {"type": "SP.List"},
   "AllowContentTypes": true,
   "BaseTemplate": 100,
   "Description": "Blah Blah.",
   "Title": "Room Occupancy Tracking"
}

#2 Create a Number type Column named Max Occupancy. Note: FieldTypeKind

Section of Send HTTPSection Value
Site Addresshttps://contoso.sharepoint.com/sites/OccupancyTracker
MethodPOST
Uri_api/lists/getbytitle(‘Room Occupancy Tracking’)/fields
Send HTTP call to create a Number type field
---- Headers ----

{
   "Accept": "application/json;odata=verbose",
   "Content-Type": "application/json;odata=verbose"
}

---- Body    ----


{
  '__metadata': {'type':'SP.Field', 'addToDefaultView': 'true' },
  'FieldTypeKind': 9,
  'Title': 'Max Occupancy'
}

#3 Create a Choice type field named Type.

Section of Send HTTPSection Value
Site Addresshttps://contoso.sharepoint.com/sites/OccupancyTracker
MethodPOST
Uri_api/lists/getbytitle(‘Room Occupancy Tracking’)/fields
Send HTTP call to create a Number Choice type field
---- Headers ----

{
   "Accept": "application/json;odata=verbose",
   "Content-Type": "application/json;odata=verbose"
}

---- Body    ----

{ 
     '__metadata':
     { 'type': 'SP.FieldChoice', 'addToDefaultView': 'true' },
     'Title': 'Question Type',
     'FieldTypeKind': 6,
     'Required': 'true',
     'Choices': { 'results': ['Single Line of Text', 'Yes No' ] }
}

#4 Add above fields to the default view. You will need an array of the field names, iterate over each name and make the following call.

Section of Send HTTPSection Value
Site Addresshttps://contoso.sharepoint.com/sites/OccupancyTracker
MethodPOST
Uri_api/web/Lists/getByTitle(‘Room Occupancy Tracking‘)/views/GetByTitle(‘All%20Items’)/ViewFields/AddViewField(‘Question Type’)/fields
Headers
Body
Send HTTP call to create a Number Choice type field

----- uri -----
_api/web/Lists/getByTitle('Room Occupancy Tracking')/views/GetByTitle('All%20Items')/ViewFields/AddViewField('Question Type')/fields

Conclusion

The above steps provided is a way to create a brand new list using a SharePoint REST call.

Keep the following SharePoint REST Wall Poster as a reference.

SharePoint 2013 REST Syntax (wall posters)

Posted in Power Automate | Leave a comment

How to export SharePoint List Template using PnP PowerShell?

Summary

I occasionally need to duplicate SharePoint List Definition from one site to other or some time create a new list from the existing list.

PnP.PowerShell can rescue using the Template methods.

Get-PnPSiteTemplate

Save-PnPSiteTemplate

Invoke-PnPSiteTemplate

Using the Get-PnPSiteTemplate you can the template definition in the XML. Using the Save-PnPsitetemplate you can save the template definition into the local file system.

Using the Invoke-PnPSiteTemplate you can use the local file system template definition file to a brand new site or same site with new list.

Step By Step

#1 Install Pnp.PowerShell Power Shell Module. Refer this article.

#2 Using the SharePoint App register pages register an app. Refer this article.

#3 Execute the following script block.



$HashArgs = @{
    url = "https://{YOUR TENANT}.sharepoint.com/sites/{YOUR SITE}"
    ClientId = "{ID FROM STEP #2}"
    ClientSecret = "{SECRET FROM STEP # 2}"
}

$conn = Connect-pnpOnline @HashArgs -ReturnConnection

# The script below will help you to get a template of a specific list or library.
$listTitle = Read-Host "Enter title of the list or library"  
$outputTemplateFile = $("{0}ListTemplate.xml" -f  $listTitle)
$template = Get-PnPSiteTemplate -OutputInstance -Handlers Lists  
$listTemplate = $template.Lists | Where-Object { $_.Title -eq $listTitle }  
$template.Lists.Clear()  
$template.Lists.Add($listTemplate)  
Save-PnPSiteTemplate -InputInstance $template -Out $outputTemplateFile

Conclusion

Using the above method you can save template for a specific list and using Invoke-PnPSiteTemplate create the same list again.

Posted in Uncategorized | Leave a comment

How to get new team creation in MS Teams using MS Graph Notification API?

Summary

A colleague asked me how to get a notification when anyone creates a Team on MS Teams? The answer is pretty simple you would use the MS Graph Notification API. There is an MS Learn session here.

What I will write in this blog post is to answer the above question using Power Automate. I will create two applications.

  1. One to listen to the notification sent for the create or change of team, aka Web Hooks.
  2. One for subscribing to the notification API. For simplicity, I will make use of the Graph Explorer tool for it.

Prerequisite

  1. You will need Power Automate Premium license for creating HTTP request trigger.
  2. You will need a Consent “Group.ReadWriteAll” permission for Graph Explorer.

Step by Step for Web Hook

Step # 1 First you will need an “When a HTTP request is received” trigger.

Please copy the ‘HTTP POST URL’ to a clipboard. (You will need this value later)

Step # 2

Create a condition for this WebHook to check whether there is any ‘queries’ parameter passed. If passed then read and send back the validationToken with 200 OK.

Check for following condition. Please put the '?' in the equation, it is important.

triggerOutputs()?['queries']                     is not equal to $null      AND 
triggerOutputs()?['queries']?['validationToken'] is not equal to $null      AND triggerOutputs()?['queries']?['validationToken'] contains        Validation

Step # 3

If the condition is success to send back the validationToken.

If condition is not successful that means the notification is received with the body.

For above Condition TRUE

###
This is a very IMPORTANT step, you must send the response back with 200 OK with body of the validationToken. Use the following expression to send the validationToken
###

triggerOutputs()?['queries']?['validationToken'] 

For above condition FALSE

In the false condition, you should process the body value. The body value will have the notification information with the change Type and resources ID. Please note that there will not be additional data for the resource, if needed then you will have to write the code to get that information using the resource ID. Finally, you will need to send the 200 OK response with no body value acknowledging that you have received the notification no further notification will be sent.

Step By Step to Subscribe

Step # 1

To simplify this article I will use Graph Explorer to subscribe to the notification of the groups’ changes. It will require that Graph Explorer Tool has been consented to “Groups.ReadWrite.All” permission. If you do not consent the Graph Explorer will give you an error during the subscription.

changeType set to updated will receive notifications on the creation of a new group.

In Graph Explorer you will make a post request to the URI ‘https://graph.microsoft.com/v1.0/subscriptions&#8217;

## In the request body you would put the following JSON. 
## In the notificationUrl put the above copies URL from Power Automate Trigger.
## Change the expiration date according to your time.
{
    "changeType": "updated,deleted",
    "notificationUrl": "[Paste Text from Step 1 of 'Step by Step for Web Hook'",
    "resource": "/groups",
    "expirationDateTime": "2021-04-10T00:00:00Z"
}

To consent for the Group.ReadWrite.All, in GE you would click on “Modify permissions” -> “Open the permission panel” -> Select Group -> Select “Group.ReadWrite.All”. Finally, you will need to click on the Consent button. Which will pop up a consent window, select OK. This action will create an Azure AD app on your tenant with the consented permission.

Finally you should see the following in the Power Automate Run mode when you subscribe.

The condition expression will be true. When it is true send the response back with the validationToken as a body.

Conclusion

The above article is an attempt to simplify to answer one question. A similar approach can be used for other supported notification types resources. You will need the consent to correct permissions.

Posted in MS Graph | Leave a comment