Search code examples
c#azureazure-storageazure-managed-identity

Azure Managed Identity local debug authentication failure


I've got a very basic example that I just can't seem to get working. The user I'm using is a subscription owner so should have access to everything. If I run the following when it tries to actually get the blob text that is when it falls over with:

StorageException: Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.

using Microsoft.Azure.Services.AppAuthentication;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage.Blob;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace testmsistorageaccess
{
    class Program
    {
        public static void Main()
        {
            AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider();
            var tokenAndFrequency = TokenRenewerAsync(azureServiceTokenProvider,
                                                        CancellationToken.None).GetAwaiter().GetResult();

            TokenCredential tokenCredential = new TokenCredential(tokenAndFrequency.Token,
                                                                    TokenRenewerAsync,
                                                                    azureServiceTokenProvider,
                                                                    tokenAndFrequency.Frequency.Value);

            StorageCredentials storageCredentials = new StorageCredentials(tokenCredential);

            var storageUri = new Uri("https://mystorageaccount.blob.core.windows.net");
            var client = new CloudBlobClient(storageUri, storageCredentials);
            var container = client.GetContainerReference("bob");
            string content = container.GetBlockBlobReference("bob.xml").DownloadTextAsync().Result;
            Console.WriteLine($"Got {content}");
        }

        private static async Task<NewTokenAndFrequency> TokenRenewerAsync(Object state, CancellationToken cancellationToken)
        {
            const string StorageResource = "https://storage.azure.com/";
            var authResult = await ((AzureServiceTokenProvider)state).GetAuthenticationResultAsync(StorageResource);
            var next = (authResult.ExpiresOn - DateTimeOffset.UtcNow) - TimeSpan.FromMinutes(5);
            if (next.Ticks < 0)
            {
                next = default(TimeSpan);
            }
            return new NewTokenAndFrequency(authResult.AccessToken, next);
        }
    }
}

Not sure what I'm doing wrong here, I've checked and the user it's trying to use and that appears correct and has the right AD Tenant ID:

enter image description here

I saw mention of checking time on my local machine with UTCNow and confirmed it's correct with GMT time other than that I've found nothing else about how to debug this.

Any help appreciated


Solution

  • Subscription owner != data access. You need to add storage blob contributor or storage blob reader role to the user.