I'm using Ruby to generate a blob URL. e.g.:
The error I get is "Signature did not match":
<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:0daa3721-e01e-0002-3049-58f5bf000000 Time:2023-03-16T20:55:10.7515529Z</Message>
<AuthenticationErrorDetail>Signature did not match. String to sign used was r 2023-03-14T20:52:54Z 2023-03-18T20:52:54Z /blob/anasstoragetest2023/telestream/test.mov https 2021-12-02 b </AuthenticationErrorDetail>
</Error>
Although output of the code shows that the signed string is identical to the one logged in the error message:
String to sign: r 2023-03-14T20:52:54Z 2023-03-18T20:52:54Z /blob/anasstoragetest2023/telestream/test.mov https 2021-12-02 b
I am aware that there is a SAS generator provided by Azure here but it also generates the same error:
blob_path = "/blob/#{account_name}/#{container_name}/#{blob_name}"
signature =
Azure::Storage::Common::Core::Auth::SharedAccessSignature.new(account_name, account_key)
sas_token =
signature.generate_service_sas_token(blob_path, service: 'b', resource: 'b')
puts "\nCreated SAS token: #{sas_token}"
url = "https://#{account_name}.blob.core.windows.net/#{container_name}/#{blob_name}?#{sas_token}"
puts "\nCreated URL: #{url}"
Custom ruby code below. I tried with both ruby 3.1.3 and 2.6.8. Used gem install azure-storage-blob for both.
Any help would be appreciated!
def generate_blob_url(account_name, account_key, container_name, blob_name)
start_time = Time.now
days = 60*60*24*2
signed_permissions = "r"
signed_start = (start_time - days).utc.iso8601
signed_expiry = (start_time + days).utc.iso8601
canonicalized_resource = "/blob/#{account_name}/#{container_name}/#{blob_name}"
signed_identifier = ""
signed_ip = ""
signed_protocol = "https"
signed_version = "2021-12-02" # "2018-11-09"
signed_resource = "b"
signed_snapshottime = ""
rscc = ""
rscd = ""
rsce = ""
rscl = ""
rsct = ""
string_to_sign = signed_permissions + "\n" +
signed_start + "\n" +
signed_expiry + "\n" +
canonicalized_resource + "\n" +
signed_identifier + "\n" +
signed_ip + "\n" +
signed_protocol + "\n" +
signed_version + "\n" +
signed_resource + "\n" +
signed_snapshottime + "\n" +
rscc + "\n" +
rscd + "\n" +
rsce + "\n" +
rscl + "\n" +
rsct
puts "\nString to sign: #{string_to_sign.gsub("\n", " ")}"
sig = Base64.strict_encode64(OpenSSL::HMAC.digest('sha256', account_key, string_to_sign))
token = "sp=#{signed_permissions}&st=#{signed_start}&se=#{signed_expiry}&spr=#{signed_protocol}&sv=#{signed_version}&sr=#{signed_resource}&sig=#{sig}"
puts "\nGenerated token: #{token}"
url = "https://#{account_name}.blob.core.windows.net/#{container_name}/#{blob_name}?#{CGI.escape(token)}"
end
So,
The azure-ruby-storage client library doesn't work. The signature generator is outdated.
I managed to fix the custom code. I was missing a bunch of newline characters that needed to sit in between the signature body. It's ridiculous that Azure doesn't just take out additional newlines from the signature body before generating the signature. Even the error message does not include those newlines.
Anyway, here's the fixed code below: