Put Blob using Azure REST API returns "Server failed to authenticate the request."


  • Hi

    I'm currently developing some stuff that requires me to upload blobs to the azure blob storage but I've been having some issue with the message signature. On most of my request it works and my table requests never fails (create table, update entity, insert entity and delete entity). The issue start with azure returning the following error: 

    <?xml version="1.0" encoding="utf-8"?><Error><Code>InternalError</Code><Message>Server encountered an internal error. Please try again after some time.

    I then reuse the old request to do a retry. The old message signature looked like this: 



    x-ms-date:Sun, 15 Apr 2012 21:58:47 GMT

    But then I get the following error message when retrying: 

    <?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.
    Time:2012-04-15T21:58:52.3098953Z</Message><AuthenticationErrorDetail>The MAC signature found in the HTTP request 'YUo4shHIcNLnX3rVuNDsn3egE/YL2wGU6yWQ5YkC01Q=' is not the same as any computed signature. Server used following string to sign: 'PUT


    x-ms-date:Sun, 15 Apr 2012 21:58:47 GMT

    Now the content length is set to 0 for some reason and it doesnt work anymore. I am aware of that the request only works for 15 min, but this retry happens a few seconds after the first try. I'm not getting this error when retyring the table requests (for example if the table doesn't exist), it's just for the blob storage I get this.

    This is what the function that creates the header looks like:

    QString AzureRestHandler::authorizationHeader(const QString& method, const QDateTime& now, const QNetworkRequest& request, const qint64 contentLength, const QString& ifMatch, const QString& md5) {
    	QString messageSignature = (isTableStorage() ?
    										 QString("%1 GMT").arg(now.toString("ddd, dd MMM yyyy hh:mm:ss")).toUtf8().constData(),
    								  : QString("%1\n\n\n%2\n%3\n\n\n\n%4\n\n\n\n%5%6")
    										 (contentLength == 0 ? "" : QString::number(contentLength)),
    	qDebug() << "Message signature: " << messageSignature;
    	std::string decoded;
    	cryptlite::base64::decode(_storageKey.toStdString(), decoded);
    	boost::uint8_t digest[cryptlite::sha256::HASH_SIZE];
    	cryptlite::hmac<cryptlite::sha256>::calc(messageSignature.toStdString(), decoded, digest);
    	return QString("SharedKey %1:%2").arg(_storageAccount, QString::fromStdString(cryptlite::base64::encode_from_array(digest, cryptlite::sha256::HASH_SIZE)));

    If you need anymore info to be able to help we I will happy to provide it. I really need some help with this one. Thank you

    Sunday, April 15, 2012 10:30 PM


All replies

  • Have you watched the request/response in a tool like Fiddler? I assume based on the error that the second time, your request is being sent with a content-length header of zero. Double check your code that sends the retried request?

    Monday, April 16, 2012 4:13 AM
  • Hi,

    Do you use Azure emulator as the target storage or the real cloud storage?

    One of the reason for this error can be that (UTC) time at your development machine is different than that on the Azure storage server. At the underlying level the REST mechanism is used for accessing the storage. This also includes encrypted header and in order to counter for replay attacks Azure storage API fails because of date discrepancy.

    Refer to:

    Hope this helps.

    Please mark the replies as answers if they help or unmark if not. If you have any feedback about my replies, please contact Microsoft One Code Framework

    Monday, April 16, 2012 4:58 AM