Morgan Soren
Morgan Soren

Reputation: 593

How to connect from an azure function to a hosted site in a blob storage?

I have a blob storage container that stores HTML files. With the public access level, I can see the HTML, but the idea is to set it to private. I want to have users authenticate and access the HTML file.

For that I created an Azure Function with the most relevant part of the code being:

    #r "Newtonsoft.Json"

using System;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;

public static async Task<IActionResult> Run(HttpRequest req, ILogger log, string version, string route)
{
    var blobUri = "https://mybloburi.blob.core.windows.net/" + route;

    var expiresOn = req.Headers.FirstOrDefault(p => p.Key.Equals("x-ms-token-aad-expires-on", 
    StringComparison.OrdinalIgnoreCase)).Value.FirstOrDefault();

    log.LogInformation($"expires On : {expiresOn}");
    log.LogInformation($"blob uri : {blobUri}");
    
    var isTokenExpired = (DateTime.Parse(expiresOn, styles: DateTimeStyles.AdjustToUniversal) - DateTime.UtcNow).TotalMinutes < 5;

    var bearerToken = isTokenExpired? await RefreshToken(req, log) : req.Headers.
    FirstOrDefault(p => p.Key.Equals("x-ms-token-aad-access-token", StringComparison.OrdinalIgnoreCase)).
    Value.FirstOrDefault();

    log.LogInformation($"bearer token: {bearerToken}");

    using (var client = new HttpClient())
    {
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", bearerToken);
        client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate");
        client.DefaultRequestHeaders.Add("Accept", "*/*");
        client.DefaultRequestHeaders.Add("x-ms-version", "2017-11-09");
        
        var response = await client.GetAsync(blobUri);

        log.LogInformation($"response: {response}");

        var contentType = response.Content.Headers.FirstOrDefault(p => p.Key.Equals("Content-Type", StringComparison.OrdinalIgnoreCase));
        var byteArray = await response.Content.ReadAsByteArrayAsync();
        
        const string defaultContentType = "application/octet-stream";
        
        return new FileContentResult(byteArray, contentType.Value.Any() ? contentType.Value.First() : defaultContentType);
    }
}

In the Integration section of the Azure Function, I added this config:

enter image description here

Then I created an App Registration. Under the Authorization option of the Azure Function, I enabled the App Service Authentication. In there I added a new Identity Provider as Microsoft and as a provider I added the created App Registration. I created a Role Group with access to the Blob Storage Container and set its App Id to the "Allowed token audiences".

When I test, I am able to authenticate to the AAD. However, the HTTP Client get function fails with

<Code>AuthenticationFailed</Code>
<Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature. 

I don't know what other configuration to do and I cant seem to find anything in the documentation that could help

Upvotes: 0

Views: 211

Answers (1)

SaiSakethGuduru
SaiSakethGuduru

Reputation: 2439

As suggested by @Thomas. Yes, we do have a static website where we have a streamlined authentication. For which you will be having a by default access to a series of pre-configured providers, or you can even register a custom provider.

enter image description here

To configure static web apps for using it as an API function for role assignment you need to add rolesSource property to auth and that is the path of API function.

{
  "auth": {
    "rolesSource": "/api/GetRoles",
    "identityProviders": {
      // ...
    }
  }
}

For more information you can check this document.

Upvotes: 1

Related Questions