Error copying uploaded video asset from blob to asset (Signature did not match. String to sign used was rwl)

Sturla 176 Reputation points
2022-06-01T08:56:47.063+00:00

Hi I´m following this excellent blogpost on how to copy a blob from my uploaded video container to a newly created asset that in the next step will be transformed in a job

but I´m getting the following error (when code below is run in my Azure AppService)

Azure.RequestFailedException: Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.  
RequestId:f635a9c3-c01e-0040-318e-75f108000000  
Time:2022-06-01T08:07:35.4056551Z  
Status: 403 (Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.)  
ErrorCode: AuthenticationFailed  
  
Additional Information:  
AuthenticationErrorDetail: Signature did not match. String to sign used was rwl  
  
2022-06-01T12:07:26Z  
/blob/eventstreamingdev/$root  
  
2019-02-02  
c  
  
Content:  
<?xml version="1.0" encoding="utf-8"?><Error><Code>AuthenticationFailed</Code><Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.  
RequestId:f635a9c3-c01e-0040-318e-75f108000000  
Time:2022-06-01T08:07:35.4056551Z</Message><AuthenticationErrorDetail>Signature did not match. String to sign used was rwl  
  
2022-06-01T12:07:26Z  
/blob/eventstreamingdev/$root  
  
2019-02-02  
c  
  
  
</AuthenticationErrorDetail></Error>  
  
