Azure / azure-iot-sdk-csharp

A C# SDK for connecting devices to Microsoft Azure IoT services
Other
457 stars 493 forks source link

[Bug Report]DeviceClient.GetFileUploadSaSUriAsync() returns invalid SAS when hub is using System-identity. #3460

Open Gamecock opened 1 month ago

Gamecock commented 1 month ago

Context

Description of the issue

Followeing these instructions Fie Upload works. Change the authentication type for iot hub here. from Key-based to System-assigned. Change back, file upload works again.

From python it works by treating the token as an AccessToken and adding an auth header, but that is not an option in C#. image

Original discussion in Q&A.

Code sample exhibiting the issue

Please remove any connection string information! Updated dotnet version and packages, did not test as written.

Console log of the issue

Follow the instructions here to capture SDK logs. Don't forget to remove any connection string information!

Exception thrown: 'Azure.RequestFailedException' in System.Private.CoreLib.dll Azure.RequestFailedException: Server failed to authenticate the request. Please refer to the information in the www-authenticate header. RequestId:2081d445-901e-0073-19b2-bda93b000000 Time:2024-06-13T16:53:36.5127373Z Status: 401 (Server failed to authenticate the request. Please refer to the information in the www-authenticate header.) ErrorCode: NoAuthenticationInformation

Content: <?xml version="1.0" encoding="utf-8"?>NoAuthenticationInformationServer failed to authenticate the request. Please refer to the information in the www-authenticate header. RequestId:2081d445-901e-0073-19b2-bda93b000000 Time:2024-06-13T16:53:36.5127373Z

Headers: Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 x-ms-request-id: 2081d445-901e-0073-19b2-bda93b000000 x-ms-client-request-id: e3128d2e-e46f-4494-aa57-6c5876f0ae64 x-ms-version: 2023-11-03 x-ms-error-code: NoAuthenticationInformation WWW-Authenticate: Bearer authorization_uri=https://login.microsoftonline.com/37051258-66ca-457a-a41d-d94c41705e37/oauth2/authorize resource_id=https://storage.azure.com Date: Thu, 13 Jun 2024 16:53:36 GMT Content-Length: 302 Content-Type: application/xml

at Azure.Storage.Blobs.BlockBlobRestClient.UploadAsync(Int64 contentLength, Stream body, Nullable1 timeout, Byte[] transactionalContentMD5, String blobContentType, String blobContentEncoding, String blobContentLanguage, Byte[] blobContentMD5, String blobCacheControl, IDictionary2 metadata, String leaseId, String blobContentDisposition, String encryptionKey, String encryptionKeySha256, Nullable1 encryptionAlgorithm, String encryptionScope, Nullable1 tier, Nullable1 ifModifiedSince, Nullable1 ifUnmodifiedSince, String ifMatch, String ifNoneMatch, String ifTags, String blobTagsString, Nullable1 immutabilityPolicyExpiry, Nullable1 immutabilityPolicyMode, Nullable1 legalHold, Byte[] transactionalContentCrc64, CancellationToken cancellationToken) at Azure.Storage.Blobs.Specialized.BlockBlobClient.UploadInternal(Stream content, BlobHttpHeaders blobHttpHeaders, IDictionary2 metadata, IDictionary2 tags, BlobRequestConditions conditions, Nullable1 accessTier, BlobImmutabilityPolicy immutabilityPolicy, Nullable1 legalHold, IProgress1 progressHandler, UploadTransferValidationOptions transferValidationOverride, String operationName, Boolean async, CancellationToken cancellationToken) at Azure.Storage.Blobs.Specialized.BlockBlobClient.<>c__DisplayClass65_0.<b__0>d.MoveNext() --- End of stack trace from previous location --- at Azure.Storage.PartitionedUploader2.UploadInternal(Stream content, Nullable1 expectedContentLength, TServiceSpecificData args, IProgress`1 progressHandler, Boolean async, CancellationToken cancellationToken) at Azure.Storage.Blobs.Specialized.BlockBlobClient.UploadAsync(Stream content, BlobUploadOptions options, CancellationToken cancellationToken)

0xDB6 commented 1 month ago

We're having the same problem. The behavior of the IoT Hub seems to have changed a couple days ago. There's another related discussion in the Q&A portal here:

https://learn.microsoft.com/en-us/answers/questions/1696008/notify-uploaded-file-using-system-assigned-authent

The workaround described above to use the wrongly returned access token for authentication can be translated to C# by creating a class which derives from TokenCredential and simply returns the extracted JWT token. If we do that, the upload itself works but the file upload notification fails with a HTTP 400 / IoT Hub error 40020 / 'InvalidStorageEndpointOrBlob' as described in the linked discussion.