Implementing Self-Service for End Users

In a previous article, I described the necessary steps to create an Azure Function connected to Exchange Online to allow users to perform actions like assigning mailbox permissions without administrator intervention. This is a very useful capability. Currently, there is no Microsoft Graph endpoint to allow users to update their Exchange Online mailbox settings.

Provisioning systems can leverage Azure functions by using HTTP transactions. By doing so, they can eliminate the dependency on the Exchange Online PowerShell V3 module.

With a kind of API for Exchange Online, we can use Azure functions to implement self-service capabilities for end-users to enhance their experience and productivity.

Creating an End-User Interface

In this article, I follow up on the previous article and show how to develop an interface for end-users using Microsoft PowerApps for interacting and rendering data from Exchange Online. In our case, data is the permissions of a mailbox.

I decided to use PowerApps as it is a low-code platform for the Microsoft 365 ecosystem that makes it relatively easy to create apps. If necessary, you can still write complex solutions. PowerApps offers a good balance between functionality and complexity.

Figure 1 shows the canvas app after a user signs in. The picture and user details come from the user’s account properties.

Combining PowerApps and Azure Functions to Build User Self-Service Capabilities
Figure 1: PowerApp after sign-in.

The user can either enter an email address in the text box and retrieve the permissions for the specified mailbox after pressing the “Get mailbox permissions” button. Alternatively, they can leave the text box empty and get the permissions for the user’s own mailbox. Figure 2 shows the permissions on Adele’s mailbox.

Combining PowerApps and Azure Functions to Build User Self-Service Capabilities
Figure 2: Permissions on Adele’s mailbox.

If an incorrect mailbox address is entered in the text box, the error from Exchange Online is displayed (Figure 3):

Combining PowerApps and Azure Functions to Build User Self-Service Capabilities
Figure 3: Error thrown by Exchange Online for a non-existing mailbox.

Creating the PowerApp

The solution is built with 2 parts. The first is the canvas app and its screen with labels, text boxes, buttons, and gallery. The other part is a flow, which triggers the Azure Function with an HTTP request.

Multiple ways exist to create a canvas app. I start with a blank app as shown in Figures 4 and 5.

Combining PowerApps and Azure Functions to Build User Self-Service Capabilities
Figure 4: Start with a blank app from the “+ Create” menu.
Combining PowerApps and Azure Functions to Build User Self-Service Capabilities
Figure 5: Start with a blank screen.

Give your app a name. Note: This name is visible for users and should give information to end-users. It can be changed later, if necessary. (Figure 6)

Combining PowerApps and Azure Functions to Build User Self-Service Capabilities
Figure 6: Name of the canvas app

Figure 7 shows the blank app we just created.

Combining PowerApps and Azure Functions to Build User Self-Service Capabilities
Figure 7: Blank app just created.

Now we need to add all the components we want to have represented to users (Figure 9):

  1. The image of the user: User().Image
  2. Three text labels:
    • Fixed text: “User details:”
    • User’s display name: User().FullName
    • User’s e-mail address: User().Email
  3. One text label and one text input:
    • Fixed text label: “Mailbox:”
    • Variable text input: the property “Hint text” is filled with “Please provide e-mail address” (Figure 8)
Combining PowerApps and Azure Functions to Build User Self-Service Capabilities
Figure 8: Hint text for text input.

4. The command button to trigger the flow

5. The gallery, which will be filled with data returned from our Azure function

6. Another text label, which is filled in case of an error by Exchange Online

Combining PowerApps and Azure Functions to Build User Self-Service Capabilities
Figure 9: Canvas app layout.

Create the Flow

Before we add any code to our canvas app, we need to create our flow to trigger the Azure function and return data. This is similar to creating an app: multiple ways are possible. Here is mine:

In your app select the Flow symbol and create a new flow as shown in Figure 10.

Combining PowerApps and Azure Functions to Build User Self-Service Capabilities
Figure 10: Create your dedicated flow.

The flow itself looks like the following (Figure 11):

  • We create a variable “UserDetails” (which is the e-mail address) as the input from PowerApps (V2)
  • Make sure there is no NULL input
  • Send an HTTP request to our Azure function. Here you need to add two things:
    • HTTP header “x-functions-key” for authorization
    • Query parameter “name” with the value of “UserDetails
  • Finally, parse the response and create 3 text responses:
    • rawResult: “if(contains(body(‘HTTP’),’An error occurred while processing this request’),”,array(body(‘HTTP’)))”
    • rawError: ”if(contains(body(‘HTTP’),’An error occurred while processing this request’),body(‘HTTP’),”)”
    • result: “if(contains(body(‘HTTP’),’An error occurred while processing this request’),false,true)”
Combining PowerApps and Azure Functions to Build User Self-Service Capabilities
Figure 11: Details of the flow.

Add Code to PowerApp

Now that we have our Flow and app created, we need to add some code and modify the layout of the gallery component.

First, add the following code to the button for the “OnSelect” attribute. The code will create a variable “rawPerms”, which will be used as the source (Figure 12):

Clear(rawPerms);
Set (varFlowResponse, Mailboxpermission.Run( If(IsBlank(MailboxAddress.Text),User().Email,MailboxAddress.Text) ) );
If(varFlowResponse.result = “True”,
    ClearCollect(
        rawPerms,
        ForAll(
            Table(ParseJSON(varFlowResponse.rawresult)),
            {
                User: Text(Value.User),
                Accessrights: Concat(Table(Value.AccessRights),Value,",")
            }
        )
    ),
    Blank()
)
Combining PowerApps and Azure Functions to Build User Self-Service Capabilities
Figure 12: Code of the button to trigger Azure function.