Headers:  
Server: Microsoft-HTTPAPI/2.0  
x-ms-request-id: f635a9c3-c01e-0040-318e-75f108000000  
x-ms-error-code: AuthenticationFailed  
Date: Wed, 01 Jun 2022 08:07:34 GMT  
Content-Length: 501  
Content-Type: application/xml  
  
   at Azure.Storage.Blobs.BlobRestClient.StartCopyFromURLAsync(String copySource, Nullable`1 timeout, IDictionary`2 metadata, Nullable`1 tier, Nullable`1 rehydratePriority, Nullable`1 sourceIfModifiedSince, Nullable`1 sourceIfUnmodifiedSince, String sourceIfMatch, String sourceIfNoneMatch, String sourceIfTags, Nullable`1 ifModifiedSince, Nullable`1 ifUnmodifiedSince, String ifMatch, String ifNoneMatch, String ifTags, String leaseId, String blobTagsString, Nullable`1 sealBlob, Nullable`1 immutabilityPolicyExpiry, Nullable`1 immutabilityPolicyMode, Nullable`1 legalHold, CancellationToken cancellationToken)  
   at Azure.Storage.Blobs.Specialized.BlobBaseClient.StartCopyFromUriInternal(Uri source, IDictionary`2 metadata, IDictionary`2 tags, Nullable`1 accessTier, BlobRequestConditions sourceConditions, BlobRequestConditions destinationConditions, Nullable`1 rehydratePriority, Nullable`1 sealBlob, BlobImmutabilityPolicy destinationImmutabilityPolicy, Nullable`1 legalHold, Boolean async, CancellationToken cancellationToken)  
   at Azure.Storage.Blobs.Specialized.BlobBaseClient.StartCopyFromUriAsync(Uri source, IDictionary`2 metadata, Nullable`1 accessTier, BlobRequestConditions sourceConditions, BlobRequestConditions destinationConditions, Nullable`1 rehydratePriority, CancellationToken cancellationToken)  
  

            Asset asset = await client.Assets.CreateOrUpdateAsync("MyResourceGroup",  
                                                                  "MyAccountName",  
                                                                  inputAssetName, new Asset());  

My code

Asset asset = await client.Assets.CreateOrUpdateAsync("MyResourceGroup",  
                                                        "MyAccountName",  
                                                        inputAssetName, new Asset());  
  
  
var response = await client.Assets.ListContainerSasAsync("MyResourceGroup",  
                                                        "MyAccountName",  
                                                        inputAssetName,  
                                                        permissions: AssetContainerPermission.ReadWrite,  
                                                        expiryTime: DateTime.UtcNow.AddHours(4).ToUniversalTime());  
  
var sasUri = new Uri(response.AssetContainerSasUrls.First());  
  
var config = configuration["Settings:Azure.Storage.Account.ConnectionString"];  
var sourceBlobClient = new BlockBlobClient(config, uplodaedRecordingBlobtName, "uploaded-videos");  
var targetBlobClient = new BlockBlobClient(sasUri);  
  
// This line throws the error  
await targetBlobClient.StartCopyFromUriAsync(sourceBlobClient.Uri);  

Here are the urls
Source
https://mytreaming.blob.core.windows.net/Uploaded-d0bcc213-fd49-4132-8b90-001fa7e30ddc.mp4/uploaded-videos

Target
https://mytreaming.blob.core.windows.net/asset-0ebab4c7-3a1b-46cd-884f-51a01da6cf79?sv=2019-02-02&sr=c&sig=IWgLE0FJzjVnGsGyOMZLPS%2FGZwARfip%2FVjnO8NF8ewg%3D&se=2022-06-01T12:19:12Z&sp=rwl

There are no firewall rules affecting me I think.
207408-image.png

Note that the destination asset is in the root of the storage account and but the source is in the "uploaded-videos". I didn´t find anything to hint about that being an issue

207428-image.png

Azure Media Services
Azure Media Services
A group of Azure services that includes encoding, format conversion, on-demand streaming, content protection, and live streaming services.
303 questions
Azure Blob Storage
Azure Blob Storage
An Azure service that stores unstructured data in the cloud as blobs.
2,436 questions
0 comments No comments
{count} votes

Accepted answer
  1. shiva patpi 13,141 Reputation points Microsoft Employee
    2022-06-03T00:53:01.523+00:00

    Hello @Sturla ,
    I don't see the complete piece of code , hence can't repro locally - but this is definitely seems be an issue with the SAS Key account token which was generated. Can you check the value of the variable sasUri ?
    How did you generate the SAS Key ? Can you try to re-generate the SAS key of the target and try to test it out manually (i.e. local instead of Azure App Service).
    In general the complete SAS URI format will be something like below: (Dummy key)
    https://forsharing.blob.core.windows.net/test2/test2?sv=2020-04-08&se=2022-06-03T01%3A45%3A12Z&sr=b&sp=r&sig=tQEUiBBq8HBmdygLABDCEFG8ZwvypaAVD3liBcCDGmc%2FI%3D

    I was testing out below sample piece of code to copy the data from one blob to another blob with-in the same storage account without downloading the blob , but it uses Storage Account Key instead of SAS.

    207957-image.png

    Can you try out the sample source code mentioned at : https://learn.microsoft.com/en-us/learn/modules/copy-blobs-from-command-line-and-code/7-move-blobs-using-net-storage-client

    Below is the modified piece of code from above document: (From one storage account blob to another storage account blob)

    public static async void CopyFromOneBlobStorageAccountToAnotherBlobStorageAccount()

    {

            try  
            {  
                var sourceConnection = "DefaultEndpointsProtocol=https;AccountName=forsharing;AccountKey=key==;EndpointSuffix=core.windows.net";  
                BlobServiceClient sourceClient = new BlobServiceClient(sourceConnection);  
                BlobServiceClient destClient = new BlobServiceClient(sourceConnection);  
                string sourceContainer = "test2";  
                string destContainer = "test3";  
                BlobContainerClient sourceBlobContainer = sourceClient.GetBlobContainerClient(sourceContainer);  
                BlobContainerClient destBlobContainer = destClient.GetBlobContainerClient(destContainer);  
                BlobClient destBlob = destBlobContainer.GetBlobClient(sourceBlobContainer.Name);  
                CopyFromUriOperation ops = await destBlob.StartCopyFromUriAsync(GetSharedAccessUri(sourceBlobContainer.Name, sourceBlobContainer));  
            }  
            catch(Exception ex)  
            {  
                Console.WriteLine(ex.ToString());  
            }  
        }  
    
        // Create a SAS token for the source blob, to enable it to be read by the StartCopyFromUriAsync method  
        private static Uri GetSharedAccessUri(string blobName, BlobContainerClient container)  
        {  
            DateTimeOffset expiredOn = DateTimeOffset.UtcNow.AddMinutes(60);  
    
            BlobClient blob = container.GetBlobClient(blobName);  
            Uri sasUri = blob.GenerateSasUri(BlobSasPermissions.Read, expiredOn);  
    
            return sasUri;  
        }  
    

    If you are still facing the issue , kindly post the whole code so that we can help you out accordingly

    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. Sturla 176 Reputation points
    2022-06-03T21:47:06.91+00:00

    Thank you shivapatpi! You answer and links helped me.

    This here is what I ended up doing (basically 99% what you suggested)

    public async Task CopyUploadRecordingToTempAssetAsync(Uri tempSasUri, string uplodaedRecordingBlobtName)
    {
        var tempContainer = new BlockBlobClient(tempSasUri);
    
        var connection = configuration["Settings:Azure.Storage.Account.ConnectionString"];
    
        var sourceContainerName = "uploaded-videos";
        var targetContainerName = tempContainer.BlobContainerName;
    
        var sourcePath = $"host/{uplodaedRecordingBlobtName}";
        var targetPath = uplodaedRecordingBlobtName;
    
        var sourceBlobClient = new BlockBlobClient(connection, sourceContainerName, sourcePath);
        var targetBlobClient = new BlockBlobClient(connection, targetContainerName, targetPath);
    
        await targetBlobClient.StartCopyFromUriAsync(sourceBlobClient.Uri);
    }
    
    1 person found this answer helpful.
    0 comments No comments