Search code examples
azureazure-functionsazure-web-app-serviceazure-blob-storageazure-sdk-.net

.NET SDK Azure Blob via API Service - Status: 403... Make sure the value of Authorization header is formed correctly including the signature.)


I have .NET 8 WebApi, that is using the Azure.Storage.Blobs SDK (v12.19.1) to access my Azure Storage account (using Access Keys).

There are no issues when running on localhost or on an Azure Virtual Machine, but when I deploy the same solution as a service (API Management service), the operation fails with "403 (Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature"

SDK Registration:

var azureConnectionString = builder.Configuration.GetConnectionString("StorageConnectionString");
services.AddAzureClients(clientBuilder =>
{
    clientBuilder.AddBlobServiceClient(azureConnectionString);
});

Exception caused by:

        var containerClient = _client.GetBlobContainerClient("uploads");

        if (!await containerClient.ExistsAsync())
            await containerClient.CreateAsync();

"StorageConnectionString": "DefaultEndpointsProtocol=https;AccountName={ACCOUNT_NAME};AccountKey={VALUE_REMOVED};EndpointSuffix=core.windows.net"

I have double checked and rotated API Keys! (if there was an issue, they shouldn't work elsewhere either)

Also tried the proposed solutions in:

A noteworthy difference in environments is that both my localhost and azure virtual machine (where things work) have their time zone set to MSDT (-7), where I've noticed the service is using UTC.

Based on answers by related posts, time zone differences can cause this error but I'm not sure how to resolve for my api service, which always runs in UTC.

I've been trying to resolve this for more than a few days now and I feel like I'm going in circles, any help would be greatly appreciated!

Stacktrace:

"Status":403,
"ErrorCode":"AuthenticationFailed",
"ClassName":"Azure.RequestFailedException",
"Message":"Service request failed.\r\nStatus: 403 (Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.)\r\n

ErrorCode: AuthenticationFailed\r\n\r\n
Headers:\r\n
    Transfer-Encoding: chunked\r\n
    Server: Microsoft-HTTPAPI/2.0\r\n
    x-ms-request-id: f7bcf6cf-d01e-002d-3537-3922f1000000\r\n
    x-ms-error-code: AuthenticationFailed\r\n
    Date: Thu, 28 Dec 2023 16:53:13 GMT\r\n",

"Data":null,
"InnerException":null,
"HelpURL":null,
"StackTraceString":"   
    at Azure.Core.HttpPipelineExtensions.ProcessMessageAsync(HttpPipeline pipeline, HttpMessage message, RequestContext requestContext, CancellationToken cancellationToken)\r\n   
    at Azure.Storage.Blobs.BlobRestClient.GetPropertiesAsync(String snapshot, String versionId, Nullable`1 timeout, String leaseId, String encryptionKey, String encryptionKeySha256, String encryptionAlgorithm, String ifTags, RequestConditions requestConditions, RequestContext context)\r\n   
    at Azure.Storage.Blobs.Specialized.BlobBaseClient.GetPropertiesInternal(BlobRequestConditions conditions, Boolean async, RequestContext context, String operationName)\r\n   
    at Azure.Storage.Blobs.Specialized.BlobBaseClient.ExistsInternal(Boolean async, CancellationToken cancellationToken)\r\n   
    at Azure.Storage.Blobs.Specialized.BlobBaseClient.ExistsAsync(CancellationToken cancellationToken)\r\n   
    at MyDaycareApi.Services.FileManagerService.LoadTemplateAsync(String path) in D:\\Repository\\Repository\\MyDaycare-Api\\MyDaycareApi\\Services\\FileManagerService.cs:line 138\r\n   
    at MyDaycareApi.Services.ViewRenderService.BuildAndReplaceAsync(String templateName, Dictionary`2 data) in D:\\Repository\\Repository\\MyDaycare-Api\\MyDaycareApi\\Services\\ViewRenderService.cs:line 19\r\n   
    at MyDaycareApi.Builders.EmailBuilder.BuildNotification(Int32 daycareId, String daycareName, IEnumerable`1 guardians, String title, String message, String btnText, String btnUrl) in D:\\Repository\\Repository\\MyDaycare-Api\\MyDaycareApi\\Builders\\EmailBuilder.cs:line 132\r\n   
    at MyDaycareApi.Services.AppNotificationService.SendEmailNotificationAsync(Guardian systemUser, Guardian accountHolder, AppNotificationCreateDto dto) in D:\\Repository\\Repository\\MyDaycare-Api\\MyDaycareApi\\Services\\AppNotificationService.cs:line 61\r\n   
    at MyDaycareApi.Services.AppNotificationService.SendNotificationAsync(AppNotificationCreateDto dto, List`1 accountHoldersToNotify) in D:\\Repository\\Repository\\MyDaycare-Api\\MyDaycareApi\\Services\\AppNotificationService.cs:line 130\r\n   
    at MyDaycareApi.Services.AppNotificationService.SendAsync(String email, AppNotificationCreateDto dto) in D:\\Repository\\Repository\\MyDaycare-Api\\MyDaycareApi\\Services\\AppNotificationService.cs:line 158\r\n   
    at MyDaycareApi.Services.MessageService.SendMessageAsync(IIdentity from, IIdentity to, String msg, UploadImageDto image, Boolean doNotSendEmail) in D:\\Repository\\Repository\\MyDaycare-Api\\MyDaycareApi\\Services\\MessageService.cs:line 320\r\n   
    at MyDaycareApi.Services.MessageService.SendMessage(ILoggedInUser loggedInUser, NewMessageDto model) in D:\\Repository\\Repository\\MyDaycare-Api\\MyDaycareApi\\Services\\MessageService.cs:line 354\r\n   
    at MyDaycareApi.Controllers.MessagesController.CreateV2Async(NewMessageDto model) in D:\\Repository\\Repository\\MyDaycare-Api\\MyDaycareApi\\Controllers\\MessagesController.cs:line 107",
"RemoteStackTraceString":null,
"RemoteStackIndex":0,
"ExceptionMethod":null,
"HResult":-2146233088,
"Source":"Azure.Storage.Blobs",
"WatsonBuckets":null}

Solution

    • Check if the firewall is enabled in Azure Portal -> Storage Account -> Networking -> Check Allow Access From (All Networks / Selected Networks),
      If you have "Selected Networks" - It means the storage account is firewall enabled.
    • Select Enabled from all networks:

    enter image description here

    • Regenerate Access Keysand refresh the storage account.
    • Check if you have switched to Access key as Authentication method in your Storage Account.
    • To set the time zone of your API service to MSDT. You can do this by setting the WEBSITE_TIME_ZONE app setting to Pacific Standard Time in the Azure portal.

    I have created a .NET 8.0 Web API to access storage account and upload a file to it.

    • Thanks @Rithwik for the code.

    • Deployed to Azure App Service(Windows):

    enter image description here

    • Able to run the deployed application and uploading the file to storage account.

    enter image description here

    Portal:

    • Could see the uploaded file to my Container in Storage Account:

    enter image description here

    References:

    Azure Blob Storage fails to authenticate: "Make sure the value of Authorization header is formed correctly including the signature"