Category: M365 & Power Automate

  • How to configure Azure App registration for MS Graph

    App registration for MS Graph are really powerful, as you can raise any request if granted. In this article, I want to illuminate, what is an app registration. For what can it be used and what are the boundaries. After setting a common understanding, I want to share you my considerations about the security of app registrations. At the end of the article you’ll also be able to understand how to create an app registration with the right permissions for MS Graph

    Before we start highlighting this topic, let’s answer the following question:

    What is an app registration in Azure Active Directory?

    Text with "What is an App registration?" with an iPhone in the background

    An app registration in Azure Active Directory is an authentication and authorization layer to access Microsoft cloud services.

    If we want to impersonate or use our scripts as a backend automation e.g., to get SharePoint Sites with Microsoft Graph, we need to ensure, that we have set up an app registration in Azure Active Directory. The app registration and the resulting enterprise application provides us the ability to authenticate to Microsoft’s cloud services and also to authorize us for the actions we need to trigger. Means we are not dependent to a functional account like a service user, if we want to run this code as an application, with no human interaction.

    • You can configure the app to run in the background – This would be considered as an app with “application permission”.
    • On the other hand you can configure app, which impersonate someone – Here you would take “delegated permission”

    Considerations about app registration in Azure Active Directory

    In this section I want to give you an overview, what to consider in terms of security of app registration in Azure Active Directory

    Permissions to create App registration for MS Graph

    To create an app registration for MS Graph, you need the proper permissions for your user account. By default, every user has the permission to create app registrations in the tenant. If you want to restrict this, you should change this setting below User settings page for your organization (azure.com).

    Even if every user is able to create an app registration, they require the requested permission granted by a global administrator for some special permissions. So it is actually not a bad idea to let the users preconfigure their apps.

    What permissions can be granted with an app registration in azure active directory?

    Before we set up an application registration, we need to think about the security requirements of our organization, and we should answer us the questions accordingly. Since you will be able to have a big impact on the tenant, I suggest you to consult also the security department of your organization to be on the safe side.

    • Will this script run in the background e.g., as a Scheduled Task / Runbook in an Azure Automation Account or will this script used by personnel, which can interact with the script and which are granted permission to the content.
      • If human interaction is OK, we should design the register the application as delegated permissioned application
    • Does any security requirement/ guide/ policy restricts me to use an enterprise application?
      • If yes, we should think about an application registration with delegated permissions.

    In general, I would strongly encourage you to think about your solution, before you start delegating application permission to your application registration. If any malicious user gets access to the application ID and application secret, he will be able to raise any action in your tenant for the defined set of the permission.

    How to create an App registration for MS Graph?

    To create an app registration, you need to browse to Azure Portal:
    Register an application – Microsoft Azure

    If you encounter this, your administrator has restricted the permission to create apps:

    Screenshot of access denied page when creating an app registration

    Otherwise, you should see this:

    Screenshot of register an application in azure portal

    Based on your use case you have the ability to create different supported account types

    TypeUse case

    Accounts in this organizational directory only (Contoso only – Single tenant)
    If your app will be used to access resources within your tenant, this is the way to go
    Accounts in any organizational directory (Any Azure AD directory – Multitenant)If your app will be used to access resources across your tenant, this is the way to go. This might make sense if your organization is a software provider and wants to grant access to the customer.
    Accounts in any organizational directory (Any Azure AD directory – Multitenant) and personal Microsoft accounts (e.g. Skype, Xbox)If your app will be used to access resources across your tenant, this is the way to go. This might make sense if your organization is a software provider and wants to grant access to the customer. In addition you enable users to make use of different identity providers.
    Personal Microsoft accounts onlyIf your app is a consumer faced app, this is the way to go. Not suitable for b2b or inter organizational use.

    In my example I am looking forward to get all SharePoint Sites in my SharePoint tenant.

    App registration for MS Graph

    How to grant the least privilege Permission to the Azure Application to work with SharePoint Sites?

    As per Microsoft documentation, following permissions are required get all sites:

    PermissionDisplay StringDescriptionAdmin Consent RequiredWhen to use?
    Sites.Read.AllRead items in all site collectionsAllows the app to read documents and list items in all site collections without a signed in user.YesRead content from all Sites
    Sites.ReadWrite.AllRead and write items in all site collectionsAllows the app to create, read, update, and delete documents and list items in all site collections without a signed in user.YesWrite content to all sites (you cannot create Lists/Libraries with this permission)
    Sites.Manage.AllCreate, edit, and delete items and lists in all site collectionsAllows the app to manage and create lists, documents, and list items in all site collections without a signed-in user.YesWrite content to all sites including lists and libraries
    Sites.FullControl.AllHave full control of all site collectionsAllows the app to have full control to SharePoint sites in all site collections without a signed-in user.YesWrite content to all sites including lists and libraries + Manage Site permissions
    Sites.SelectedAccess selected site collectionsAllow the application to access a subset of site collections without a signed in user.  The specific site collections and the permissions granted will be configured in SharePoint Online.Yes
    Write content for one specific site including lists and libraries + Manage Site permissions

    For my current example, I am designing the Azure Application to run in the background, therefore I am choosing the Application Permission type and as I am targeting least privilege, I am using Sites.Read.All. However, you should carefully select the permission level and make sure that you follow the least privilege approach, try to use Sites.Selected if you can.

    In order to configure it, switch to the API Permission blade.

    API Permission Blade of the App Registration

    To add the permission, click on add permission

    Add a permission screenshot of an app registration

    As I want to add Graph permissions, I am clicking on Microsoft Graph.

    App registration for MS Graph

    Now you can select between Delegated and Application Permission. In my case I am using Application permissions.

    App registration for MS Graph

    By searching for sites, I am getting to the sites permission section. Follow the enumeration in red circles to add the permission.

    Screenshot of Sites.Read.All Permission

    Now you need to ensure, that the global administrator in your organization grants the permission for the organization, for which you are requesting the permission. In my example, I am requesting the permission for my organization and as I am the global administrator, I am able to directly grant the permission.

    App registration for MS Graph with a hint how to grant permission for the current tenant

    This is how it looks like, once the permissions for the designated organization is granted.

    Screenshot of granted permission

    In order to use the app registration, you need to configure the app secret or credential part.

    This can be done in the Credential & secrets blade of your azure app registration.

    Screenshot of Certificates & secrets link

    Now you have the option, either to upload a certificate or create a secret.

    How to Create and Upload a certificate for an App Registration

    I have used following script to create the certificate and export it.

    $Certname = "SPSitesReadAll2"    ## Replace {certificateName}
    $ExportFilePathPFX = "C:\Users\Serka\OneDrive\Desktop\PS\Keys\SPSitesReadAll2.pfx"   # Path to save the exported certificate with private key
    $ExportFilePathCer = "C:\Users\Serka\OneDrive\Desktop\PS\Keys\SPSitesReadAll2.cer"   # Path to save the exported certificate (only public part)
    
    $Cert = New-SelfSignedCertificate -Subject "CN=$certname" -CertStoreLocation "Cert:\CurrentUser\My" -KeyExportPolicy Exportable -KeySpec Signature -KeyLength 2048 -KeyAlgorithm RSA -HashAlgorithm SHA256
    
    
    # Define parameters
    
    $Password = Read-host -Prompt "Provide a password for the certificate" -AsSecureString | ConvertTo-SecureString  -Force -AsPlainText   # Password to protect the private key (if exporting private key)
    
    # Retrieve the certificate by its subject name
    $Certificate = Get-ChildItem -Path Cert:\CurrentUser\My | Where-Object { $_.Subject -like "CN=$Certname" }
    
    # Check if the certificate was found
    if ($null -eq $Certificate)
    {
        Write-Error "Certificate with the name $Certname not found."
        return
    }
    
    # Export the certificate (with private key, as PFX)
    Export-PfxCertificate -Cert $Certificate -FilePath $ExportFilePathPFX -Password $Password
    Export-Certificate -Cert $Cert -FilePath $ExportFilePathCER 
    
    Write-Output "Certificate exported successfully to $ExportFilePathPFX and $ExportFilePathCer"

    Now upload the certificate and give it a meaningful name:

    This is how it shall look like after the upload:

    With the uploaded certificate, I can now make use of the Azure App registration to get all sites.

    You can see below, that I was able to authenticate with my application and fetch all sites.

    How to create a client secret in an App Registration

    Besides the certificate option, you can also create an Client Secret in Azure Portal. Give it a meaningful name.

    Upon addition, you’ll see the app secret value once. Make sure to store it at a protected place like Azure Key Vault.

    How to use the Site Selected Permission in an App Registration for MS Graph?

    In order to use the site selected permission in an app registration, you need to create two apps:

    1. TenantAdminApp with the permissions Sites.FullControl.All
    2. SpSiteAdmin App with the permission Sites.Selected

    You need to upload a certificate or a client secret to authenticate with this application. You can do it like this:
    I gave the app secret a meaningful name: SharePointAdmin_AppOnlySecret_6months. Note the secret down, you’ll need it when you want to grant the SiteAdminApp the permission to alter a specific site.

    he TenantAdminApp should look like this:

    Your SiteAdminApp registration shall look like this, when it comes to the permissions:

    How to Grant the App registration Permissions to use Sites.Selected permissions using MS Graph

    Now, that the App has in principle the permission to alter SharePoint Sites, we need to specify for which SharePoint Site the App registration is entitled to conduct the changes. This can be done by running this script after adjusting the parameters:

    • $Tenant: Specifies the Entra ID tenant ID, which is used for authentication. The tenant ID is the unique identifier for your organization in Azure AD. It helps the script understand which Entra ID to authenticate against (e.g., m365x16735261) in my example.
    • $TenantAppID: The Application (client) ID of the Entra ID application that will handle permissions related to creating SharePoint sites. This app registration is responsible for granting the necessary permissions to interact with SharePoint resources on behalf of the script. You can obtain the App ID from the overview page of the TenantAdminApp App Registration.
    • $SiteAdminAppID: The Application (client) ID of another Entra ID application. This app is the one that will be responsible for performing administrative tasks related to SharePoint site creation, such as managing permissions and administering the site. You can obtain the App ID from the overview page of the SiteAdminApp App Registration.
    • $PermissionDisplayName: The name associated with a specific permission in SharePoint, which you are looking forward to grant to the SiteAdminApp.
    • $HostName: The domain name for your tenant’s SharePoint environment. This is used to construct the base URL for interacting with SharePoint resources (e.g., m365x16735261.sharepoint.com).
    • $ServerRelativePath: The relative path to the SharePoint site you wish to access. This is typically used after the hostname to construct the full URL to the site (e.g., /sites/GraphSite1), where the script will perform the necessary actions.

    When you run the script, you’ll be prompted for the app secret of the TenantApp.

    # Define parameters for the tenant, application ID, site name, and mail nickname
    Param (
        # The Entra ID tenant ID for authentication
        $Tenant = "m365x16735261", 
        # The Application (client) Id of the registered Entra ID application registration, which is supposed to grant permissions to the App registration, which creates the SharePoint Site (TenantAdminApp)
        $TenantAppID = "39180af4-ad90-442f-a4ca-028b9221b133",
        # The Application (client) ID of the registered Entra ID application registration, which is supposed to create SharePoint Sites (SPSiteAdminApp)
        $SiteAdminAppID = "3342565c-dca1-4b55-b107-7aa0e2f7bfd6",
        # The displayname of the permission as part of the SharePoint Site
        $PermissionDisplayName = "GraphSites_ReadWrite_Permission", 
        # hostname of the tenant
        $HostName = "m365x16735261.sharepoint.com",
        # The relative path of the site, beginning with /sites/, /teams/, or another valid site type path.
        $ServerRelativePath = "sites/GraphSite1"
    )
    # Function to obtain the Microsoft Graph API token
    function Get-GraphToken
    {
        param (
            [string]$Tenant,
            [PSCredential]$AppCredential
        )
        
        # Define the required scope for accessing the Microsoft Graph API
        $Scope = "https://graph.microsoft.com/.default"
    
        # Prepare the body for the token request with client ID, client secret, and scope
        $Body = @{
            client_id     = $AppCredential.UserName                     # Client ID from app registration
            client_secret = $AppCredential.GetNetworkCredential().password   # Securely retrieve the client secret
            scope         = $Scope                                         # API scope required for MS Graph API access
            grant_type    = 'client_credentials'                      # Grant type for app-only authentication
        }
    
        # Entra ID endpoint to request an OAuth token
        $GraphUrl = "https://login.microsoftonline.com/$($Tenant).onmicrosoft.com/oauth2/v2.0/token"
    
        try
        {
            # Request the access token from Entra ID
            $AuthorizationRequest = Invoke-RestMethod -Uri $GraphUrl -Method "Post" -Body $Body
            # Retrieve the access token from the response
            return $AuthorizationRequest.Access_token
        }
        catch
        {
            # Handle authentication errors, if any
            Write-Error "Error during token retrieval: $_"
            return $null
        }
    }
    
    #region authentication - obtain bearer token
    $TenantAdminAppCredential = Get-Credential -UserName $TenantAppID -Message "Enter the client secret for the app TenantAppID $TenantAppID"
    
    # Call the Get-GraphToken function and store the result
    $Access_token = Get-GraphToken -Tenant $Tenant -AppCredential $TenantAdminAppCredential
    
    # Check if access token is successfully obtained
    if (-not $Access_token) 
    {
        Write-Error "Failed to retrieve access token. Exiting script."
        return
    }
    
    # Set the Authorization header with the bearer token for API requests
    $Header = @{
        Authorization  = "Bearer $Access_token"              # Bearer token for API authorization
        "Content-Type" = "application/json"                 # JSON content type for the request body
    }
    
    Write-Output "Access token retrieved successfully."
    #endregion
    
    #Obtain the SiteID of the Site
    
    $Url = "https://graph.microsoft.com/v1.0/sites/${HostName}:/$ServerRelativePath"
    $Site = Invoke-RestMethod -Uri $Url -Headers $Header
    
    #region grant the SiteAdminApp the write permission for the Site
    
    $Url = "https://graph.microsoft.com/v1.0/sites/$($Site.ID)/permissions"
    $Body = @{
        roles               = @("write")
        grantedToIdentities = @(
            @{
                application = @{
                    id          = $SiteAdminAppID
                    displayName = $PermissionDisplayName
                }
            }
        )
    }
    
    $BodyJSON = $Body | ConvertTo-Json -Depth 3
    
    try
    {
        # Send the HTTP POST request to create the Grant write permission to the specified site
        $response = Invoke-RestMethod -Uri $Url -Headers $Header -Method Post -Body $BodyJSON
        Write-Output "Permission granted successfully:"
        Write-Output $response
    }
    catch
    {
        # Handle errors that may occur during the permission granting process
        Write-Error "The permission could not be granted successfully."
        Write-Error $Error[0]
    }
    #endregion

    Reference

    Create a self-signed public certificate to authenticate your application – Microsoft Entra | Microsoft Learn

    Authentication and authorization basics – Microsoft Graph | Microsoft Docs

  • Business Process Automation: How to make customers happy

    Business Process Automation: How to make customers happy

    Business process automation can help you to design a more efficient organization. With business process automation, you can guide your users through your processes, so your users know what to do and when to do it. In this article, I want to show you my key success factors, to make your customers happy.

    I also have talked in the PowerShell DevOps Conference about this topic. Here you can find the video:

    Know your customer

    The customers for business process automation

    Each of these people can be our customer. The chemist on the upper left side might add some results of tests to forms, which you have designed. The engineers on the upper right side might request approval for a new production process, which they request over a PowerApp. The construction worker could give the site manager an update by adding the current state to an app, you have designed. But also office workers, like the lady in the lower right corner, appreciate faster processes through business process automation.

    For all of our customers, we should have to try to look through their eyes and consider their working environment, e.g., the construction worker does need a responsive design, since he mostly will work with a tablet. Our aim should be to make their work as easy as possible.

    Automation Journey

    All of our customers are either directly or indirectly involved in our automation journey. Our customers input data by filling formulas, changing parameters in scripts or reacting to prompts in scripts. After entering the data, business process rules will be applied by flows, scripts, or Azure Runbooks. Here is the part, where we relieve our customers. Our processing component should lead to an appropriate output.

    Business process automation journey
    Automation Journey

    6 Key factors for business process automation

    1. Clear Expectations
      • Give your customers an idea, what you request from them
    2. Focus on essentials
      • Focus on essentials, don’t show or request data, which don’t provide any benefit
    3. Consideration of experience
      • People are influenced by their experience with previous forms.
    4. Request as less manual input as possible
      • Manual input might lead to bad data quality.
    5. Self-explanatory
      • Design the form, so nobody got any questions. Provide close and up-to-date help to guide new users.
    6. Guide your users through the process
      • Give them an overview, where they stand and what will happen to their inputs.

    In the following, I will describe my key factors to make our customers happy with business process automation.

    Input

    What do you notice, when you see the input form below?

    Bad example for input
    Bad example for input of data
    • The expectations for the user are not clear
      • “What is expected from me?”
      • “How should the data, e.g. for probability, look like?”
      • This can result in demotivation and additional inquiries.
    • No focus on essentials
      • “Why is modified by and attachments in the form, when I cannot change them?”
      • People will spend time with things, which do not result in benefits.
    • People are influenced by their experience
      • “Why does this formula look so ugly and unstructured?”
      • People will be demotivated by an unstructured form.
    • Form is not self-explanatory
      • This will lead to inquiries, and so to more effort
    • Manual inputs are required
      • “Why should I type in the product?”
      • This will lead to mistakes, and it will be hard to analyse the data afterwards.

    All these points are things, we should consider, when we want to make our customers happy. I have prepared a form, which covers the points:

    The form begins with an intro screen, describing what to do and what to do, if you feel unsure:

    Better example for input of data – intro screen

    The customer gets his expectations cleared, and also an example is shown how to get help.

    As you can see, the form is more structured and does not overwhelm the user.

    Better example for input of data — input form
    Hint text for an attribute
    Better example for input of data — hint text
    detailed help for an attribute
    Better example for input of data — detailed help
    • Expectations are clear
    • Focus is set on the essentials
    • The experience and influence of experience is considered in this form
    • The aim to request zero manual input is tracked
      • On the areas, where manual input is needed, the form guides the user by telling him, how the data should look like
    • The form is self-explanatory
      • It provides a close & up-to-date help for users, who are not sure.
      • It also references to further detailed help.

    Process

    Processing the data in business process automation is the core benefit of it. When we check the picture below, we can see, that the user of the automation, does not know, how long it probably will take. The idea is to guide the user through the process, so he knows, where he stands.

    Automation without indication, where the process stands

    We can help the user to indicate, how long the procedure will take, by showing him how many items are processed.

    Automation, where the user sees what's going on

    Output

    Telling the user, that the process is finished is a good starting point.

    Success screen at the end of automation

    We can leverage the experience, by telling him, what will happen afterwards or what he shall make afterwards, so he is well-informed.

    End of automation, where we make clear, what will happen afterwards

    Conclusio

    Business process automation can leverage the efficiency of the work, if you see you centre your automation on your users. The six key factors are for sure not sufficient. What do you think? Have I missed something, to improve the automation journey?