Create a custom connector for Azure AD–protected Azure function apps

A key principle with Microsoft Power Apps connectors that use Azure Active Directory (Azure AD) for authentication is that they don't provide users with access to any data that the user doesn't already have access to. This is because the API call to the Azure AD–protected service executes under the user identity used to sign in to the connector. Therefore, the target service maintains responsibility for enforcing what's permitted for the authenticated user.

This tutorial shows you how to use Azure Functions to build a REST API, enable Azure AD authentication, and then make it available to Power Apps as a custom connector.

Create Azure function apps by using Visual Studio Code

With Azure Functions, you have many options to consider, including hosting options, language choice, and authoring options such as using the Azure portal, Visual Studio Code, or Visual Studio. For this tutorial, we'll use C# and Visual Studio Code. To complete this tutorial, you must first complete the Quickstart: Create a C# function in Azure using Visual Studio Code tutorial. Make note of the name you provided for your function app in the Create the function app in Azure step.

Important

Don't complete the Clean up resources section in the Quickstart. You'll need to keep all your resources in place to build on what you've already done.

Protect calls to Azure function apps by using Azure AD

  1. Find your function app in the Azure portal. Select the name of your function app in the list.

    List of function apps in the Azure portal.

  2. Select the Platform features tab.

    The Platform features tab highlighted on the Function Apps blade in the Azure portal.

  3. From the Networking group, select the Authentication / Authorization link.

    The Authentication / Authorization link highlighted on the Function Apps blade in the Azure portal.

  4. On the Authentication / Authorization blade, turn on the App Service Authentication toggle.

    The On option for the App Service Authentication toggle highlighted in the function app authentication settings in the Azure portal.

  5. In the Action to take when request not authenticated dropdown, change the value to Log in with Azure Active Directory. This setting ensures that anonymous requests to the API won't be allowed.

    The 'Log in with Azure Active Directory' option highlighted in the 'Action to take when request not authenticated' dropdown list on the function app authentication settings blade.

  6. Next, in the list of authentication providers, select Azure Active Directory.

    'Azure Active Directory' highlighted in the list of authentication providers for a function app.

  7. On the Azure Active Directory Settings blade, set the Management mode option to Express. Set the second Management mode option to Create New AD App.

    Azure Active Directory Settings blade opened for a function app in the Azure portal.

    Important

    Before you continue, copy the value in the Create App field and paste it somewhere for later. This value represents the name of the Azure AD application that you'll use to secure the API. You'll use this value later when you configure your custom connector.

  8. Select OK to confirm your selection.

  9. Back on the Authentication / Authorization blade, select Save to update the function app authentication and authorization settings.

    The Save button highlighted on the Authentication / Authorization blade for a function app in the Azure portal.

  10. After saving, select Azure Active Directory in the Authentication Providers section.

    Azure Active Directory Provider.

  11. Select the Azure AD App, and then copy the Client Id value and paste it somewhere for use later.

    Client Id page.

  12. Confirm that the API is correctly secured by opening a new browser window in private mode and going to the API. The URL for your function app can be found in the Overview section of the Function Apps blade. If the authentication settings have been applied correctly, you should be redirected to the Azure AD sign-in page.

    Azure AD sign-in page.

Create a custom connector for your Azure function app

To create a custom connector that uses Azure AD authentication, you must create an Azure AD app registration to secure the custom connector and acquire delegated access to the Azure function app protected by the Azure AD app registration created in the Protect calls to Azure function apps by using Azure AD section.

Create an app registration for your custom connector in Azure AD

First, create an Azure AD application for your custom connector. This is required to grant the custom connector permission to call your Azure function app.

  1. Go to the App registrations page in the Azure portal.

    Azure AD registrations page in the Azure portal.

  2. In the list of registered applications, select New registration.

    New registration button.

  3. Enter a name for your application, select the supported account types and platform configuration (optional), and then select Register.

    Under Supported account types, select Accounts in this organizational directory only. Under Platform configuration, select Web API.

    Note

    To learn more about app registration options, go to Quickstart: Register an application with the Microsoft identity platform.

  4. After selecting Register, you'll be shown API permissions for your App registration.

    API permissions screen.

  5. Select Add a permission.

    Add a permission button.

  6. Select the APIs my organization uses tab, and then search for the app name from step 7 in the Protect calls to Azure function apps by using Azure AD section. When you find it, select the name of the app.

    Important

    Your app name will be different than what's in the screenshot.

    Azure function app name.

  7. Select the user_impersonation checkbox, and then select Add permissions.

    Add user_impersonation permission.

    Note

    To learn more about permissions, go to Permissions and consent in the Microsoft identity platform endpoint.

  8. Select Certificates & secrets, and then select New client secret.

    Certificates & secrets.

  9. Enter a description for your secret, select an expiration period, and then select Add.

    Add a client secret.

  10. Your new secret is displayed. Copy and paste the value somewhere. You'll need it later.

    Screenshot that shows the new secret in the Client secrets section.

  11. Select Overview, and then copy and paste the value of the Application (client) ID somewhere. You'll need it later.

    Screenshot that shows the Application (client) I D value.

Keep this page open so you can come back to it. There is one more step in the Azure portal, but first you create a custom connector.

Create a custom connector

Now that the Azure AD application is configured, you create the custom connector. To create a custom connector, you must describe the API you want to connect to so that the connector understands the API's operations and data structures. When building Azure function apps for custom connectors, you'll often iteratively build your connector by repeating the following steps:

  1. Create, test, and debug the Azure function app locally by using Visual Studio Code.
  2. Deploy your function app to Azure.
  3. Update the custom connector configuration to reflect changes in your function app.

Postman is a popular tool to test web APIs. It's often used to test Azure function apps. In this topic, you'll create a custom connector from a Postman collection. The Postman collection will be provided for you.

Note

Go to the Create a Postman collection for a custom connector topic to learn how to create your own. Using Postman to create a custom connector is just one option. Go to the Describe the API and define the custom connector topic to learn about others.

  1. In a new browser tab, sign in to Power Apps or Power Automate.

  2. Copy the code below. Using your favorite text editor, create a new file, and paste the code as the contents of the file. Save the file. You can name it whatever you prefer, but remember the name (for example, tutorial-custom-connector.json). You'll need to use this file in the next steps.

    {
        "id": "c4b5deba-f97b-47d0-82a5-a2b32561fb01",
        "name": "Custom Connector",
        "description": null,
        "auth": null,
        "events": null,
        "variables": [],
        "order": [
            "374365a1-ede5-4ead-8068-d878085dad26"
        ],
        "folders_order": [],
        "protocolProfileBehavior": {},
        "folders": [],
        "requests": [
            {
                "id": "374365a1-ede5-4ead-8068-d878085dad26",
                "name": "Hello",
                "url": "http://localhost:7071/api/Hello",
                "description": "",
                "data": [],
                "dataOptions": {
                    "raw": {
                        "language": "json"
                    }
                },
                "dataMode": "raw",
                "headerData": [
                    {
                        "key": "Content-Type",
                        "name": "Content-Type",
                        "value": "application/json",
                        "description": "",
                        "type": "text"
                    }
                ],
                "method": "POST",
                "pathVariableData": [],
                "queryParams": [],
                "auth": null,
                "events": null,
                "folder": null,
                "responses": [
                    {
                        "id": "46baba58-7b85-4a2e-8c7d-303080e08ba9",
                        "name": "Hello",
                        "status": null,
                        "mime": null,
                        "language": "plain",
                        "text": "Hello, Marc. This HTTP triggered function executed successfully.",
                        "responseCode": {
                            "code": 200,
                            "name": "OK"
                        },
                        "requestObject": {
                            "data": [],
                            "dataMode": "raw",
                            "dataOptions": {
                                "raw": {
                                    "language": "json"
                                }
                            },
                            "headerData": [
                                {
                                    "key": "Content-Type",
                                    "name": "Content-Type",
                                    "value": "application/json",
                                    "description": "",
                                    "type": "text"
                                }
                            ],
                            "method": "POST",
                            "pathVariableData": [],
                            "queryParams": [],
                            "url": "http://localhost:7071/api/Hello",
                            "rawModeData": "{\n\t\"name\": \"Marc\"\n}"
                        },
                        "headers": [
                            {
                                "key": "Date",
                                "value": "Wed, 04 Mar 2020 22:32:06 GMT"
                            },
                            {
                                "key": "Content-Type",
                                "value": "text/plain; charset=utf-8"
                            },
                            {
                                "key": "Server",
                                "value": "Kestrel"
                            },
                            {
                                "key": "Transfer-Encoding",
                                "value": "chunked"
                            }
                        ],
                        "cookies": null,
                        "request": "374365a1-ede5-4ead-8068-d878085dad26",
                        "collection": "c4b5deba-f97b-47d0-82a5-a2b32561fb01"
                    }
                ],
                "rawModeData": "{\n\t\"name\": \"Marc\"\n}",
                "headers": "Content-Type: application/json\n",
                "pathVariables": {}
            }
        ]
    }
    
  3. On the left pane, expand Data, and then select Custom Connectors.

    Screenshot that shows Data and Custom Connectors on the left pane.

  4. In the upper-right corner, select New custom connector, and then select Import a Postman collection.

    Import a Postman collection.

  5. Enter a name for the connector, select Import, browse to the file you created in step 2, and then select Continue.

    Name and file location.

  6. The General page opens. Change the Scheme to HTTPS, replace the Host value with the domain of your function app, and then advance the wizard to the Security page.

    General information settings.

  7. On the Security page, provide Azure AD information for the application:

    OAuth settings.

    After entering security information, select Update connector to create the custom connector.

  8. On the Security page, the Redirect URL field is now populated. Copy this URL so you can use it in the next section of this tutorial.

    Note

    You might need to scroll down to see the redirect URL.

    Screenshot that shows the Redirect U R L field.

  9. In another browser tab, return to the app registration you created in the Create an app registration for your custom connector in Azure AD section. Make sure you're in the Overview section, and then select Add a Redirect URI.

    Screenshot that shows the Add a Redirect U R I button.

  10. Select Add a platform.

    Add a platform button.

  11. On the Configure platforms pane, select Web.

    Screenshot that shows Web on the Configure platforms pane.

  12. On the Configure Web pane, paste the Redirect URL value from step 7, and then select Configure.

    Screenshot that shows the Configure Web pane.

  13. Return to the browser tab containing the custom connector configuration. You should still be on the Security page in the wizard.

  14. Advance to the Definition page in the wizard by selecting the word Definition, and review.

    Screenshot that shows the Definition button.

    Note

    The definition comes from the Postman collection you imported. If you changed any of the code in the Quickstart: Create a C# function in Azure using Visual Studio Code tutorial, the import file might not match the shape of your API. You'll either need to create a new Postman collection or manually adjust the action in the custom connector. To create a new Postman collection, use the links shared earlier in this tutorial here. To manually adjust the action, you can review the Create the connector definition section of the Create a custom connector from scratch tutorial.

Test the connector

Now that you've created the connector, test it to make sure it's working properly. Testing is currently available only in Power Automate and Power Apps.

  1. Advance to the Test page in the wizard by selecting the word Test.

    Test page.

  2. On the Test page, select New connection.

    Screenshot that shows the New connection button.

  3. Select Create, and then sign in with your Azure AD user.

    Screenshot that shows the Create button and the sign-in screen.

  4. Return to the Test page, and do one of the following:.

    • In Power Automate, you're taken back to the Test page. Select the refresh icon to make sure the connection information is updated.

      Refresh connection.

    • In Power Apps, you're taken to the list of connections available in the current environment. On the left pane, select Custom Connectors. Find your custom connector, and then select the edit icon.

      Screenshot that shows the list of custom connectors.

  5. Go back to the Test page, enter a value for the name field, and then select Test operation.

    Test operation.

  6. Review the Request and Response.

    Screenshot that shows the request fields of Url, Method, Headers, ane Body.

    Screenshot that shows the response fields of Status, Headers, and Body.

Next steps

Now that you've created a custom connector and defined its behaviors, you can use the connector.

Provide feedback

We greatly appreciate feedback on issues with our connector platform, or new feature ideas. To provide feedback, go to Submit issues or get help with connectors and select your feedback type.