2

I'm occasionally having trouble with Azure Storage SAS tokens generated on the server. I don't set anything for start time since this was recommended to avoid clock skew issues, and I set my expiry time to 1 hour after DateTime.UtcNow. Every now and then, the SAS tokens don't work, and I'm guessing this might have to do with a clock skew issue. Here are two errors I received recently:

<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:cb371f2b-801e-0063-16a1-08d06f000000 Time:2021-02-21T22:35:53.9832140Z</Message>
<AuthenticationErrorDetail>Signed expiry time [Sun, 21 Feb 2021 20:39:40 GMT] must be after signed start time [Sun, 21 Feb 2021 22:35:53 GMT]</AuthenticationErrorDetail>
</Error>

<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:8818c581-401e-0058-6477-08717d000000 Time:2021-02-21T17:35:37.1284611Z</Message>
<AuthenticationErrorDetail>Signature not valid in the specified time frame: Start [Sat, 20 Feb 2021 00:15:01 GMT] - Expiry [Sat, 20 Feb 2021 01:30:01 GMT] - Current [Sun, 21 Feb 2021 17:35:37 GMT]</AuthenticationErrorDetail>
</Error>

This is how I generate the token:

var blobSasBuilder = new BlobSasBuilder
{
      BlobContainerName = containerName,
      BlobName = fileName,
      Resource = "b",
      ExpiresOn = DateTime.UtcNow.AddHours(1),
      Protocol = SasProtocol.Https
};

How can I fix this issue? According to the above error, it looks like I tried to access this resource after the token expired, but in reality I tried to access it immediately after the token was generated and sent to the client. As I said, this does not happen often, but it's a recurring problem.

On a second thought, I wonder if this is a bug with the v12 SDK.

user246392
  • 2,661
  • 11
  • 54
  • 96
  • Assuming it's clock skew: Try setting your start time to something a bit earlier than current time (maybe a minute early, for example). This should at least eliminate any skew-based access issue when trying to use a SAS immediately after creation. – David Makogon Feb 14 '21 at 02:15
  • 1
    I set it to 15 minutes into the past. I'll see if this fixes anything. – user246392 Feb 14 '21 at 02:23
  • Do you have specific timezone that the function is supposed to run in. Check if there is an application setting on that function with name of WEBSITE_TIME_ZONE. In any case, add logging and log parameters like current time, start time and end time that you set in the code. Also, while you mentioned in the comment how the code is written, it would be useful to post the relevant portion. Is this reproducible in an isolated code? If so post that in entirety along with the exact version of SDK etc so it can be reproduced by someone else. In principle the design should work. – amit_g Feb 20 '21 at 22:26
  • I don't have WEBSITE_TIME_ZONE setting. Also, I added logs and noticed Azure Functions is fine. The expiry time I generate on the server is different from the error message I'm getting, which makes me think the storage side has the issue. – user246392 Feb 21 '21 at 17:47
  • Does the logged start and expiry time match these as part of the sas token which has both values in it too? – amit_g Feb 22 '21 at 01:50
  • Have you checked both machine's clock are synced? Sometimes if the machine's local time is out of sync, usually machine's loose track of time, if they are not synced with a time server. – Akash Kava Feb 25 '21 at 05:43
  • Can you show the SAS token URL but without the signature? – Igor Feb 26 '21 at 22:44

2 Answers2

1

According to the error, the start time is later than your expiration time and current time. Please set the start time to be at least 15 minutes in the past. enter image description here

For example

I use Net SDK Azure.Storage.Blobs

//  Creates a client to the BlobService using the connection string.
var blobServiceClient = new BlobServiceClient(storageConnectionString);

//  Gets a reference to the container.
var blobContainerClient = blobServiceClient.GetBlobContainerClient(<ContainerName>);

//  Gets a reference to the blob in the container
BlobClient blobClient = containerClient.GetBlobClient(<BlobName>);

//  Defines the resource being accessed and for how long the access is allowed.
var blobSasBuilder = new BlobSasBuilder
{
    StartsOn = DateTime.UtcNow.Subtract(-15), 
    ExpiresOn = DateTime.UtcNow.AddHours(1),
    BlobContainerName = <ContainerName>,
    BlobName = <BlobName>,
};
    
//  Defines the type of permission.
blobSasBuilder.SetPermissions(BlobSasPermissions.Write);
       
//  Builds an instance of StorageSharedKeyCredential      
var storageSharedKeyCredential = new StorageSharedKeyCredential(<AccountName>, <AccountKey>);

//  Builds the Sas URI.
var sasQueryParameters = blobSasBuilder.ToSasQueryParameters(storageSharedKeyCredential);
Jim Xu
  • 21,610
  • 2
  • 19
  • 39
  • Originally, I did not set the start time to anything as recommended in the text you uploaded (See `Or, don't set it at all, which will make it valid immediately in all cases`). This should have worked, right? Why isn't this approach working? – user246392 Feb 15 '21 at 17:28
  • @user246392 Could you please tell me how you create as token? – Jim Xu Feb 16 '21 at 00:58
  • I do it similar to how you did it above, but I remove the line `StartsOn = DateTime.UtcNow.Subtract(-15), `. In other words, I leave `StartsOn` as its default value. – user246392 Feb 17 '21 at 03:56
  • @user246392 According to my test, it is ok for me. My code : https://pastebin.pl/view/cdc14ffd . My result https://imgur.com/a/kppDGl2 – Jim Xu Feb 17 '21 at 06:05
  • I subtracted 15 mins from the current utc time for `StartsOn` and added 1 hour for `ExpiresOn`, but I'm still occasionally getting errors. This time the error message is different. `Signature not valid in the specified time frame: Start [Sat, 20 Feb 2021 01:55:41 GMT] - Expiry [Sat, 20 Feb 2021 03:10:41 GMT] - Current [Sat, 20 Feb 2021 03:15:32 GMT]` – user246392 Feb 20 '21 at 03:22
0

The code that generates the SAS must run on a machine where the date, time and time zone are correctly set.

The error messages are a little different for both cases. First error: is saying that Signed expiry time is ~1h:56m before the error time, how it can be possible? Maybe the SAS expire time was set to a value that is too early, I mean almost 2 hours earlier and not 15 minutes earlier? or Most likely the SAS start time is greater than the SAS end time?

Second error: the time of error is 21 February, but the SAS expires on 20 February, again, it looks like the SAS time is expired, but this time with more than 35 hours and not 15 minutes.

Maybe the machine that runs the code for generating the SAS has some issues with time? This can be checked by polling that machine for its time at regular intervals(once per minute for example) and comparing the results.

Harold Adrian
  • 13
  • 1
  • 6
Igor
  • 266
  • 1
  • 3
  • 13