Reputation: 593
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:
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
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.
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