Blog Post

Secure Logic Apps with OAuth Authorization

,

I’ve used Logic Apps a couple of times over the past years for simple workflows, like sending an email (still not supported in ADF, booooo), reading a SharePoint List or copying some files from A to B (cheaper than the Copy Data Activity in ADF). When you create a Logic App with an HTTP trigger (which is most likely scenario if you’re using ADF to trigger the Logic Apps), an URL is generated:

It has the following format:

https://prod-xxx.myregion.logic.azure.com:443/workflows/someid/cdb/triggers/manual/invoke?api-version=2016-10-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=sastoken

The URL contains 4 parameters:

  • the API version
  • sp, which points to the trigger (service permission, it tells you what you can do with the URL)
  • sv = 1.0 (SAS version)
  • sig = SAS token

Because it includes a SAS token, basically anyone who knows the URL (you’d be surprised in what you can find in public git repos) can trigger your Logic App (and possibly send harmful stuff in the JSON body, such as a SQL injection attack). To avoid this, we’re going to ditch the SAS token and work with an authorization policy for the Logic App. You can set this up in the Logic App settings:

Click on Add Policy and specify the following properties:

  • Policy Name – you can choose what you want, and it doesn’t need to be unique
  • OAuth Type – you have the options Azure Active Directory (someone forgot to update that dropdown) and Azure AD with Proof of Possession (AADPOP). I choose the first one.
  • Issuer Claims – this is either https://sts.windows.net/tenant-id/ or https://login.microsoftonline.com/tenant-id/ depending on the access token you need. I used sts.windows.net.
  • Audience Claims – I’ve seen blog posts using https://management.core.windows.net/, but when using ADF to trigger the Logic App you can use https://management.azure.com/.

I cannot stress enough how important the slash is at the end of the URL. I forgot it at first, and I got errors at the ADF side: “One or more claims either missing or does not match with the open authentication access control policy”.

In ADF, we can now trigger the Logic App using a Web or Webhook Activity.

For the URL, you need to take the Logic App URL from the trigger, but drop all parameters except the API version. For the authentication, you can take the system-assigned managed identity (no passwords or secrets that can expire) and as resource you specify the audience from the OAuth policy. For the headers, you need to specify application/json as the Content-Type. The managed identity will fetch a token from Azure and include it as a bearer token in the HTTP headers, you don’t need to do this yourself.

If you would still specify the SAS token in the URL, you’ll get an error saying you can’t mix authentication schemes: “The request has SAS authentication scheme and an additional authorization scheme or internal token scheme. Only one scheme should be used.

This means that even though we specified the OAuth policy, the Logic App can still be triggered with the original URL. To avoid this, we need to modify the Logic App itself. In the trigger settings, we can specify that the Authorization HTTP header needs to include the word “Bearer”. If this isn’t the case, the Logic App won’t be triggered. You can use the following expression:

@startsWith(triggerOutputs()?['headers']?['Authorization'], 'Bearer')

If you would like to view the Authorization header, you need to add the following piece to the JSON code of the Logic App trigger:

,"operationOptions": "IncludeAuthorizationHeadersInOutputs"

This will include the (sanitized) Authorization header into the output:

You can also see ADF was the one that triggered the Logic App in the User-Agent header. You can view the actual bearer token by parsing the JSON headers (with the Parse JSON task):

This gives the following output:

You can decode the contents of the token on https://www.jwt.io/.

If you want that only ADF can trigger the Logic App, you can put a condition in the Logic App on the user-agent header:

The Logic App will still be triggered, but if it wasn’t by ADF you can prevent from any actual work being done. Another option would be to decode the bearer token in the Logic App itself and check the contents to see if it was ADF, but this is out-of-scope for this blog post. You can find more info on how to do this in the blog post Parsing JSON tokens in a Logic App.

If you have a Logic App calling itself recursively (or triggering other Logic Apps), you need to use the OAuth Policy as well. In the HTTP Webhook task, you can add Subscribe Authentication in the Advanced parameters:

There are different authentication types available, but as usual managed identity is our favorite.

I used a user-assigned managed identity, as it is easier to manage with CI/CD (read more about how to do this with Logic Apps here and here). When you extract the ARM template of the Logic App, you can see the OAuth Policy is included as well:

The post Secure Logic Apps with OAuth Authorization first appeared on Under the kover of business intelligence.

Original post (opens in new tab)
View comments in original post (opens in new tab)

Rate

You rated this post out of 5. Change rating

Share

Share

Rate

You rated this post out of 5. Change rating