I have a dotnet core 8 Web Application which connects (or tries) to a Storage Account Queue using System Assigned Manged Identity. I've assigned the "Storage Queue Data Contributor" role to the Webapp Identity on the storage account. I'm using the code below on Program.cs but it fails with the error
NoAuthenticationInformation
Server failed to authenticate the request. Please refer to the information in the www-authenticate header. RequestId:94f7fba2-2003-0034-3f51-645603000000 Time:2025-01-11T17:48:56.7911044Z"
Anyone has a clue on what might be wrong?
The code:
builder.Services.AddScoped<MessageQueueService>(provider =>
{
string queueName = builder.Configuration["IAQueue:QueueName"]
?? throw new InvalidOperationException("Queue name for IAQueue is not configured.");
string accountName = builder.Configuration["IAQueue:AccountName"]
?? throw new InvalidOperationException("Account name for IAQueue is not configured.");
if (builder.Environment.IsDevelopment())
{
string accountKey = builder.Configuration["IAQueue:AccountKey"]
?? throw new InvalidOperationException("Account key for IAQueue is not configured.");
string connectionString = $"DefaultEndpointsProtocol=https;AccountName={accountName};AccountKey={accountKey};EndpointSuffix=core.windows.net";
return new MessageQueueService(connectionString, queueName);
}
else
{
var queueUri = new Uri($"https://{accountName}.queue.core.windows.net/{queueName}");
QueueClient queueClient = new QueueClient(queueUri, new DefaultAzureCredential());
return new MessageQueueService(queueUri);
}
});
When I run the app locally connecting to the Azure Queue Storage using Access Key, it works perfectly.
I have created a .NET Core 8 Web Application and successfully sent and received messages to the Azure Storage Queue using System Assigned Managed Identity by assigning the Storage Queue Data Contributor
role to the service principal for local development and to the Azure Web App for deployment.
Program.cs :
using Azure.Identity;
using Azure.Storage.Queues;
using WebApplication6.Services;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddScoped<MessageQueueService>(provider =>
{
string queueName = builder.Configuration["IAQueue:QueueName"]
?? throw new InvalidOperationException("Queue name for IAQueue is not configured.");
string accountName = builder.Configuration["IAQueue:AccountName"]
?? throw new InvalidOperationException("Account name for IAQueue is not configured.");
var queueUri = new Uri($"https://{accountName}.queue.core.windows.net/{queueName}");
var credential = new DefaultAzureCredential();
var queueClient = new QueueClient(queueUri, credential);
return new MessageQueueService(queueClient);
});
builder.Services.AddControllers();
var app = builder.Build();
app.MapControllers();
app.Run();
Controllers/QueueController.cs :
using Microsoft.AspNetCore.Mvc;
using WebApplication6.Models;
using WebApplication6.Services;
namespace WebApplication6.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class QueueController : ControllerBase
{
private readonly MessageQueueService _queueService;
public QueueController(MessageQueueService queueService)
{
_queueService = queueService;
}
[HttpPost("send")]
public async Task<IActionResult> SendMessage([FromBody] QueueMessage message)
{
await _queueService.SendMessageAsync(message.MessageText);
return Ok("Message sent.");
}
[HttpGet("receive")]
public async Task<IActionResult> ReceiveMessages()
{
var messages = await _queueService.ReceiveMessagesAsync();
return Ok(messages);
}
}
}
Services/MessageQueueService.cs :
using Azure.Storage.Queues;
using QueueMessage = Azure.Storage.Queues.Models.QueueMessage;
namespace WebApplication6.Services
{
public class MessageQueueService
{
private readonly QueueClient _queueClient;
public MessageQueueService(string connectionString, string queueName)
{
_queueClient = new QueueClient(connectionString, queueName);
}
public MessageQueueService(QueueClient queueClient)
{
_queueClient = queueClient;
}
public async Task SendMessageAsync(string message)
{
await _queueClient.SendMessageAsync(message);
}
public async Task<IEnumerable<QueueMessage>> ReceiveMessagesAsync(int maxMessages = 10)
{
var response = await _queueClient.ReceiveMessagesAsync(maxMessages);
return response.Value;
}
public async Task DeleteMessageAsync(string messageId, string popReceipt)
{
await _queueClient.DeleteMessageAsync(messageId, popReceipt);
}
}
}
Models/QueueMessage.cs :
namespace WebApplication6.Models
{
public class QueueMessage
{
public string MessageText { get; set; }
}
}
appsettings.json :
{
"IAQueue": {
"QueueName": "<queueName>",
"AccountName": "<StorageName>"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
launchSettings.json :
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:46358",
"sslPort": 44325
}
},
"profiles": {
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7170;http://localhost:5102",
"launchUrl": "api/queue/receive",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "api/queue/receive",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
I have assigned the Storage Queue Data Contributor
role to the Service principle under Access Control (IAM).
I successfully sent a message to the Azure Storage Queue using the POST request.
https://localhost:7170/api/queue/send
I received the message from the Azure Storage Queue using the Get request in the browser.
https://localhost:7170/api/queue/receive
Then, I published the project to the Azure Web App and turned On
the System Assigned Managed Identity.
I have assigned the Storage Queue Data Contributor
role to the Azure Web App under Access Control (IAM).
I successfully sent a message to the Azure Storage Queue using a POST request with the Azure Web App URL.
https:<webappurl>/api/queue/send
I received the message from the Azure Storage Queue using the Get request in the browser with the Azure Web App URL.
https:<webappurl>/api/queue/receive
Azure Storage Queue :