Azure Service Bus - Unauthorized access. 'Send' claim(s) are required to perform this operation
A

4

10

I am trying to access Azure Service Bus Queue from my Windows Service application. I am following this sample.

I want to protect this Azure Service Bus using Azure Service Principal Below are the steps I have implemented

  1. Register an application named pc-shutdown-producer in Azure Ad representing my Windows Service
  2. I have created my Azure service bus namespace named shutdowncomputer
  3. Inside Access control (IAM), I have added Role Assignment with below values
    • Role - Azure Service Bus Data Owner
    • Assign access to - pc-shutdown-producer

As per my knowledge above configuration will let pc-shutdown-producer application to manage all the resources in the servicebus namespace. 4. Apart from this, I have also provided pc-shutdown-producer delegated API Permissions to access the service bus namespace.

enter image description here

Below is my C# code.

        public async Task Init()
        {
            string authority = $"https://login.windows.net/{TenantId}";

            ITokenProvider tokenProvider = TokenProvider.CreateAzureActiveDirectoryTokenProvider(AuthenticationCallback, authority);
            var endpoint = new Uri($"sb://shutdowncomputer.servicebus.windows.net/");
            var entityPath = "shutdownrequest";

            var qc = new QueueClient(endpoint.ToString(), entityPath, tokenProvider);

            Message m = new Message();
            m.Body = Encoding.ASCII.GetBytes("{id: 1, name: 'hemant'}");
            m.ContentType = "application/json";
            try
            {
                await qc.SendAsync(m);
            }
            catch (Exception ex)
            {
                //I am getting exception here. 
                //Unauthorized access. 'Send' claim(s) are required to perform this operation.
                throw ex;
            }
        }

        private async Task<string> AuthenticationCallback(string audience, string authority, object state)
        {
            string accessToken = string.Empty;
            IConfidentialClientApplication app = ConfidentialClientApplicationBuilder.Create(AppId)
                .WithAuthority(authority)
                .WithClientSecret(Password)
                .Build();

            var serviceBusAudience = new Uri("https://servicebus.azure.net");

            List<string> claims = new List<string>();
            claims.Add($"{serviceBusAudience}/.default");
            try
            {
                var result = await app.AcquireTokenForClient(claims.ToArray()).ExecuteAsync();
                accessToken = result.AccessToken;
            }
            catch (Exception ex)
            {
                //No issue here.
                Console.WriteLine(ex.Message);
            }
            //Successfully able to retrieve a token.
            return accessToken ;
        }

Upon executing Init() , I am getting below exception message.

Unauthorized access. 'Send' claim(s) are required to perform this operation. Resource: 'sb://shutdowncomputer.servicebus.windows.net/shutdownrequest'. TrackingId:52c0eedcf19d4513a8ec105943859764_G12, SystemTracker:gateway7, Timestamp:2020-05-11T06:59:01

UPDATE 1

As per @Carl Zhao sugession, I have provided admin consent to pc-shutdown-producer but still having same issue.

enter image description here

Thanks

Anisometric answered 11/5, 2020 at 7:4 Comment(0)
C
6

Insufficient permissions, should add administrator consent: enter image description here

Cannibalism answered 11/5, 2020 at 7:45 Comment(2)
Thanks for your response. I have provided admin consent but still the same issue. I am aware of the fact that it can take up to 5 mins to propagate. I tried this after 20min and still no luck.Anisometric
it was my bad. Instead of adding 'Azure Service Bus Data Owner' , I added 'Owner' role. After correcting this in my Azure Service bus namespace I was able to send a message. ThanksAnisometric
C
3

Make sure to assign the application the Azure Service Bus Data Owner role rather than Owner (per OP's comment).

A screenshot of the "Add role assignment" page in Azure Portal with two similarly named roles circled: "Owner" and "Azure Service Bus Data Owner."

Carvajal answered 17/1, 2023 at 21:22 Comment(0)
C
0

In my case, the error was misleading.

The reason was missing password in configuration files (this happened in Jenkins test agent and it was retrieving the password from some other file where it was not set).

If I had a wrong password, the error is just "Attempted to perform an unauthorized operation.". But without any password (eg. empty property value), the error was "Unauthorized access. 'Send' claim(s) are required to perform this operation.".

Commodore answered 18/8, 2021 at 14:4 Comment(0)
B
0

You can also resolve this issue by using connection string without the need of configure roles. I tried to follow this tutorial when I faced this error.

I copy the most important parts of the link above:

  1. On the Service Bus Namespace page, select Shared access policies on the left menu.

  2. On the Shared access policies page, select RootManageSharedAccessKey.

  3. In the Policy: RootManageSharedAccessKey window, select the copy button next to Primary Connection String, to copy the connection string to your clipboard for later use. Paste this value into Notepad or some other temporary location.

Example c# code for connecting:


 using Azure.Messaging.ServiceBus;

// the client that owns the connection and can be used to create senders and receivers
ServiceBusClient client;

// the sender used to publish messages to the queue
ServiceBusSender sender;

// number of messages to be sent to the queue
const int numOfMessages = 3;

// The Service Bus client types are safe to cache and use as a singleton for the lifetime
// of the application, which is best practice when messages are being published or read
// regularly.
//
// set the transport type to AmqpWebSockets so that the ServiceBusClient uses the port 443. 
// If you use the default AmqpTcp, you will need to make sure that the ports 5671 and 5672 are open

// TODO: Replace the <NAMESPACE-CONNECTION-STRING> and <QUEUE-NAME> placeholders
var clientOptions = new ServiceBusClientOptions()
{ 
    TransportType = ServiceBusTransportType.AmqpWebSockets
};
client = new ServiceBusClient("<NAMESPACE-CONNECTION-STRING>", clientOptions);
sender = client.CreateSender("<QUEUE-NAME>");

// create a batch 
using ServiceBusMessageBatch messageBatch = await sender.CreateMessageBatchAsync();

for (int i = 1; i <= numOfMessages; i++)
{
    // try adding a message to the batch
    if (!messageBatch.TryAddMessage(new ServiceBusMessage($"Message {i}")))
    {
        // if it is too large for the batch
        throw new Exception($"The message {i} is too large to fit in the batch.");
    }
}

try
{
    // Use the producer client to send the batch of messages to the Service Bus queue
    await sender.SendMessagesAsync(messageBatch);
    Console.WriteLine($"A batch of {numOfMessages} messages has been published to the queue.");
}
finally
{
    // Calling DisposeAsync on client types is required to ensure that network
    // resources and other unmanaged objects are properly cleaned up.
    await sender.DisposeAsync();
    await client.DisposeAsync();
}

Console.WriteLine("Press any key to end the application");
Console.ReadKey();

Backbreaker answered 8/2, 2023 at 9:35 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.