NOTE: This blog post was written in June 2016 and is based upon a preview of Azure Logic Apps. The functionality is bound to change in the future. I have no additional information about when the new functionality may, or may not, be available.
Recently I have been working on a PoC where I have created an API App that needs to talk to an On-Premise REST Service hosted in a 3rd party platform called Denodo. I will talk about those details in a future post. But for the purpose of this post I want to discuss how I can secure, using Azure AD, my Denodo API App. In the broader solution that I am working on, I know this API App will be called from a Logic App. As a result, I want to prove out that a Logic App can authenticate, with Azure AD, while calling my API App.
Some documentation that did help me out in this journey was the following post from Stephen Siciliano. In the comments, Jeff Hollan also provided some commentary that was helpful. There were still a few bumps in the road, so I figured I would document exactly the steps that I followed, in order to provide a more streamlined experience.
Part 1 – Enabling Authentication on Endpoint
- Build your API App in Visual Studio. In my case I am wrapping an existing REST API that is provided by Denodo platform. One of the benefits of wrapping it using App Service is that I can add Swagger meta data, which will help me in Logic Apps. Also, by using an App Service, I can bridge cloud and on-prem using either Hybrid Connections or a VPN connection. More on the hybrid connectivity in next post (promise).
- Enable Swagger metadata by uncommenting the .EnableSwaggerUI call in the SwaggerConfig.cs
- Publish App Service. You will need to specify/create an Azure APP Service Plan, Azure Subscription and Resource Group.
- With the Azure App Service Authentication set to off we will be able to access our API through a browser.
- By navigating to our APP Service URL and appending “/Swagger” we will see our API exposed. We can interact with our API by clicking on Try It Out!
- At this point we know our API is working and in my case it is calling an on-prem REST API.
NOTE: When you first deploy your API App, a swagger file will be created. You should download this file before you start locking down your endpoint.
- At my organization we heavily leverage Azure AD. Whenever we are doing something with cloud, we try to plug-in to Azure AD as we can centrally manage it and it generally plays nice in the Microsoft ecosystem and other SaaS apps.
- At first I thought I was going to have to create an Azure AD Application by going into the old portal, but you don’t have to do that any more. Within the new Azure AD Portal there is some slick integration going on.
- While in your App Service click on Authentication/Authorization and turn on App Service Authentication and and select Log in with Azure Active Directory.
- Click on Azure Active Directory under Authentication Providers
- From Management mode select Express
- Create New AD App and provide AD App Name.
- Save your configuration
- If you then navigate to your Web API/Swagger console you should now be challenged to authenticate against Azure AD. Enter your credentials and you can interact with Swagger console.
- At this point your endpoint is secure, but how do you connect Logic Apps to use it? Keep reading.
Part 2 – Exposing Swagger Metadata
As of this writing (June 2016), you will have issues with Logic Apps being able to consume your Swagger metadata. The reason for this is that Logic Apps (at least for now) requires that the Swagger metadata is available from a public source and over HTTPS. As soon as you locked down your endpoint, the swagger metadata is not publicly available.
For now (as I fully expect that Microsoft is working on a cleaner solution), Take your swagger metadata and place it in Blob storage without any authentication around it. To do this perform the following steps:
- Create the storage account from the new portal
- Use the Resource manager Deployment model, it can be General Purpose with Standard Performance, using Locally-redundant storage (LRS) and provide a Resource Group.
- With your storage container created, you can then use a tool like Azure Storage Explorer to manage your storage instance.
- While logged in with my Storage Account credentials (available from Azure Portal) I created a new Blob Container and then set the access level to Public
- Use the Upload button to update your swagger meta data and then you can view your URI for your document by having it selected and clicking on View.
Unfortunately we are not done yet. We now need to deal with CORS. There are ways to enable CORS for blob storage but I decided not to go down that path…at least for now. As part of the original article that I referenced, Jeff Hollan from the Logic Apps team has provided a bit of a work around to get around CORS. With your swagger file in a public blob storage, you can take that URL and use his utility which has a “CORS bypass” enabled. This may not be a long term solution and I can’t speak to how long Jeff will keep this alive but for now it works for me. If you want to enable CORS for your storage account then check out this link.
To use Jeff’s workaround I just added my Swagger/Blob Storage URL to his helper api:
- I then need to update my API Definition in my API App to use this new URL.
Part 3 – Wiring Logic App to use AAD
In order to complete this part we are going to need some data from Azure AD. In order to get this data we need to get it from the old portal at https://manage.windowsazure.com.
Ultimately, we need to construct a message that looks the following so that we can provide it as an Authentication header in our API Call
{“audience”:”<SignOnURL>”,
“clientId”:”<ClientID>”,
“secret”:”<Secret>”,
“tenant”:”<TenantID>”,
“type”:”ActiveDirectoryOAuth”}
Now the question is where do you get these values? You get them from your Azure AD instance and more specifically the Azure AD App that you created in Part 1 of this blog post. In the following image I have outlined exactly where to get the required values.
With this information in hand we can now create a new Logic App. To keep things simple, I have created a Logic App and use a Recurrence Trigger, mainly so that I can trigger it on demand.
Next, I should be able to select Show APIs for App Services in the same region and my API should show up.
Note: If you have any issues with Swagger meta data, this is where you will see them. You may see the dreaded “Failed to fetch swagger. Ensure you have CORS enabled on the endpoint and are calling an HTTPS endpoint” error. If so you likely have one of two issues:
- Swagger Metadata not being publicly accessible
- CORS
For my API, I am only performing a GET and as a result do not have any query parameters. The only data I need to send is in my Authentication Header which we covered in a previous step.
When submitting a message and getting an error like the following, then that means something hasn’t been set up correctly with your Authentication header.
{“code”:”BadRequest”,”message”:”Http request failed as there is an error getting AD OAuth token: ‘AADSTS70001: Application with identifier ‘<bad_token>’ was not found in the directory aff3442b-5f55-409c-be77-da97b366435a\r\nTrace ID: 54eb2e86-2e1b-46p9-8d14-983102278428\r\nCorrelation ID: 873a248f-900c-4f19-9684-447b5bfe6da4\r\nTimestamp: 2016-06-27 03:01:28Z’.”}
Conclusion
I fully expect Microsoft to make this a simplier and more streamlined experience but until that time, I think it is important that people are locking down their Azure resources. Lately I have been doing a lot of PoCs with the business and other IT groups. Naturally the question about security is going to come up and I am not going to just say it is secure, or say it is possible for it to be secure – I want to ensure it is secure. Once you have the process down, I also don’t think it is too much effort to get it working once you understand all of the mechanics involved.