Imre Pühvel
Imre Pühvel

Reputation: 5004

Azure storage account rejects the issuer of a managed service identity

I'm using the Microsoft.Azure.Services.AppAuthentication library (v1.0.3) for .NET to connect from Azure Function app to blob storage using managed service identity. Auth code:

var tokenProvider = new AzureServiceTokenProvider();
string accessToken = await tokenProvider.GetAccessTokenAsync("https://storage.azure.com/");
var tokenCredential = new TokenCredential(accessToken);
var credentials = new StorageCredentials(tokenCredential);
var storageUri = new Uri($"https://{accountName}.blob.core.windows.net");
var client = new CloudBlobClient(storageUri, credentials);

One existing storage account refuses to accept the MSI regardless of given RBAC roles:

Microsoft.WindowsAzure.Storage.StorageException: Server failed to authenticate the request.
Make sure the value of Authorization header is formed correctly including the signature.
   at Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteAsyncInternal[T](RESTCommand`1 cmd, IRetryPolicy policy, OperationContext operationContext, CancellationToken token)
   at Microsoft.WindowsAzure.Storage.Blob.CloudBlobContainer.CreateIfNotExistsAsync(BlobContainerPublicAccessType accessType, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken)

Additional exception details of storageException.RequestInformation.ExtendedErrorInformation.AdditionalDetails complain that AuthenticationErrorDetail: Issuer validation failed. Issuer did not match.

When decoding the failing jwt token, the issuer seems ok:

{
  "aud": "https://storage.azure.com/",
  "iss": "https://sts.windows.net/<my directory guid>/",
  ...
}

When I created new identically set up storage accounts then the same function app MSI and auth code worked and even the issuer in token were exactly the same. So the client function app and it's MSI identity are not the culprit here.

Why does this one storage account fail to authorize and how to get it to accept the MSI?

UPDATE: Cross posted to MS forum to get MS attention in verifying if this is an azure bug.

Upvotes: 6

Views: 6448

Answers (3)

WerkmanW
WerkmanW

Reputation: 102

I just had a nice quality day with this error. It might not be due to the same root cause as OP, but it might help others so I thought I'd post it here.

I was using the DefaultAzureCredential class to retrieve a token for my user, configured as the Azure Service Account in Visual Studio. This would then automatically switch to using the managed identity of the app server in non-localhost environments.

For my specific case, I saw that the tenant id of the issuer in the JWT did not match the tenant id of the user's objectid mentioned in the oid property of the JWT. This meant that a token for my user's tenant was retrieved instead of the tenant in which the resource was located. I solved this by supplying the correct tenant id in the credential options. Here's some steps:

  1. Use this to retrieve and check the token used by the blob client
// This will try to use the VisualStudioCredential to get a token as all other options will fail
var token = await new DefaultAzureCredential().GetTokenAsync(new Azure.Core.TokenRequestContext(new[] { "https://mystorageaccount.blob.core.windows.net/.default" }));

Decoding this token through jwt.ms shows you the iss property with a value like "https://sts.windows.net/{issuerTenantId}/"

  1. How to manually set the right tenant for the credential
var cred = new DefaultAzureCredential(new DefaultAzureCredentialOptions()
{
    VisualStudioTenantId = tenantId
});

var storageclient = new BlobServiceClient(new Uri(url), cred);

BlobContainerClient container = _storageclient.GetBlobContainerClient(containerId);
await container.CreateIfNotExistsAsync();
BlobClient blob = container.GetBlobClient(blobId);
byte[] byteArray = JsonSerializer.SerializeToUtf8Bytes(entity);

using (var stream = new MemoryStream(byteArray))
{
    await blob.UploadAsync(stream, overwrite: true);
}

Hope this helps!

Upvotes: 3

Imre P&#252;hvel
Imre P&#252;hvel

Reputation: 5004

Even after checking with MS, it is unclear what was the cause, but moving the affected subscriptions to another Azure AD directory seems to have fixed the issue.

Upvotes: 0

Joey Cai
Joey Cai

Reputation: 20127

I test with your Auth code and both existing and new created Storage account accept MSI. So I approve with what juunas said, it may be an bug on Azure Storage.

You could go to here to give your feedback to let developers fix it.

Upvotes: 0

Related Questions