AAD API Azure API management JWT Validation Logic Apps

Deep-diver: Hardening authentication and authorization between logic apps and API management

I’ve recently surveyed that most integrations with Logic Apps HTTP request trigger are added with out-of-the-box integration settings to API management. While this is fairly easy to do, it’s security relies on secret embedded on the static URL. There are various scenarios where you accidentally can leak such url: pasting it from clipboard to google search etc, including it Github repos, and after all the fact that you need to rotate such key. This post focuses on reducing the use of such authentication methods between APIM and Logic Apps.

Problem = using url embedded secret?

Reference information about URL Security


Solution: use Managed Service Identity, and Azure Active Directory Authorization Policies in Logic Apps

Luckily for us API management and Logic Apps offers also out-of-the-box possibility to authorize downstream calls from API management to logic app back-end with OAuth2 Access Tokens. This solution offers multiple benefits, and one caveat can mitigated with trigger conditions.


”Credential-less” No secrets to leak, no rotation needed (*), no need to get static credentials from key vault

✅ Authorization is tied into lifecycle of the APIM instance. If you delete the instance, you don’t need to worry about left behind credentials

Another key takeaway?

While this post explores the relationship between APIM and Logic Apps, its worth noting that APIM offers really easy way to generate access tokens with Managed Identity inside policy definition, which virtually can extend this towards any downstream API that offers validating JWT tokens


Azure API Management authentication policies | Microsoft Docs



✅ You have imported logic app to APIM


✅ Enable managed Identity for APIM, and get appid of the managed identity by searching SPN’s with the ObjectID of the Managed Identity pane in APIM

You can also get the managed Identity with PowerShell

✅ Configure policies in logic app from ’Authorization’ pane

Explanation of policies

  • Issuer ensures that only the current tenant can issue those tokens
    • Audience and appid needs to be the same, effectively limits it to the APIM instance
    • Appidacr ensures that token from Managed Identity is based on certificate authentication
Docs example for AppIdacr claim

✅ Remove SAS authorization from template

✅ Edit the following policy to include the AppID you got on earlier step

        <base />
        <authentication-managed-identity resource="50a9e8ec-1b06-44fa-b372-030eb6d94129" output-token-variable-name="msi-access-token" ignore-error="false" />
        <set-method id="apim-generated-policy">POST</set-method>
        <rewrite-uri id="apim-generated-policy" template="/manual/paths/invoke/?api-version=2016-06-01&amp;sp=/triggers/manual/run" />
        <set-header id="apim-generated-policy" name="Ocp-Apim-Subscription-Key" exists-action="delete" />
        <set-header name="Authorization" exists-action="override">
            <value>@("Bearer " + (string)context.Variables["msi-access-token"])</value>
        <base />
        <base />
        <base />

✅ APIM trace for successful use of Access Token on back-end call

Deny use of SAS tokens without interfering with business Logic

At the moment of writing logic apps still allow using SAS tokens in the URL; So even if Authorization Policy is enabled for Oauth2 authorization; The caveat is that attacker can still use ”URL authentication” scheme to bypass APIM, even when you have ensured that APIM uses the Managed Identity; Luckily we have quite feasible workaround for this by ensuring Authorization headers are present in all requests processed in Logic App.

SAS Tokens and Oauth2 at docs https://docs.microsoft.com/en-us/azure/logic-apps/logic-apps-securing-a-logic-app#generate-shared-access-signatures-sas

Workaround solution

Deny use of SAS keys


✅ Include authorization header in logic apps (When this is done correctly this authorization header only works for this app, so the risk of leaking the authorization header from Logic Apps itself is self-mitigating)

ref Include ’Authorization’ header in request trigger outputs

✅ Check the presence of authorization header in ”Trigger Conditions” with the following condition:

  • < @startsWith(triggerOutputs()?['headers']?['Authorization'], 'Bearer' ) >
    • Had to do quite bit of digging into getting ”Trigger Conditions” syntax correct, found a good link here
  • This essentially forces all calls to have Authorization header of the Managed Service Identity be passed to the Logic app
      1. ✅”Trigger Condition” All calls must have Authorization header with Bearer string in the beginning
      2. ✅”Logic Apps Authorization logic” Any call that has Authorization header can’t have SAS token in the URL
      3. ”Logic apps Authorization Logic” Any call that has Authorization header must pass the authorization logic

Protection examples:

🔴 Attacker calls with SAS correct token results in

code: 'InvalidTemplate',
message: "The template language expression evaluation failed: 'The template language function 'startsWith' expects its first parameter to be of type string. The provided value is of type 'Null'. Please see https://aka.ms/logicexpressions#startswith for usage details.'."

🔴 Attacker calls with SAS token and forged Access token results in

code: 'DirectApiRequestHasMoreThanOneAuthorization',
message: "The request has both SAS authentication scheme and 'dogs' authorization scheme. Only one scheme should be used."

🔴 Attacker calls with Access Token

{"code":"MisMatchingOAuthClaims","message":"One or more claims either missing or does not match with the open authentication access control policy."}

✅ Valid caller calls trough APIM (Empty SQL response for SQLI)

200 { ResultSets: {}, OutputParameters: {} } OK

Secure access and data – Azure Logic Apps | Microsoft Docs

  • There is also the possibility of combining this with the IP restrictions on inbound calls for Logic apps, but that would somewhat add extra overhead, that this method is reducing in the first place.


You can greatly enhance the security of Logic Apps Inbound calls even without IP restrictions in place for inbound calls by enforcing the use of managed identity to be checked at Logic Apps side

3 comments on “Deep-diver: Hardening authentication and authorization between logic apps and API management

  1. Paluuviite: Azure API Management – Call Azure Functions with Managed Identity – SecureCloudBlog

  2. Hi! Another workaround to prevent the attacker to call Logic App using SAS is to filter incoming requests by IP address. We can use the public VIP of APIM here.


    • Hi you are correct. This also mentioned in the blog, as it it’s valid alternative, are can work in conjunction with this method “There is also the possibility of combining this with the IP”



Täytä tietosi alle tai klikkaa kuvaketta kirjautuaksesi sisään:


Olet kommentoimassa WordPress.com -tilin nimissä. Log Out /  Muuta )


Olet kommentoimassa Facebook -tilin nimissä. Log Out /  Muuta )

Muodostetaan yhteyttä palveluun %s

%d bloggaajaa tykkää tästä: