Reputation: 77
I'm trying to create a File Share via REST API but I'm getting this error
AuthenticationFailed
Server failed to authenticate the request. Make sure the value of > > > Authorization header is formed correctly including the signature. RequestId:aba10b5f-001a-0026-49cb-51d887000000 Time:2017-10-30T22:04:13.9907093ZThe MAC > signature found in the HTTP request > > > 'U8UvWw4KO0fXAk21p/fuXhfqpDdgK7OZn29r5JQ1x4E=' is not the same as any computed > signature. Server used following string to sign: 'PUT
This is my code:
static void CreatFileShare()
{
string requestMethod = "PUT";
string urlPath = strShareName + "?restype=share";
string urlPathResource = "restype:share";
String canonicalizedResource = String.Format("/{0}/{2}\n{1}", StorageAccountName, urlPathResource, /*strShareName*/ "MFS2");
try
{
HttpWebRequest request = GetWebRequest(requestMethod, urlPath, canonicalizedResource, "CreateShare");
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
Console.WriteLine("Response status code: " + response.StatusCode + ". Successfully Create the share \"" + strShareName + "\".");
}
}
catch (WebException ex)
{
ThrowWebException(ex);
}
}
static HttpWebRequest GetWebRequest(string requestMethod, string urlPath, String canonicalizedResource, string MethodType)
{
HttpWebRequest request = null;
try
{
const string type = "file";
const string msVersion = "2017-04-17";
String dateInRfc1123Format = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);
String canonicalizedHeaders = "";
//canonicalizedHeaders = String.Format("x-ms-date:{0}\nx-ms-version:{1}", dateInRfc1123Format, msVersion);
canonicalizedHeaders = String.Format("x-ms-date:{0}\nx-ms-version:{1}\n", dateInRfc1123Format, msVersion);
if (MethodType == "CreateFile")
{
canonicalizedHeaders = String.Format("x-ms-content-length:1024\nx-ms-date:{0}\nx-ms-type:file\nx-ms-version:{1}", dateInRfc1123Format, msVersion);
}
String stringToSign = "";
//stringToSign = String.Format("{0}\n\n\n\n\n\n\n\n\n\n\n\n{1}\n{2}", requestMethod, canonicalizedHeaders, canonicalizedResource);
stringToSign = String.Format("{0}\n\n\n\n\n\n\n\n\n\n\n\n{1}{2}", requestMethod, canonicalizedHeaders, canonicalizedResource);
String authorizationHeader = CreateAuthorizationHeader(stringToSign);
Uri uri = new Uri(FileEndPoint + urlPath);
request = (HttpWebRequest)WebRequest.Create(uri);
if (requestMethod != "Get")
{
request.ContentLength = 0;
}
request.Method = requestMethod;
request.Headers.Add("x-ms-date", dateInRfc1123Format);
request.Headers.Add("x-ms-version", msVersion);
request.Headers.Add("Authorization", authorizationHeader);
request.Headers.Add("Accept-Charset", "UTF-8");
request.Accept = "application/atom+xml,application/xml";
if (MethodType == "CreateFile")
{
request.Headers.Add("x-ms-content-length", "1024");
request.Headers.Add("x-ms-type", type);
}
}
catch (Exception ex)
{
throw ex;
}
return request;
}
I'm using the HMAC-SHA256 algorithm within CreateAuthorizationHeader
method
My application also has logic to retrieve the File shares and Directories/Files inside a storage account and it's working ok. The problem comes at the moment I want to create a File, File share or share snapshot.
Any help would be greatly appreciated!!
Upvotes: 2
Views: 7552
Reputation: 18465
For Create Share the request would be:
PUT https://{your-storage-accountname}.file.core.windows.net/{share-name}?restype=share
Request Headers:
x-ms-version: 2017-04-17
x-ms-date: <date>
Authorization: SharedKey {your-storage-accountname}:{shared-key-signature-string}
The canonicalized headers string would be:
x-ms-date:Wed, 01 Nov 2017 05:53:50 GMT\nx-ms-version:2017-04-17\n
The Canonicalized Resource string would be:
/{your-account-name}/{your-share-name}\nrestype:share
While for Create File, the request would be:
PUT https://{your-storage-accountname}.file.core.windows.net/{share-name}/{file}
Request Headers:
x-ms-version: 2017-04-17
x-ms-date: <date>
x-ms-content-length: 1024 //This header specifies the maximum size for the file, up to 1 TB.
Authorization: SharedKey {your-storage-accountname}:{shared-key-signature-string}
The canonicalized headers string would be:
x-ms-content-length:1024\nx-ms-date:Wed, 01 Nov 2017 06:03:57 GMT\nx-ms-type:file\nx-ms-version:2017-04-17\n
The Canonicalized Resource string would be:
/{your-account-name}/{your-share-name}/{your-file}
//e.g. /brucchstorage/myshare1/helloworld.txt
For your code, you need to modify the parameters urlPath
and canonicalizedResource
under your CreatFileShare
method to support creating the file. Also, you need to append a new-line character (\n
) to the canonicalizedHeaders
parameter under your GetWebRequest
method for the MethodType equals CreateFile
.
Additionally, the common cause for this issue dues to the generating for the CanonicalizedResource and CanonicalizedHeaders. I would recommend you refer to Authentication for the Azure Storage Services for a better understanding of them. Also, you could leverage fiddler to capture the network traces and compare the string to sign from the error response with your local value to narrow this issue.
As Gaurav Mantri commented that you could leverage the Azure Storage Client Library for .NET to achieve your purpose in a simple way. More details, you could refer to here.
Upvotes: 1