Skip to main content

Secure Logic App HTTP Endpoints with Azure API Management

Prerequisites ?


What ?

API Management (APIM) helps organizations publish APIs to external, partner, and internal developers to unlock the potential of their data and services. You can use API Management to publish APIs to external, partner, and employee developers securely and at scale. 

In this blog, we will be configuring APIM so that we can use it to secure our Logic App HTTP Endpoint from public access.


What are subscriptions?

When you publish APIs through API Management, it's easy and common to secure access to those APIs by using subscription keys. Developers who need to consume the published APIs must include a valid subscription key in HTTP requests when they make calls to those APIs. Otherwise, the calls are rejected immediately by the API Management gateway. They aren't forwarded to the back-end services.
To get a subscription key for accessing APIs, a subscription is required. 
Subscriptions can be associated with various scopes: product, all APIs, or an individual API.



What are products ?

In Azure API Management, a product contains one or more APIs as well as a usage quota and the terms of use. Once a product is published, developers can subscribe to the product and begin to use the product's APIs.
Products are associations of one or more APIs. You can include a number of APIs and offer them to developers through the developer portal. You can add an existing API during the product creation. You can add an API to the product later, either from the Products Settings page or while creating an API.
Developers must first subscribe to a product to get access to the API. When they subscribe, they get a subscription key that is good for any API in that product. If you created the APIM instance, you are an administrator already, so you are subscribed to every product by default.


Why ?

Logic App offers various kinds of authentication schemes to secure its HTTP Endpoints like SAS key, restrict based on IP, configure AAD, OAuth or other security. We need to secure our HTTP Endpoints so that they are not accessible by general public and they are secured via Industry standard authentication schemes.

Here is a small illustration of the security architecture using API Management and Logic Apps -


How ?

APIM has rich features that allow us to configure security mechanisms for our API's. It supports Identities, OAuth 2.0, Open ID Connect, Certificates, etc. 

We will be configuring OAuth 2.0 security layer for our API and then all requests to the APIM API should have Bearer tokens and only then the calls would be successful, else user will get UnAuthorized response from the APIM.  This will require an App to be registered in the Azure Active Directory, and the credentials of that app will be configured in the APIM. 

On top of the OAuth 2.0 layer, we will also restrict access to our Logic App HTTP Endpoint by IP, so that the endpoint allows calls only from the APIM to be successful. If someone having the Logic App HTTP endpoint URL tries to call the endpoint from their local machine or anywhere else, the call does not go through.

Steps ?

  1. App Registration
  2. Create Azure API Management Service
  3. Set up APIM
    1. Create APIM User
    2. Import Logic App Endpoint as an API
    3. Create a Product
    4. Create a Subscription
    5. Add OAuth 2.0 Authentication
    6. Enable OAuth 2.0 Authentication in API
    7. Update Inbound Processing Policy
  4. Test using APIM Developer Portal
  5. Test using Visual Studio Code
  6. Restrict access to Logic App Endpoint based on IP

Now lets go through each of the above mentioned steps and configure them in Azure portal. 

  1. App Registration - 

  • Navigate to https://portal.azure.com/ 
  • Go To Azure Active Directory
  • Click on App Registrations
  • Create a new Application
  • Select Web app / API, fill other fields and click on Create
  • Copy the Application ID, this will be needed later.
  • Go to Required Permissions
  • Click on Grant Permissions button under Required Permission section, and click on Yes, if there is any popup.
  • Now click on Keys, and give a Key name, and select Never Expired for duration field, and click on Save. Once saved, you will be shown Value of the Key, copy it as this will be required later. Also once you close this window, you wont be able to see this later.
  • After doing this, you need to provide the copied Application ID and Key, and other details in the VS Code as shown to generate the AD token.

  1.  Create Azure API Management Service


  • Navigate to https://portal.azure.com/ 
  • Click on Create a Resource from top left of screen
  • Search for API Management
  • Select API Management from the results and click on Create
  • Fill in the required details as indicated below and click on Create
    • Name - APIM Service Name
    • Subscription - Your Azure Subscription
    • Resource Group - Existing or New
    • Location - Any available location of your choice
    • Organization Name - A Unique Name for Organization
    • Administrator Email - your email address
    • Pricing Tier - Developer
  • Once you click on Create, it will take some time for the APIM deployment to complete and get activated.

  1. Set up APIM
    1. Create APIM User
      • Navigate to the APIM service that you have created and verify that it is up and activated. (If it is not yet ready, as soon as you open it in Azure portal, you will see a notification message like service is getting activated.)
      • From Left Navigation inside APIM, click on Users tab
      • Click on Add User button
      • Fill out required details like Name, Email, Password, etc. and click on Add button at bottom.
      • The user will be created and you can use the email and password for this user to Log In to the Developer portal for testing your APIM API's.
    1. Import Logic App Endpoint as an API
      • Navigate to the APIM service
      • Click on API from left navigation inside APIM
      • You will see a number of templates to get started with, select Logic App from those templates.
      • Browse for your logic app from your subscription
      • Provide a meaningful Display name for your API
      • Click on Create
      • Once you click on Create, APIM will analyze your logic app and create an API and an operation within that API for you.
    1. Create a Product
      • Navigate to the APIM service
      • Click on Products from left navigation inside APIM
      • Click on Add Product
      • Fill out basic details about your product like Name, Description, Id.
      • Select State as Published
      • Click on Select APIs button, then select your API that you created in previous step.
      • Finally click on Create and your product will be created.
    1. Create a Subscription
      • Navigate to the APIM service
      • Click on Subscriptions from left navigation inside APIM
      • Click on Add Subscription
      • Give a meaningful name to your subscription.
      • For Scope, select Product from the drop-down.
      • In the next field, select your Product that you just created in the previous step.
      • In the next field, select the User that we created few steps back.
      • Click on save. This will  create a subscription for you, associate the product that you selected with your subscription and generate a unique Subscription key for you. You will be required to pass this subscription key while calling the APIM API.
    1. Add OAuth 2.0 Authentication
      • Now that we have created API, Product and Subscription, next we will set up OAuth 2.0 Authentication in our API.
      • Navigate to the APIM service
      • Click on OAuth 2.0 from left navigation inside APIM
      • Click on Add from top
      •  Fill out the form as per below suggestions, only the fields that needs modification are mentioned below, remaining fields should be left as is - 
        • Display Name - a meaningful name
        • Id - a meaningful name
        • Client Registration Page URL - http://test (any valid URL)
        • Authorization Grant Types - only select Client Credentials
        • Authorization Endpoint URL - https://login.microsoftonline.com/your-tenant-id/oauth2/authorize
        • Authorization Request Method - Get and Post both should be selected
        • Token Endpoint URL - https://login.microsoftonline.com/your-tenant-id/oauth2/token
        • Client Id - App Id of the app you registered
        • Client - Secret - Secret key of the app you registered
      • Once you have set up everything like mentioned above, click on Create.
      • Your Authentication mechanism will then be set up, and is now available to be selected in any API that you want within your APIM instance.
    1. Enable OAuth 2.0 Authentication in API
      • Navigate to the APIM service
      • Click on API from left navigation inside APIM
      • Select your API created for the Logic App Endpoint
      • Click on Settings from right
      • Scroll down to the Security section, in the User authorization field, select OAuth 2.0
      • In the field OAuth 2.0 server, select the authentication mechanism from dropdown. This is the mechanism that we have just created in previous step.
      • Click on Save.
      • Now your API is secured using OAuth 2.0 and any incoming requests to any operation of this API must include a Bearer token to get through.
    1. Update Inbound Processing Policy
      • Navigate to the APIM service
      • Click on API from left navigation inside APIM
      • Select your API created for the Logic App Endpoint
      • From the available operations, select Post operation. (should be names as manual-invoke or something like it)
      • From right, you will see 3 tabs - Frontend, Inbound processing and Backend.
      • From the Inbound Processing tab, you need to click on </> button just next to Policies.
      • Once you click on that, you will get an editor window to modify Inbound processing policies for this API. Here you will have to add a policy to remove Authorization header from being passed to the Logic App. Just before the closing Inbound tag, add this line - 
      • <set-header id="apim-generated-policy" name="Authorization" exists-action="delete" />
      • What this does is that it just deletes the Authorization header from the request that is being passed to logic app if it exists.
      • If you miss this step, you will get 401 response and following error from logic app when you try to invoke the APIM API, which internally invokes the Logic App endpoint - 
      • { "error": { "code": "DirectApiAuthorizationRequired", "message": "The request must be authenticated only by Shared Access scheme." } }

  1. Test using APIM Developer Portal

  • Navigate to https://portal.azure.com/ 
  • Navigate to the APIM service
  • Click on Developer Portal from top of screen
  • You will be automatically logged in the Developer portal using Admin credentials. Since you have created the APIM, you initially have ADMIN role on it. You can alternatively log in using the user account that you have created in the APIM as well. 
  • This is where you can share the user accounts with external parties who are looking towards integrating with your API's. They can login to the Developers Portal, and will get all info about the API's that you have created. They can even try out the API's from the Developers Portal.
  • Once you are in the Developers portal home page, click on APIS tab from top.
  • Select your API that you created.
  • Click on Try it button.
  • Notice that subscription key is added as one of the request headers. This is because you have associated the API with a product and the product is in turn associated to a subscription. Having access to subscription generated a subscription key for you, and every API in APIM requires a subscription key to be invoked.
  • Scroll down and you will see a Request Body text area thats pre-filled as APIM has detected the type of input that the Logic App requires.
  • When you scroll down further, you will notice that there is an Authorization section, where your OAuth 2.0 mechanism that you created previously is present as a dropdown field. Select Client Credentials in dropdown, and you will be presented with a confirmation popup. Select Authorize button in the popup and APIM will generate a brerer token for you using OAuth 2.0 authentication mechanism, and add the same to the request header.
  • Once everything is set, scroll to bottom of screen and click on Send.
  • This will invoke the APIM API from the developer portal for you, and internally the APIM API will invoke the logic app and pass the request body to it. Remember we have added an inbound processing policy to the API as well. It will take care of preventing the authorization header from being passed to the Logic App. You should see a response from the API within seconds or milliseconds. 😊

  1. Test using Visual Studio Code

  • Open Visual Studio Code
  • Click on Ctrl + N (this will create a new file)
  • Click on Ctrl + K, M and select HTTP as Language
  • Copy and paste following code in VS Code

1
2
3
4
5
6
POST https://your-logic-app-endpoint-url HTTP/1.1
Content-Type: application/json

{
    "Name" : "Sachin Kumar"
}

  • In the JSON Body, you can update it with the JSON that your Logic App is expecting. Also update the Logic App Endpoint url in code.
  • Now right click in VS Code editor and click on Send Request. Alternatively you can also use shortcut to send the request using Ctrl + Alt + R
  • You will see a response from the Logic App with 200 Status code.
  • Next we will try getting the OAuth token from AAD using Client Id and Secret.
  • Click on Ctrl + N (this will create a new file)
  • Click on Ctrl + K, M and select HTTP as Language
  • Copy and paste following code in VS Code - 

1
2
3
4
5
6
7
8
@ClientId=add-your-client-id-here
@TenantId=add-your-tenant-id-here
@Secret=add-your-secret-key-here

POST https://login.microsoftonline.com/{{TenantId}}/oauth2/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id={{ClientId}}&client_secret={{Secret}}
  • Here you need to update it with Client Id, Secret Key and Tenant Id.
  • Now right click in VS Code editor and click on Send Request. Alternatively you can also use shortcut to send the request using Ctrl + Alt + R
  • You will see a response with OAuth Token and other details about the token like Expiry time, etc.
  • Now we will use this Token to make a call to APIM API
  • Click on Ctrl + N (this will create a new file)
  • Click on Ctrl + K, M and select HTTP as Language
  • Copy and paste following Code in VS Code - 

1
2
3
4
5
6
7
8
POST add-your-apim-api-endpoint-here
Content-Type: application/json
Ocp-Apim-Subscription-Key: add-your-subscription-key-here
Authorization: Bearer add-your-oauth-token-here

{
    "Name" : "Sachin Kumar1"
}
  • Here you need to update it with your APIM API endpoint url, Subscription Key to APIM, and the OAuth token you have received in previous step.
  • Now right click in VS Code editor and click on Send Request. Alternatively you can also use shortcut to send the request using Ctrl + Alt + R
  • You will see a success response from APIM API with status code as 200. 

  1. Restrict access to Logic App Endpoint based on IP

  • Now that we have secured our API using Subscription and OAuth 2.0, there is just one task remaining. The Logic App HTTP Endpoint can still be accessed from anywhere (local machine or VM) since it allows connections from public.
  • To prevent that as well, we can configure workflow settings within logic app to allow connections only from a specific IP ranges.
  • In our case, we will allow connections only from the APIM IP's.
  • Navigate to https://portal.azure.com/ 
  • Navigate to the APIM service
  • From left tab inside APIM, select properties.
  • You will see a field for Public Virtual IP (VIP) Address, copy the address from there.
  • Now Navigate to the Logic App
  • From left tab inside Logic App, go to Workflow Settings
  • Within Access control configuration on the form, select Specific IP ranges in the Trigger access option field.
  • Now within the next field IP ranges for Triggers, enter the IP address that you copied in the next step as a range. e.g. X.X.X.X-X.X.X.X
  • Now click on Save
  • From Now on, you wont be able to call Logic App Endpoint using HTTP call from anywhere outside of the APIM. Try giving it a try from VS Code or Postman, you will get error response saying IP is not configured to call the endpoint.
  • Also if you try hitting the same endpoint from APIM API that we created from the Developer Portal, you will see that you get a success response.

Advantages ?

There are various advantages to using APIM for securing your HTTP Endpoints. 

Firstly, APIM has wide variety of rick features that you can leverage to build highly scalable and efficient API layer for your endpoints. 

Secondly, APIM allows you to set different types of Inbound/Ourbound Processing policies, which can help you solve various business requirements just by simple configurations.

Lastly, APIM can integrate with various caching providers like Redis Cache so that you can cache responses and save resources and time.

So  I hope you will be able to follow the above mentioned steps easily and secure your Logic App endpoints, just like I did in the blog. Hope this was helpful, feel free to leave your comments/suggestions and I should be able to get back to you on them.

Happy coding. 😊😊

Comments

Post a Comment

Popular posts from this blog

Handling Concurrency in Azure Functions (HTTP Triggered)

Concurrency & Isolation Concurrency is one of the most common requirements when we don't want the resource to be accessed by multiple requests at the same time. Lets say we have a Database that holds products stock information, then it is very important that any read/write operation that happens on the Database must hold the property of Isolation . The isolation property ensures that the concurrent execution of transactions results in a system state that would be obtained if transactions were executed sequentially, i.e., one after the other. Providing isolation is the main goal of concurrency control. Depending on the concurrency control method (i.e., if it uses strict – as opposed to relaxed – serializability), the effects of an incomplete transaction might not even be visible to another transaction. Options Available in Azure Functions Recently while working on Azure Functions, I discovered a really simple way of handling Concurrency via code. There are ways to con

Azure Functions - Retrieve data from Dynamics 365 CRM/CE Online using CRM OData Web API

Introduction: This blog describes how you can retrieve data from Dynamics 365 CRM/CE Online in an Azure Function, using CRM OData Web API. The CRM Web API has a couple of advantages over the traditional SOAP based approach to interact with CRM. These are rest based services, its easy to use and transport over http protocol , and there is no need to use additional web resources (XrmServiceToolkit ) of SDK (SDK.REST). Here is a detailed documentation on CRM OData Wbeb API. I will be using an Azure Function Application in Visual Studio 2017 to retrieve records from Dynamics 365 CRM/CE, by making use of OData API Endpoint provided by CRM. Prerequisites: Dynamics 365 CRM Online Trial https://trials.dynamics.com/ https://signup.microsoft.com/Signup?OfferId=bd569279-37f5-4f5c-99d0-425873bb9a4b&dl=DYN365_ENTERPRISE_PLAN1&Culture=en-us&Country=us&ali=1 Azure Subscription related to CRM Online instance https://portal.azure.com/ Visual Studio 2017 with Cl

Retrieve 5000+ Records in Dynamics 365 CE using CRM OData, Fetch XML and C#

If you want to retrieve 5000+ records in Dynamics 365 CE, you need to make use of Paging concept of CRM. By default 5000 records are retrieved in a single OData call in CRM. To get more, you need to make subsequent calls to OData Endpoint by passing a paging cookie in the request. I will be using a simple C# Console Application to retrieve 5000+ records from Dynamics 365 CE, by making use of OData API Endpoint provided by CRM and passing Fetch XML in OData Call . Concept: CRM OData Endpoints allows us to use Fetch XML to retrieve data from Microsoft Dynamics 365 CE.  If your resultset has more than 5000 records, you will be returned with first 5000 records ONLY in one OData call. To know if the resultset has more than 5000 records, we make use of the response from OData call. The response is added with a cookie value contained in a key - "@Microsoft.Dynamics.CRM.fetchxmlpagingcookie" If you wish to fetch the next set of resultset data, you will have to pass this c