Welcome to Day 10
of #30DaysOfLowCode!
The theme for this week is backend. Yesterday we talked about building custom connectors. Today we'll explore the topic of providing Power Platform custom connectors with additional security via Azure API Management. Ready? Let's go!
What We'll Cover
- Authentication Types for Custom Connectors
- Prerequisites
- Deploying Sample Apps
- Exercise – Try it yourself!
- Resources – For self-study!
Custom Connector Authentication Types
Power Platform custom connectors currently support four authentication flow options – No Auth flow, API Key Auth flow, Basic Auth flow and OAuth2 Authorisation Code Auth flow. "No Auth flow" is definitely not an option this time, but let's focus on the other three options throughout this post. You also need to be aware that those authentication types are mutually exclusive. In other words, you CANNOT combine two or more authentication scenarios on one custom connector. Also, if you want to use the API Key auth flow, you CANNOT use the other two authentication types within the custom connector. I'll discuss that later in this post.
Prerequisites
For this post, you need to have the following signed up:
- Microsoft 365 Developer Program
- Power Platform Developer Program
- Free Microsoft Azure subscription
- Free GitHub account
Deploying Sample Apps
Let's deploy the sample apps for this post. Fork this repository and follow the detailed instruction on its README to provision and deploy the sample apps. Once everything is done, you will have one API Management instance and three Azure Functions app instances representing authentication scenarios like API Key Auth, Basic Auth and OAuth2 Auth, respectively.
Each function app has already been integrated with API Management. Let's take a look at each authentication type.
1. API Key Auth
The first option is using an API key to provide extra security. Using Azure API Management, you can choose between:
- A concept called subscription, where you use the subscription key through a HTTP request header of
Ocp-Apim-Subscription-Key
- Or you can use a HTTP request query string of
subscription-key
.
Both options add another security layer to your API, in addition to your Azure Function app's x-functions-key
in the request header or code
in the request querystring.
Let's take a look at the API policy configurations in API Management.
Through this policy, the function app's API key is integrated. Therefore, you don't need to worry about the function app's API key.
Now, you want to add the API Management's API key. First, make sure your API settings have enabled the subscription. Also, ensure that no user authorization is enabled by selecting "None" against the "User authorization" option.
Export the OpenAPI document by selecting the "Export" menu and choosing the "OpenAPI v2 (JSON)" option. Then you will be able to download an OpenAPI document.
You might have a question here.
What does the "Create Power Connector" menu do? Isn't that for this API key auth?
That's actually a valid question. The only difference between exporting the OpenAPI document and creating the connector directly through the menu is that which tenant you want to export the connector to. If you want to only use within your tenant, the "Create Power Connector" is a simple and easy way to generate a custom connector. However, if your connector is not only for your tenant, but also other tenant, you should export the OpenAPI document and use it in the other tenants.
Therefore, throughout this post, you're assuming to use this custom connector in general purpose, rather than tied with your tenant.
Let's take a look at the document. It might look like the following JSON document, saying that you MUST use the API key through
Ocp-Apim-Subscription-Key
in the request header orsubscription-key
in the request querystring.{
"swagger": "2.0",
...
"securityDefinitions": {
"apiKeyHeader": {
"type": "apiKey",
"name": "Ocp-Apim-Subscription-Key",
"in": "header"
},
"apiKeyQuery": {
"type": "apiKey",
"name": "subscription-key",
"in": "query"
}
},
"security": [
{
"apiKeyHeader": []
},
{
"apiKeyQuery": []
}
],
"paths": {
...
}
...
}Alright. Let's import this OpenAPI document for a custom connector. Go to either
https://make.powerapps.com
for Power Apps orhttps://make.powerautomate.com
for Power Automate, and create a custom connector by importing an OpenAPI file.It automatically identifies the authentication type to "API Key", the API key parameter name of
Ocp-Apim-Subscription-Key
and the parameter location of "Header".After creating the connector, let's create a connection for the connector. Then, it requires the API key. Enter the API key generated from the API Management.
Test the connector to see whether it works OK or not.
We've added extra security to the custom connector with API Management's API key.
2. Basic Auth
The second option is to use the basic auth flow. It's important to know that API Management doesn't support this basic auth flow out-of-the-box. Although it's a limitation, you can still apply this flow for the Power Platform custom connectors by slightly modifying the OpenAPI document.
Let's take a look at the API policy, which is basically the same as the one in the previous section – integrate the function app's API key with API Management.
Make sure that you're not going to use the subscription key at this time. Therefore, disable the subscription key. By doing so, you no longer need the API key for this API.
WARNING: If you disable the subscription key for this exercise, your API endpoint works as like a public API – not secure at all. Therefore, you MUST implement the logic in your function app that validates the basic authentication header sent through API Management. As mentioned above, it's required to disable the subscription key because API Management doesn't natively support the basic auth feature. Therefore, if you want to use this approach, please use it with extra care.
Once you're ready, export the OpenAPI document by selecting the "Export" menu and choosing the "OpenAPI v2 (JSON)" option.
Then, you will be able to download an OpenAPI document. Let's take a look at the document. It might look like the following JSON document, saying that you MUST use either
Ocp-Apim-Subscription-Key
in the request header orsubscription-key
in the request querystring.However, you MUST replace both with the basic auth because you will not use the API key auth this time.
{
"swagger": "2.0",
...
"securityDefinitions": {
// ⬇️⬇️⬇️ Remove both 'apiKeyHeader' and 'apiKeyQuery' ⬇️⬇️⬇️
"apiKeyHeader": {
"type": "apiKey",
"name": "Ocp-Apim-Subscription-Key",
"in": "header"
},
"apiKeyQuery": {
"type": "apiKey",
"name": "subscription-key",
"in": "query"
},
// ⬆️⬆️⬆️ Remove both 'apiKeyHeader' and 'apiKeyQuery' ⬆️⬆️⬆️
// ⬇️⬇️⬇️ Add 'basicAuth' ⬇️⬇️⬇️
"basicAuth": {
"type": "basic"
}
// ⬆️⬆️⬆️ Add 'basicAuth' ⬆️⬆️⬆️
},
"security": [
// ⬇️⬇️⬇️ Remove both 'apiKeyHeader' and 'apiKeyQuery' ⬇️⬇️⬇️
{
"apiKeyHeader": []
},
{
"apiKeyQuery": []
},
// ⬆️⬆️⬆️ Remove both 'apiKeyHeader' and 'apiKeyQuery' ⬆️⬆️⬆️
// ⬇️⬇️⬇️ Add 'basicAuth' ⬇️⬇️⬇️
{
"basicAuth": []
}
// ⬆️⬆️⬆️ Add 'basicAuth' ⬆️⬆️⬆️
],
"paths": {
...
}
...
}Once you update the OpenAPI document, let's import this OpenAPI document for a custom connector. Go to either
https://make.powerapps.com
for Power Apps orhttps://make.powerautomate.com
for Power Automate, and create a custom connector by importing an OpenAPI file.It automatically identifies the authentication type as "Basic authentication", "username", and "password".
After creating the connector, let's create a connection for the connector. Then, it requires the username and password. The username and password in this sample app are for Atlassian Jira. Therefore, get your email address as the username and API token as the password from there.
Test the connector to see whether it works OK or not.
We've added extra security to the custom connector with basic auth.
3. OAuth2 - Auth Code
The third option is to use OAuth2. There are many authentication flows in OAuth2, but Power Platform custom connector only supports the Authorisation code auth flow at this time of writing. Therefore, let's focus on that. The basic idea of using any OAuth2 auth flow is to get the access token and the resources you want. It's safe to assume that the function app is able to understand the access token and process it.
To use OAuth2 auth flow, you need to first register an app in Azure Active Directory. After registering a new app, it will give the ability to get the access codes. I'm not going into too many details here, but it's worth taking a look at this document. Once you create the app, you will have the following information:
- Tenant ID
- Client ID
- Client secret
- Endpoint URL for authorization
- Endpoint URL for the access token
- Endpoint URL for the refresh token
With this information, you need to integrate it with API Management. Go to Azure Portal, open the API Management instance, and navigate to the "OAuth 2.0 + OpenID Connect" blade. Add a new OAuth2 service under the "OAuth 2.0" tab.
Enter the following details in the fields and create the service.
- Display name:
AuthCode Auth
- Client registration page URL:
http://localhost
- Authorization grant types: tick only on "Authorization code"
- Authorization endpoint URL: endpoint URL for authorization noted from the above
- Token endpoint URL: endpoint URL for access token noted from the above
- Default scope:
https://graph.microsoft.com/.default
- Client ID: client ID noted from the above
- Client secret: client secret noted from the above
After that, you will have both redirect URLs:
null/signin-oauth/code/callback/authcode-auth
null/signin-oauth/implicit/callback
Replace
null
with your API Management instance URL likehttps://{{APIM_NAME}}.azure-api.net
, where{{APIM_NAME}}
is your API Management instance name.- Display name:
Add both redirect URLs to your registered app on Azure AD as redirect URLs.
Check out the API policy, which is basically the same as in the previous sections – integrate the function app's API key with API Management.
Make sure you will not use the subscription key this time. Therefore, disable the subscription key. By doing so, you no longer need the API key for this API. In addition to this, because you're using OAuth2 authorization, choose the "OAuth 2.0" option and select the OAuth 2.0 server of "AuthCode Auth" that you just created right before.
It's also worth noting that because the custom connector sends the OAuth2 access token to the function app through API Management, it's safe to assume that the function app is able to understand the token and process it.
Once you're ready, export the OpenAPI document by selecting the "Export" menu and choosing the "OpenAPI v2 (JSON)" option.
Then, you will be able to download an OpenAPI document. Let's take a look at the document. It might look like the following JSON document, saying that you MUST use either
Ocp-Apim-Subscription-Key
in the request header orsubscription-key
in the request querystring.However, you MUST remove both because you will not use the API key auth this time. Make sure you MUST replace
{{TENANT_ID}}
with your tenant ID.{
"swagger": "2.0",
...
"securityDefinitions": {
// ⬇️⬇️⬇️ Remove both 'apiKeyHeader' and 'apiKeyQuery' ⬇️⬇️⬇️
"apiKeyHeader": {
"type": "apiKey",
"name": "Ocp-Apim-Subscription-Key",
"in": "header"
},
"apiKeyQuery": {
"type": "apiKey",
"name": "subscription-key",
"in": "query"
},
// ⬆️⬆️⬆️ Remove both 'apiKeyHeader' and 'apiKeyQuery' ⬆️⬆️⬆️
// ⬇️⬇️⬇️ Keep 'oauth2AuthCode Auth' ⬇️⬇️⬇️
"oauth2AuthCode Auth": {
"type": "oauth2",
"scopes": {
"https://graph.microsoft.com/.default": ""
},
"flow": "accessCode",
"authorizationUrl": "https://login.microsoftonline.com/{{TENANT_ID}}/oauth2/v2.0/authorize",
"tokenUrl": "https://login.microsoftonline.com/{{TENANT_ID}}/oauth2/v2.0/token"
}
// ⬆️⬆️⬆️ Keep 'oauth2AuthCode Auth' ⬆️⬆️⬆️
},
"security": [
// ⬇️⬇️⬇️ Remove both 'apiKeyHeader' and 'apiKeyQuery' ⬇️⬇️⬇️
{
"apiKeyHeader": [],
"oauth2AuthCode Auth": [
"https://graph.microsoft.com/.default"
]
},
{
"apiKeyQuery": [],
"oauth2AuthCode Auth": [
"https://graph.microsoft.com/.default"
]
}
// ⬆️⬆️⬆️ Remove both 'apiKeyHeader' and 'apiKeyQuery' ⬆️⬆️⬆️
// ⬇️⬇️⬇️ Add 'oauth2AuthCode Auth' ⬇️⬇️⬇️
{
"oauth2AuthCode Auth": [
"https://graph.microsoft.com/.default"
]
}
// ⬆️⬆️⬆️ Add 'oauth2AuthCode Auth' ⬆️⬆️⬆️
],
"paths": {
...
}
...
}Once you update the OpenAPI document, let's import this OpenAPI document for a custom connector. Go to either
https://make.powerapps.com
for Power Apps orhttps://make.powerautomate.com
for Power Automate, and create a custom connector by importing an OpenAPI file.It automatically identifies the authentication type to "OAuth 2.0" and the Identity Provider of "Generic OAuth 2". Then, enter the Client ID, Client secret, and the Refresh URL noted above. Using a different registered app here is OK if it's under the same tenant.
After creating the connector, let's create a connection for the connector. As you've already provided the client ID and secret, you will immediately create the connection.
Test the connector to see whether it works OK or not.
We've added extra security to the custom connector with OAuth2 - authorization code auth.
4. BFF - Combine Auth
Many organisations nowadays have requirements using the BFF (Backends-for-frontends) pattern through API Management, mainly if your organisation adopts microservice architecture. It's not uncommon that APIs use different authentication approaches for different APIs – one uses the API key auth, another uses the basic key auth, and the other uses the OAuth2 auth.
If you are about to build a BFF with those APIs using different authentication methods, what would you do? What could you do if you're even about to create the BFF for the Power Platform custom connector? There are many different combinations of authentication methods, but let's focus on following two – API key auth and basic auth:
First of all, you MUST choose which authentication type you will use for the main one for the Power Platform custom connector. If you want to use basic auth as the main one, the custom connector doesn't have to know the API key and vice versa. In other words, the other authentication method MUST be handled by the API Management policy of the BFF API.
Let's take a look at this OpenAPI document for BFF. It combines both apps using the API key auth and basic auth, respectively.
openapi: 3.0.1
...
paths:
/greeting:
get:
tags:
- greeting
summary: Greeting
operationId: Greeting
...
security:
- apiKeyHeader: [ ]
- apiKeyQuery: [ ]
/profile:
get:
tags:
- profile
summary: Profile
operationId: Profile
...
security:
- apiKeyHeader: [ ]
- apiKeyQuery: [ ]
- basicAuth: [ ]
...
components:
...
securitySchemes:
apiKeyHeader:
type: apiKey
name: Ocp-Apim-Subscription-Key
in: header
apiKeyQuery:
type: apiKey
name: subscription-key
in: query
basicAuth:
type: http
scheme: basicIt defines API key auth and basic auth in the document and applies them to each endpoint.
Import this OpenAPI to API Management. Then check out the settings. Make sure you MUST activate the subscription.
Add the
authentication-basic
as an inbound policy that sets the basic auth token to the request header. After this, API Management automatically injects this basic auth token into every request header.Export the OpenAPI document. As you use the API key auth, follow the 1. API Key Auth pattern.
In the Power Platform custom connector, you only need the API key provided by API Management to create the connection because API Management has already encapsulated the basic auth token.
Test the connector to see whether it works OK or not. As you can see, both endpoints work perfectly fine.
We've created a BFF by combining APIs that use API key auth and basic auth, and the BFF has been used for the Power Platform custom connector. However, as mentioned earlier in this post, we have to choose only one authentication type due to the restriction of authentication types in the Power Platform custom connector. Therefore, if you need more than one authentication type for your connector, you MUST choose one, and API Management MUST encapsulate all the others.
Theoretically, there are three possible combinations for BFF:
- API key auth and basic auth
- API key auth and OAuth2 auth code auth
- Basic auth and OAuth2 auth code auth
Throughout this post, we've walked through the first combination. After that, you can try the other two combinations on your end!
Exercise – Try it yourself!
If you haven't joined the following programs, it's time to do so for further learning!
- Microsoft 365 Developer Program
- Power Platform Developer Program
- Free Microsoft Azure subscription
- Free GitHub account
Then, follow the steps below. After that, you will be the one who knows better security on Power Platform custom connectors!
- Fork this GitHub repository to provision and deploy the sample apps.
- Read and follow the instructions for each scenario: