question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[BUG] Accessing blob container fails with auth error, when using Azure Front Door CDN

See original GitHub issue

Library name and version

Azure.Storage.Blobs 12.15.0

Describe the bug

When creating a BlobServiceClient based on an Azure Front Door endpoint URL, in ~50% of the cases, it produces an Authentication exception.

Expected behavior

In my solution, I want to create a SAS Uri for a blob item that is accessed via an Azure Front Door (AFD) endpoint. The blob container cannot be publicly accessible and therefore the SAS is needed. After creating a SAS for a blob item, you can replace the hostname of the blob URL E.g ‘https://<NAME>.blob.core.windows.net’ (from the complete SAS) with the hostname of the AFD endpoint. E.g: ‘https:// <NAME>.z01.azurefd.net’. With this new URL, you can access the blob item (even download it in the browser) through the AFD endpoint and use CDN.

In code, it seemed a clumsy solution first to create a SAS and then replace the hostname of the URL in the code. After some searching, I found a solution in creating a ‘BlobServiceClient’ with a different service URL, which points to the AFD endpoint. At first glance, this seems great. With this, I only have to change the initialization of the blob object(s) in my startup logic and keep my logic in the application the same. Unfortunately, this is not always working. In half of the cases, it works and in the other half, an exception is thrown in the code.

Why is this exception thrown and should it work as I intend? Or, are there better alternatives for what I want to achieve?

Actual behavior

The exception that is produced is:

Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
RequestId:abba20e0-f01e-004d-1969-52f96d000000
Time:2023-03-09T09:26:42.6689043Z
Status: 403 (Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.)
ErrorCode: AuthenticationFailed

Additional Information:
AuthenticationErrorDetail: The MAC signature found in the HTTP request 'C7MEyGoAuJVMoVG7whS58c46CW/2JUlPEiQoylCt4ok=' is not the same as any computed signature. Server used following string to sign: 'GET

bytes=0-8388607
x-ms-client-request-id:9798c48e-0480-4e8e-990e-2a5f615ec103
x-ms-date:Thu, 09 Mar 2023 09:26:42 GMT
x-ms-return-client-request-id:true
x-ms-version:2021-12-02
/<NAME>/machineimages
comp:list
restype:container'.

Content:
<?xml version="1.0" encoding="utf-8"?><Error><Code>AuthenticationFailed</Code><Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
RequestId:abba20e0-f01e-004d-1969-52f96d000000
Time:2023-03-09T09:26:42.6689043Z</Message><AuthenticationErrorDetail>The MAC signature found in the HTTP request 'C7MEyGoAuJVMoVG7whS58c46CW/2JUlPEiQoylCt4ok=' is not the same as any computed signature. Server used following string to sign: 'GET

bytes=0-8388607
x-ms-client-request-id:9798c48e-0480-4e8e-990e-2a5f615ec103
x-ms-date:Thu, 09 Mar 2023 09:26:42 GMT
x-ms-return-client-request-id:true
x-ms-version:2021-12-02
/<NAME>/machineimages
comp:list
restype:container'.</AuthenticationErrorDetail></Error>

Headers:
Date: Thu, 09 Mar 2023 09:26:42 GMT
Connection: keep-alive
x-ms-request-id: abba20e0-f01e-004d-1969-52f96d000000
x-ms-error-code: AuthenticationFailed
Access-Control-Expose-Headers: REDACTED
Access-Control-Allow-Origin: *
x-azure-ref: REDACTED
X-Cache: REDACTED
Content-Type: application/xml
Content-Length: 800

Reproduction Steps

The following C# code reproduces (sometimes) the exception:

using System;
using System.Threading.Tasks;
using Azure.Storage;
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;

namespace ConsoleApp23
{
 internal class Program
 {
 static async Task Main(string[] args)
 {
 try
 {
 //Note1: Add a random image to the 'machineimages' container before running the code
			
 var accountName = "mystoragetst01";
 var accountKey = "*****************************************************************";

 //Note3: This is the original blob url that works without problems
 //string serviceUrl = "https://mystoragetst01.blob.core.windows.net";

 //Note4: This is the Azure Front Door url (Update the after running the BICEP script!) which throw regularly (~50%) an exception when using this.
 string serviceUrl = "https://mystoragetst01-?????????.z01.azurefd.net"; //TODO: Update url based on AFD endpoint after running the BICEP script!
 

 string containerName = "machineimages";

 StorageSharedKeyCredential credential = new StorageSharedKeyCredential(accountName, accountKey);
 BlobServiceClient blobServiceClient = new BlobServiceClient(new Uri(serviceUrl), credential);
 BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient(containerName);

 await foreach (BlobItem blobItem in containerClient.GetBlobsAsync()) //--> This line will produce the exception: 'Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.'
 {
 Console.WriteLine(blobItem.Name);
 }
 }
 catch (Exception exception)
 {
 Console.WriteLine(exception);
 }
 }
 }
}

Project file:

<Project Sdk="Microsoft.NET.Sdk">

 <PropertyGroup>
 <OutputType>Exe</OutputType>
 <TargetFramework>net7.0</TargetFramework>
 </PropertyGroup>

 <ItemGroup>
 <PackageReference Include="Azure.Storage.Blobs" Version="12.15.0" />
 </ItemGroup>

</Project>

The following BICEP script creates the Storage Account and the Azure Front Door (I composed it from multiple files so it isn’t production code):

param location string = resourceGroup().location

var storageAccountName = 'mystoragetst01'

resource storageAccountResource 'Microsoft.Storage/storageAccounts@2022-09-01' = {
 name: storageAccountName
 location: location
 kind: 'StorageV2'
 sku: {
 name: 'Standard_LRS'
 }
 properties: {
 minimumTlsVersion: 'TLS1_2'
 allowBlobPublicAccess: false
 allowSharedKeyAccess: true
 supportsHttpsTrafficOnly: true
 accessTier: 'Hot'
 }
}

//CORS rules
var corsProperty = {
 corsRules:[
 {
 allowedOrigins: [ 
 '*' 
 ]
 allowedHeaders: [
 '*'
 ]
 allowedMethods: [
 'GET'
 ]
 maxAgeInSeconds: 0
 exposedHeaders: [
 '*'
 ]
 }
 ]
}

//Set Data protection/Enable soft delete for blobs
resource blobServicesResource 'Microsoft.Storage/storageAccounts/blobServices@2022-09-01' = {
 parent: storageAccountResource
 name: 'default'
 properties: {
 containerDeleteRetentionPolicy: {
 enabled: true
 days: 14
 }
 deleteRetentionPolicy: {
 enabled: true
 days: 14
 }
 cors: corsProperty
 }
}

//Create container: 
resource containerResource 'Microsoft.Storage/storageAccounts/blobServices/containers@2022-09-01' = {
 name: '${storageAccountName}/default/machineimages'
 dependsOn: [
 
 ]
}

//Set Lifecycle management
resource storageAccountName_default 'Microsoft.Storage/storageAccounts/managementPolicies@2022-09-01' = {
 name: '${storageAccountName}/default'
 dependsOn: [
 storageAccountResource
 ]
 properties: {
 policy: {
 rules: [
 {
 enabled: true
 name: 'DeleteBlobInMessagesAfter186Days'
 type: 'Lifecycle'
 definition: {
 actions: {
 baseBlob: {
 delete: {
 daysAfterModificationGreaterThan: 186
 }
 }
 }
 filters: {
 blobTypes: [
 'blockBlob'
 ]
 prefixMatch: [
 'messages'
 ]
 }
 }
 }
 ]
 }
 }
}

//Create Azure Front Door
var frontDoorName = 'MyAFDTest01'

resource azureFrontDoorResource 'Microsoft.Cdn/profiles@2022-11-01-preview' = {
 name: frontDoorName
 location: 'Global'
 sku: {
 name: 'Premium_AzureFrontDoor'
 }
 properties: {
 originResponseTimeoutSeconds: 60
 extendedProperties: {
 }
 }
}


//Retrieves host name by substring 'https://mystoragetst01.blob.core.windows.net/' into 'mystoragetst01.blob.core.windows.net'
var storageAccountHostName = substring(storageAccountResource.properties.primaryEndpoints.blob, 8, length(storageAccountResource.properties.primaryEndpoints.blob) - 8 - 1)

//Add Endpoint to Azure Front Door
var endpointName = storageAccountName
var originGroupName = 'MyStorageTstOriginGroup'
var originName = 'MyStorageTstOrigin'
var originHostName = storageAccountHostName
var endpointRouteName = 'MyStorageTstRoute'
var webApplicationFirewallPolicyName = 'MyWafTest01'
var webApplicationFirewallPolicyMode = 'Detection'
var securityPolicyName = 'MyStorageTstSecurityPolicy'

//AFD Endpoint
resource endpointResource 'Microsoft.Cdn/profiles/afdendpoints@2022-11-01-preview' = {
 parent: azureFrontDoorResource
 name: toLower(endpointName)
 location: 'Global'
 properties: {
 enabledState: 'Enabled'
 }
}

//ADF Origin Group
resource originGroupResource 'Microsoft.Cdn/profiles/origingroups@2022-11-01-preview' = {
 parent: azureFrontDoorResource
 name: originGroupName
 properties: {
 loadBalancingSettings: {
 sampleSize: 4
 successfulSamplesRequired: 3
 additionalLatencyInMilliseconds: 50
 }
 healthProbeSettings: {
 probePath: '/'
 probeRequestType: 'HEAD'
 probeProtocol: 'Http'
 probeIntervalInSeconds: 100
 }
 sessionAffinityState: 'Disabled'
 }
}

//ADF Origin
resource originResource 'Microsoft.Cdn/profiles/origingroups/origins@2022-11-01-preview' = {
 parent: originGroupResource
 name: originName
 properties: {
 hostName: toLower(originHostName)
 httpPort: 80
 httpsPort: 443
 originHostHeader: toLower(originHostName)
 priority: 1
 weight: 1000
 enabledState: 'Enabled'
 enforceCertificateNameCheck: true
 }
}

//ADF Endpoint Route
resource routeResource 'Microsoft.Cdn/profiles/afdendpoints/routes@2022-11-01-preview' = {
 parent: endpointResource
 name: endpointRouteName
 properties: {
 cacheConfiguration: {
 compressionSettings: {
 isCompressionEnabled: true
 contentTypesToCompress: [
 'application/eot'
 'application/font'
 'application/font-sfnt'
 'application/javascript'
 'application/json'
 'application/opentype'
 'application/otf'
 'application/pkcs7-mime'
 'application/truetype'
 'application/ttf'
 'application/vnd.ms-fontobject'
 'application/xhtml+xml'
 'application/xml'
 'application/xml+rss'
 'application/x-font-opentype'
 'application/x-font-truetype'
 'application/x-font-ttf'
 'application/x-httpd-cgi'
 'application/x-javascript'
 'application/x-mpegurl'
 'application/x-opentype'
 'application/x-otf'
 'application/x-perl'
 'application/x-ttf'
 'font/eot'
 'font/ttf'
 'font/otf'
 'font/opentype'
 'image/svg+xml'
 'text/css'
 'text/csv'
 'text/html'
 'text/javascript'
 'text/js'
 'text/plain'
 'text/richtext'
 'text/tab-separated-values'
 'text/xml'
 'text/x-script'
 'text/x-component'
 'text/x-java-source'
 ]
 }
 queryStringCachingBehavior: 'IgnoreQueryString'
 }
 customDomains: []
 originGroup: {
 id: originGroupResource.id
 }
 ruleSets: []
 supportedProtocols: [
 'Https'
 ]
 patternsToMatch: [
 '/*'
 ]
 forwardingProtocol: 'HttpsOnly'
 linkToDefaultDomain: 'Enabled'
 httpsRedirect: 'Disabled'
 enabledState: 'Enabled'
 }
}

//Create Web Application Firewall
resource frontdoorWebApplicationFirewallPolicyResource 'Microsoft.Network/frontdoorwebapplicationfirewallpolicies@2022-05-01' = {
 name: webApplicationFirewallPolicyName
 location: 'Global'
 sku: {
 name: 'Premium_AzureFrontDoor'
 }
 properties: {
 policySettings: {
 enabledState: 'Enabled'
 mode: webApplicationFirewallPolicyMode
 customBlockResponseStatusCode: 403
 requestBodyCheck: 'Enabled'
 }
 customRules: {
 rules: []
 }
 managedRules: {
 managedRuleSets: [
 {
 ruleSetType: 'Microsoft_DefaultRuleSet'
 ruleSetVersion: '2.0'
 ruleSetAction: 'Block'
 ruleGroupOverrides: []
 exclusions: []
 }
 {
 ruleSetType: 'Microsoft_BotManagerRuleSet'
 ruleSetVersion: '1.0'
 ruleGroupOverrides: []
 exclusions: []
 }
 ]
 }
 }
}

//Web Application Firewall connection to the Endpoint
resource securityPolicyResource 'Microsoft.Cdn/profiles/securitypolicies@2022-11-01-preview' = {
 parent: azureFrontDoorResource
 name: securityPolicyName
 properties: {
 parameters: {
 wafPolicy: {
 id: frontdoorWebApplicationFirewallPolicyResource.id
 }
 associations: [
 {
 domains: [
 {
 id: endpointResource.id
 }
 ]
 patternsToMatch: [
 '/*'
 ]
 }
 ]
 type: 'WebApplicationFirewall'
 }
 }
}

Environment

NET runtime version: .Net 6.0 & .Net 7.0 IDE and version: Microsoft Visual Studio Enterprise 2022 (64-bit) - Current Version 17.5.1 OS: Windows 11 Pro Version 22H2 (OS Build 22621.1344)

Issue Analytics

  • State:closed
  • Created 6 months ago
  • Comments:17 (8 by maintainers)

github_iconTop GitHub Comments

1reaction
navba-MSFTcommented, Mar 13, 2023

@StannieV Apologies for the late reply. Thanks for reaching out to us and reporting this issue. We are looking into this issue and we will provide an update.

0reactions
github-actions[bot]commented, Apr 3, 2023

Hi @StannieV, we’re sending this friendly reminder because we haven’t heard back from you in 7 days. We need more information about this issue to help address it. Please be sure to give us your input. If we don’t hear back from you within 14 days of this comment the issue will be automatically closed. Thank you!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Azure Blob Storage fails to authenticate: "Make sure the ...
Hi I am trying to upload a binary file (a blob for an excel file, actually) to my storage account but the client...
Read more >
Authentication errors using Azure blob storage and ...
I tried in my environment and got below results: Initially, I got a same when I tried to access blob storage with CDN...
Read more >
Azure front door 500 error. The Front Door manager in Azure ...
When using Azure Front Door SSL offload, it should take the SSL ... find a similar bug ( #115 ), and conceptually I...
Read more >
Azure status history | Microsoft Azure
This page contains root cause analyses (RCAs) of previous service issues, each retained for 5 years. From November 20, 2019, this included RCAs...
Read more >
General Feedback · Community - Azure Feedback
Add Microsoft Authenticator for the Windows 10 OS so that we can utilize it for the medical field on our PC. Completed. Completed....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found