Mobile app performing an HTTP Post to Azure Function using Bearer Token and Function Key returns Unauthorized

353 Views Asked by At

I'm using a mobile app and am receiving an Unauthorized response when attempting to post to an Azure Function and providing a function key.

Error:

StatusCode: 401, ReasonPhrase: 'Unauthorized'

Code:

let postToAsync (baseAddress:string) (resource:string) (payload:Object) =

async {

    let tokenSource = new CancellationTokenSource(TimeSpan(0,0,30));
    let token = tokenSource.Token;
    
    try
        let tokens      = resource.Split("?code=")
        let functionKey = tokens.[1]

        use client = httpClient baseAddress
        client.DefaultRequestHeaders.Add("x-functions-key", functionKey)
        client.DefaultRequestHeaders.Accept.Add(MediaTypeWithQualityHeaderValue("application/json"))

        let  json     = JsonConvert.SerializeObject(payload)
        let  content  = new StringContent(json, Encoding.UTF8, "application/json")
        let! response = client.PostAsync(resource.Replace($"?code={functionKey}",""), content, token) |> Async.AwaitTask

        Debug.WriteLine $"\n\n{baseAddress}{resource}\nSuccess: {response.IsSuccessStatusCode}\n\n" 

        return response

    with ex -> ...
} |> Async.StartAsTask

Note:

My Azure Function's AuthorizationLevel is set to Function.

I can call the function successfully when I publish it manually from Visual Studio. However, when I deploy the function using Pulumi, I receive an Unauthorized response. I believe this is because Pulumi constrains me to add access policies for each Function App.

Versioning:

<TargetFramework>net6.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>

enter image description here

oauth2/v2.0:

I think the following link provides a clue to why I'm observing the issue. However, I still don't know how to resolve it.

Connectivity

I launched Log Stream and observed that the URL is correct:

enter image description here

Access Control:

Please note that the difference between the Function App that I created without using Pulumi, which lets me post successfully, versus the Function App that was generated using Pulumi, is an Access Policy per Function App with Pulumi.

public static class AccessPolicies
{
    public static void Build(string policyName, string functionName, Dictionary<string, CustomResource> registry)
    {
        var resourceGroup = registry[nameof(ResourceGroup)] as ResourceGroup;
        var keyVault      = registry[nameof(KeyVault)]      as KeyVault;
        var functionApp   = registry[functionName]   as FunctionApp;

        var result = new AccessPolicy(policyName, new AccessPolicyArgs {

            KeyVaultId = keyVault.Id,
            TenantId   = TenantId.Value,
            ObjectId   = functionApp.Identity.Apply(v => v.PrincipalId ?? "11111111-1111-1111-1111-111111111111"),
            KeyPermissions    = new[] { "Get", },
            SecretPermissions = new[] { "Get", }, 
        });

        registry.Add($"{policyName}-{functionName}", result);
    }
}

}

enter image description here

1

There are 1 best solutions below

7
On

I tried to reproduce the same in my environment via Postman and got below results:

I have one function app with http function named srifunction like below:

enter image description here

I generated one bearer token with same scope as you like below:

POST https://login.microsoftonline.com/<tenantID>/oauth2/v2.0/token
grant_type:client_credentials
client_id: <appID>
client_secret: <secret_value>
scope: https://management.azure.com/.default

Response:

enter image description here

When I used the above token to call function, I got 401 Unauthorized error same as you like below:

POST https://<funcappName>.azurewebsites.net/api/<function_name>
Authorization: Bearer <token>

enter image description here

If you pass function key in token value, you will still get 401 Unauthorized error like below:

POST https://<funcappName>.azurewebsites.net/api/<function_name>
Authorization: Bearer <function key>

enter image description here

To call function using function key, you need to include key value in x-functions-key header instead of Bearer token.

When I included the above header, I am able to call the function successfully like below:

POST https://<funcappName>.azurewebsites.net/api/<function_name>
x-functions-key: <function key>

enter image description here