0
votes

I'm generating an Azure SAS token to upload a file to Azure like this

    // create client
    val storageConnectionString = s"DefaultEndpointsProtocol=https;AccountName=${accountName};AccountKey=${accountKey}"
    val storageAccount = CloudStorageAccount.parse(storageConnectionString)
    val client = storageAccount.createCloudBlobClient()
    // get blob client
    val container = client.getContainerReference(containerName)
    val blockBlob = container.getBlockBlobReference(path)
    // generate SAS token
    val policy = new SharedAccessBlobPolicy()
    policy.setPermissions(EnumSet.of(SharedAccessBlobPermissions.CREATE, SharedAccessBlobPermissions.WRITE))
    val now = new Date()
    val calendar = Calendar.getInstance()
    calendar.setTime(now)
    calendar.add(Calendar.DATE, -1)
    val start = calendar.getTime
    calendar.add(Calendar.HOUR, 10)
    val end = calendar.getTime
    policy.setSharedAccessStartTime(start)
    policy.setSharedAccessExpiryTime(end)
    val token = blockBlob.generateSharedAccessSignature(policy, null)

The output of the logic above is something like this

sig=XXXXXXXXXXXXXXX&st=2020-09-04T00%3A13%3A56Z&se=2020-09-04T10%3A13%3A56Z&sv=2019-02-02&spr=https&sp=cw&sr=b

now I tried to add this token to the Authorization header in a PUT request to upload a file

$ curl -X PUT -H 'Accept: */*' -H 'Content-Type: application/json' -H 'Authorization: SharedAccessSignature sig=XXXXXXXXXXXXXXX&st=2020-09-04T00%3A13%3A56Z&se=2020-09-04T10%3A13%3A56Z&sv=2019-02-02&spr=https&sp=cw&sr=b' -d '{}' https://<AccountName>.blob.core.windows.net/<ContainerName>/test.json -v

But this fails with something like this

* upload completely sent off: 8 out of 8 bytes
< HTTP/1.1 403 Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
< Content-Length: 321
< Content-Type: application/xml
< Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
< x-ms-request-id: f5fd7e6b-601e-0058-681b-837a50000000
< Date: Sat, 05 Sep 2020 00:30:47 GMT
< 
<?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:f5fd7e6b-601e-0058-681b-837a50000000
* Connection #0 to host <AccountName>.blob.core.windows.net left intact
Time:2020-09-05T00:30:47.9553766Z</Message></Error>* Closing connection 0

My dependencies in build.sbt:

lazy val azureLibs = Seq(
  "com.azure" % "azure-storage-blob" % "12.7.0",
  "com.microsoft.azure" % "azure-storage" % "8.6.5"
)

How to properly generate a SAS token and use it to upload a file to Azure Blob Storage?

1
According to your code, you create sas token. If so you need to use the script curl -X PUT -H 'Accept: */*' -H 'Content-Type: application/json' -d '{}' https://<AccountName>.blob.core.windows.net/<ContainerName>/test.json?sig=XXXXXXXXXXXXXXX&st=2020-09-04T00%3A13%3A56Z&se=2020-09-04T10%3A13%3A56Z&sv=2019-02-02&spr=https&sp=cw&sr=b -v to upload : docs.microsoft.com/en-us/rest/api/storageservices/…Jim Xu
Echoing the comment above - you’re almost there. The SAS token should be used as a query string appended to the URL of the blob you’re trying to accessAlex
you're right, I should have noticed that, it was this section that got me wrong as they used it as Header and not query param docs.microsoft.com/en-us/rest/api/eventhub/…bachr
@bachr Hi. I have summarized my suggestion as a solution. Besides, since it is useful for you, could you please accept it as an answer?Jim Xu

1 Answers

0
votes

I summarize the solution as below.

If we want to use shared access signatures(SAS token) to manage Azure blob, we need to use the SAS token as query string. So the request url should be like https://<AccountName>.blob.core.windows.net/<ContainerName>/test.json?<your sas token>. For more details, please refer to here