Make sure that you change the following attributes of the permission gallery (Figure 13):

  • Data source: must be set to “rawPerms”
  • Layout: must be set to “Blank”
Combining PowerApps and Azure Functions to Build User Self-Service Capabilities
Figure 13: Set gallery properties

As we have set the “Layout” to blank, we add the fields to be displayed. Add the following labels (Figures 14 and 15):

  • Fixed text label for user and permissions: the values are “User” and “Permissions
  • Dynamic text label of all users and permissions in the response. For each row in the source table, a line will be generated by using ThisItem.User and ThisItem.Accessrights
Combining PowerApps and Azure Functions to Build User Self-Service Capabilities
Figure 14: Fixed and dynamic filled text labels of the gallery
Combining PowerApps and Azure Functions to Build User Self-Service Capabilities
Figure 15: Dynamic filled text label

Error Details

Finally, we add a text label to show details of any error returned by the Azure function. The following code must be added for the Text property (Figure 16):

If(
    varFlowResponse.result = “False”,
    "Error occured:" & Text(ParseJSON(varFlowResponse.rawerror)),
    Blank()
)
Combining PowerApps and Azure Functions to Build User Self-Service Capabilities
Figure 16: Add code to show error

Recommendations

I want to highlight that in PowerApps variables and flows are case-sensitive. Make sure that all variables, names etc. your using are correctly written. Otherwise, the canvas app will not work!

Here’s an example to illustrate the point (Figures 17 and 18).

The check of the result is text with Boolean. This seems to have changed and in my new app I received a warning:

Combining PowerApps and Azure Functions to Build User Self-Service Capabilities
Figure 17: Existing app with working code
Combining PowerApps and Azure Functions to Build User Self-Service Capabilities
Figure 18: The New app, where the “old” code wasn’t working

It makes sense and I should have known better. However, this example clearly outlines complexity and many moving parts behind the scenes.

Conclusion

This example demonstrates how you can leverage Azure functions connected to Exchange Online sending HTTP requests without any PowerShell dependencies. With this, you can start building any kind of tools and/or apps for desktop or mobile devices (like you can do with Microsoft Graph).

This allows you to eliminate the existing gap in Microsoft Graph: missing Exchange Online support.

TEC Talk Series 2024

Check out these free, 60-minute live training webinars modeled after the acclaimed, in-person sessions that The Experts Conference (TEC) is known for – with practical, no-fluff insight led by the industry’s leading Microsoft 365 experts.

About the Author

Ingo Gegenwarth

Ingo Gegenwarth is a Technical Consultant at a market-leading organization for enterprise application software. In his role, he is responsible for the Exchange infrastructure as well as Office 365. In 2003, he earned his first MCSE 2000, and since then he's earned Microsoft Certified Master (MCM) and Microsoft Certified Solutions Master (MCSM).

Comments

  1. Ingo Gegenwarth

    Hi Marcin,
    it’s a beast. The name of the flow needs to be exactly the one you use in the code. In my case I named the flow “Mailboxpermission” and you run it with “Mailboxpermission.Run(…”.
    I can see that you still have the default name for the flow “PowerAppV2->Condition…”
    Ciao,
    Ingo

    1. Marcin R.

      Ahh missed this one, thank you. Seems like I am almost there.

      Now I have the following error due to invalid arguments:

      https://i.imgur.com/rGbs6OJ.png

      1. Ingo Gegenwarth

        Hi Marcin,
        do you have the Text Input label named “MailboxAddress”?
        Ciao,
        Ingo

        1. Marcin R.

          Yes Sir. It is displayed correctly when I highlight it. Looking at the error it seems like there is something wrong with the flow. I am trying to investigate it. Please see detailed screenshot:

          https://i.imgur.com/4Rpo6Xa.png

          1. Ingo Gegenwarth

            Hi Marcin,
            can you check if your flow works at all? Mayba just temporary issue? You should be able to test the flow and providing an e-mail address. Maybe you can see there more details.

        2. Marcin R.

          So I have deleted the button and created from scratch. Flow started working perfectly fine but it could not find a recipient. It seems like you have made a small mistake in condition step. It should be “UserDetails” IS NOT EQUAL to null instead of IS EQUAL TO. Have a look on your screenshot 😉

          Anyway, Power App is now working like a charm. Thank you very much, really appreciate your help!

          Now I need to work a little bit on formatting the output. Any idea how to make smaller gaps between the results? So based on your example I would like to achieve something like this:

          https://i.imgur.com/vBPMGhE.png

          1. Ingo Gegenwarth

            Hi Marcin,
            thank you for pointing this out. I came across this and I took another screenshot. Obviously, I missed to replace the image…
            In regards of the line height:
            have a look at the “TemplateSize” property for the gallery. Decrease the value, which should do the trick.
            I’ll have the article updated.
            Thanks again!
            Ciao,
            Ingo

  2. Marcin R.

    Hi Ingo. Great article but seems like I am stuck on creating 3 text responses inside the flow (rawResult, rawError, result). Says that the expression is invalid. Tried to replace ”” with ” and ‘’ with ” but with no luck. Not sure what I am doing wrong here. Any advise would be much appreciated.

    1. Marcin R.

      OK. Figured it out. The key here was to use ‘ ‘ everywhere. So in my case rawResult expression looks like this:

      if(contains(body(‘HTTP’),’An error occured while processing this request’),”,array(body(‘HTTP’)))

      But now I am stuck on the next step (Add Code to PowerApp). Getting errors as follows:

      https://i.imgur.com/WodHD0y.png

Leave a Reply