Search code examples
node-redazure-web-app-serviceazure-api-management

Reverse proxy/daemon in Azure


I have setup a node-red instance as an Azure Web App for the sole purpose of creating a selection of API web services. Currently, this is secured by Active Directory which is simple and effective. However, ultimately we would like to make some of the APIs publicly available (via Microsoft accounts perhaps). This means access to the web app needs to be opened up to some extent which makes me nervous.

What I would like to do is have something like a reverse proxy service that would forward calls to a restricted set of URL paths. Further, to avoid having to provide web app access to non-AD accounts, I would like a daemon service on the proxy to make the calls on behalf of a service account.

I was hoping that such functionality would be part of Azure API Management but as far as I can tell it just forwards all API calls to the back end for authentication there.

Looking for suggestions on how to achieve the above.


Solution

  • Create 2 AAD apps: 1 for the node-red backend web app and 1 for APIM. The App URI ID for the backend needs to be in the format: "https://****webappid****.azurewebsites.net/.auth/login/aad/callback".

    In APIM, add the inbound policy as shown below, inserting the values relevant to your environment.

     <policies>
        <inbound>
            <!--          Authenticate as the "Azure API Management Service" app in AD and get token to authenticate with backend          -->
            <!--      Active Directory tenant      -->
            <set-variable name="tenantid" value="****your AD tenant id here****"/>
            <!--      Application id of APIM Service app in Active Directory      -->
            <set-variable name="clientid" value="*** your application id here****"/>
            <!--      Key from APIM Service app in Active Directory      -->
            <set-variable name="key" value="*** your application key here****"/>
            <!--      App ID UR for the backend app in Active Directory      -->
            <set-variable name="audience" value="https%3A%2F%2F****your backend web app id here****.azurewebsites.net%2F.auth%2Flogin%2Faad%2Fcallback"/>
            <send-request mode="new" response-variable-name="reply" timeout="10" ignore-error="false">
                <set-url>@("https://login.microsoftonline.com/"+context.Variables.GetValueOrDefault<string>("tenantid")+"/oauth2/token")</set-url>
                <set-method>POST</set-method>
                <set-header name="Content-Type" exists-action="override">
                    <value>application/x-www-form-urlencoded</value>
                </set-header>
                <set-body>@("grant_type=client_credentials&client_id="+context.Variables.GetValueOrDefault<string>("clientid")+"&client_secret="+context.Variables.GetValueOrDefault<string>("key")+"&resource="+context.Variables.GetValueOrDefault<string>("audience"))</set-body>
            </send-request>
            <!--          Extract token from reply          -->
            <set-variable name="accesstoken" value="@((String)((IResponse)context.Variables["reply"]).Body.As<JObject>()["access_token"])"/>
                <!--          Add authentication token to request          -->
                <set-header name="Authorization" exists-action="override">
                    <value>@("Bearer " + context.Variables.GetValueOrDefault<string>("accesstoken"))</value>
                </set-header>
            </inbound>
            <backend>
                <forward-request/>
            </backend>
            <outbound/>
        </policies>