question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[BUG] Event Hubs service rejecting SAS token for unknown reason

See original GitHub issue

Library name and version

Azure.Messaging.EventHub 5.6.2

Describe the bug

I am using the Azure.Messaging.EventHubs.Producer.EventHubProducerClient from my .NET 6 Web project to publish events to an Azure Event Hub. This was working fine when I used a connection string to authenticate the EventHubProducerClient but I want to switch to using SharedAccessSignature Tokens instead.

Unfortunately, when I try to use SAS tokens, I get this error:

System.UnauthorizedAccessException: Put token failed. status-code: 401, status-description: Malformed authorization token. 

Expected behavior

Correctly authenticate when using SAS tokens.

Actual behavior

An error is returned:

System.UnauthorizedAccessException: Put token failed. status-code: 401, status-description: Malformed authorization token. 

Reproduction Steps

I am registering my EventHubProdocuerClient as a Scoped lifetime service in my service provider. I am reading the SAS token from a file (which will actually be mounted to my pod as a Kubernetes secret but that detail isn’t important here):

    services.AddScoped<Azure.Messaging.EventHubs.Producer.EventHubProducerClient>((sp) =>
    {
        string sasToken = fileReader.ReadAllText(sharedAccessSignatureFilePath).Result;
        
        return new Azure.Messaging.EventHubs.Producer.EventHubProducerClient(fullyQualifiedNamespace,
            eventHubName,
            new AzureSasCredential(sasToken)
    });

fullyQualifiedNamespace is like this:

my-eventhub-001.servicebus.windows.net

First I created a Shared Access Policy in my Event Hub in the Azure Portal called “EventProducer” and I gave it “Send” rights. If I click on that, it shows me a connection string and keys. I pulled some of the info like the resourceUri, keyName, and key from there.

I generated my SAS token using the C# code example as shown in Authenticate access to Event Hubs resources using shared access signatures (SAS) -> Generate a Shared Access Signature token -> C#

My SAS token looks like this:

SharedAccessSignature sr=sb%3a%2f%2fmy-eventhub-001.servicebus.windows.net%2fmyhub1&sig=9q3N{...omitted...}KJy78%3d&se=1640997904&skn=EventProducer

Now I try to create a message batch with my `EventHubProducerClient:

    using EventDataBatch eventBatch = await _producerClient.CreateBatchAsync();

It fails with the following exception:

{System.UnauthorizedAccessException: Put token failed. status-code: 401, status-description: Malformed authorization token. TrackingId:775b1ad2-1250-4523-b840-4c7781cb6522_G7, SystemTracker:my-eventhub-001.servicebus.windows.net:myhub1, Timestamp:2021-12-31T23:12:12.
 ---> Microsoft.Azure.Amqp.AmqpException: Put token failed. status-code: 401, status-description: Malformed authorization token. TrackingId:775b1ad2-1250-4523-b840-4c7781cb6522_G7, SystemTracker:my-eventhub-001.servicebus.windows.net:myhub1, Timestamp:2021-12-31T23:12:12.
   at Microsoft.Azure.Amqp.ExceptionDispatcher.Throw(Exception exception)
   at Microsoft.Azure.Amqp.AsyncResult.End[TAsyncResult](IAsyncResult result)
   at Microsoft.Azure.Amqp.AsyncResult`1.End(IAsyncResult asyncResult)
   at Microsoft.Azure.Amqp.AmqpCbsLink.EndSendToken(IAsyncResult result)
   at Microsoft.Azure.Amqp.AmqpCbsLink.<>c__DisplayClass4_0.<SendTokenAsync>b__1(IAsyncResult a)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location ---
   at Azure.Messaging.EventHubs.Amqp.AmqpConnectionScope.RequestAuthorizationUsingCbsAsync(AmqpConnection connection, CbsTokenProvider tokenProvider, Uri endpoint, String audience, String resource, String[] requiredClaims, TimeSpan timeout)
   at Azure.Messaging.EventHubs.Amqp.AmqpConnectionScope.CreateSendingLinkAsync(AmqpConnection connection, Uri endpoint, TransportProducerFeatures features, PartitionPublishingOptionsInternal options, TimeSpan timeout, String linkIdentifier, CancellationToken cancellationToken)
   at Azure.Messaging.EventHubs.Amqp.AmqpConnectionScope.OpenProducerLinkAsync(String partitionId, TransportProducerFeatures features, PartitionPublishingOptionsInternal options, TimeSpan timeout, String linkIdentifier, CancellationToken cancellationToken)
   at Azure.Messaging.EventHubs.Amqp.AmqpProducer.CreateLinkAndEnsureProducerStateAsync(String partitionId, String producerIdentifier, PartitionPublishingOptionsInternal partitionOptions, TimeSpan timeout, CancellationToken cancellationToken)
   at Azure.Messaging.EventHubs.Amqp.AmqpProducer.CreateLinkAndEnsureProducerStateAsync(String partitionId, String producerIdentifier, PartitionPublishingOptionsInternal partitionOptions, TimeSpan timeout, CancellationToken cancellationToken)
   at Microsoft.Azure.Amqp.FaultTolerantAmqpObject`1.OnCreateAsync(TimeSpan timeout)
   at Microsoft.Azure.Amqp.Singleton`1.GetOrCreateAsync(TimeSpan timeout)
   at Microsoft.Azure.Amqp.Singleton`1.GetOrCreateAsync(TimeSpan timeout)
   at Azure.Messaging.EventHubs.Amqp.AmqpProducer.CreateBatchAsync(CreateBatchOptions options, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at Azure.Messaging.EventHubs.Amqp.AmqpProducer.CreateBatchAsync(CreateBatchOptions options, CancellationToken cancellationToken)
   at Azure.Messaging.EventHubs.Producer.EventHubProducerClient.CreateBatchAsync(CreateBatchOptions options, CancellationToken cancellationToken)
   at Azure.Messaging.EventHubs.Producer.EventHubProducerClient.CreateBatchAsync(CancellationToken cancellationToken)
   at Epic.ApiGateway.Diagnostics.TestPerformer.ResultsReporting.AzureEventHubResultReporter.Report(DestinationTestResult testResult) in /home/justin/source/repos/src/MyProject/AzureEventHubEventProducer.cs:line 34}

I have tried changing the connection options in my producer client to use WebSockets like this but that doesn’t help:

    services.AddScoped<Azure.Messaging.EventHubs.Producer.EventHubProducerClient>((sp) =>
    {
        string sasToken = fileReader.ReadAllText(sharedAccessSignatureFilePath).Result;
        
        return new Azure.Messaging.EventHubs.Producer.EventHubProducerClient(fullyQualifiedNamespace,
            eventHubName,
            new AzureSasCredential(sasToken),
            new EventHubProducerClientOptions()
            {
                ConnectionOptions = new EventHubConnectionOptions()
                {
                    TransportType = EventHubsTransportType.AmqpWebSockets
                }
            });
    });

I also tried taking the SAS token and manually sending a request to the Event Hub using HTTPS and that seemed to work just fine:

curl -v -H 'Authorization: SharedAccessSignature sr=https%3a%2f%2fmy-eventhub-001.servicebus.windows.net%2fmyhub1&sig=KlJ4U1{...omitted...}g%3d&se=1640988523&skn=EventProducer' --data 'hello world!' https://my-eventhub-001.servicebus.windows.net/myhub1/messages?timeout=60\&api-version=2014-01

This returns a 201:

< HTTP/1.1 201 Created

It seems to me there is a bug in Azure.Messaging.EventHubs.Producer.EventHubProducerClient which makes it not work with SAS tokens… Unless I am using it incorrectly in which case the documentation should be updated to clarify the proper use. On that note, I also created an issue on the documentation page about some of the code there: https://github.com/MicrosoftDocs/azure-docs/issues/85870

Environment

dotnet --info:

.NET SDK (reflecting any global.json):
 Version:   6.0.100
 Commit:    9e8b04bbff

Runtime Environment:
 OS Name:     ubuntu
 OS Version:  20.04
 OS Platform: Linux
 RID:         ubuntu.20.04-x64
 Base Path:   /usr/share/dotnet/sdk/6.0.100/

Host (useful for support):
  Version: 6.0.0
  Commit:  4822e3c3aa

.NET SDKs installed:
  3.1.416 [/usr/share/dotnet/sdk]
  5.0.403 [/usr/share/dotnet/sdk]
  6.0.100 [/usr/share/dotnet/sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.App 3.1.22 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.12 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.0 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 3.1.22 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.12 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.0 [/usr/share/dotnet/shared/Microsoft.NETCore.App]

To install additional .NET runtimes or SDKs:
  https://aka.ms/dotnet-download

IDE is VS Code

1.63.2
899d46d82c4c95423fb7e10e68eba52050e30ba3
x64

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
jsquirecommented, Jan 3, 2022

Glad to hear that you were able to figure it out and that the fix was simple.

1reaction
js8080commented, Jan 3, 2022

I figured it out…

My SAS token that I was reading from a file had a \n at the end of it… 🤦

For folks that may encounter this issue in the future – check carefully that the SAS token you are passing to new AzureSasCredential(sasToken) does NOT have any stray characters like \n at the end of it as the constructor will not detect that and throw an error on the client side.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Troubleshoot connectivity issues - Azure Event Hubs
Any connection attempt from an IP address that doesn't match an allowed IP rule on the Event Hubs namespace is rejected as unauthorized....
Read more >
Unable to validate credentials using EventProcessorClient ...
I'm seeing the error handler invoked as expected. The Event Hubs service rejects the first operation run (querying properties of the Event ...
Read more >
Event Hub Error: Put token failed. status-code: 401 ...
For me the issue "Put token failed. status-code: 401, status-description: Unauthorized" was caused by the networking configuration of the ...
Read more >
Spring Cloud Azure - Reference Documentation
Managed Identity support for Azure App Configuration, Event Hubs, Service ... SAS token and token credential authentication with Service Bus and Event Hubs....
Read more >
Other exceptions
When you move the event hub connection string from the Azure portal to IBM® QRadar®, ensure that no additional white space or invisible...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found