Monday 13 July 2020

Moved

Blogger's editor sucks.

As a result, I've copied all old posts to Github pages where I can author everything in markdown.

https://alanparr.github.io/

All new posts will be at the above url.

Friday 10 July 2020

Supporting SameSite None in .Net 4.6 or lower.

As I write this post, it is 4 days until Chromium begins enforcing the new SameSite rules again.
When they first did this in March, it caused a number of issues including breaking website integrations with some payment gateways.
If you're on .Net 4.7 or higher, Microsoft supports setting SameSite to None. The official recommendation is that if you want to use SameSite None, then you need to move up to .Net 4.7.2, which if you are able, you should absolutely do.
However, there are those of us who are stuck on .Net lower than 4.7 and there is nothing we can do about it and our employers want to know that their sites aren't going to start breaking come the 14th of July.
While trying to find a solution to this problem, I stumbled upon what appears to be a possible solution for those of us stuck on lower .Net versions.
var cookie = new HttpCookie("myreallyimportantcookie")
            {
                Value = "myreallyimportantcookievalue",
                Secure = true,
                Path = "/",
                HttpOnly = true
            };
As you'll see from the below image, we have a cookie with the secure attribute and httponly, but no samesite attribute.

Adding SameSite

In .Net 4.7.2, if we want to support SameSite, we simply add the SameSite attribute.
var cookie = new HttpCookie("myreallyimportantcookie")
            {
                Value = "myreallyimportantcookievalue",
                Secure = true,
                Path = "/",
                HttpOnly = true, 
                SameSite = SameSiteMode.None
            };
Of course, we can't do this in .Net 4.5 as the SameSite property doesn't exist. Instead, we can do this somewhat gross thing:
var cookie = new HttpCookie("myreallyimportantcookie")
            {
                Value = "myreallyimportantcookievalue" + ";SameSite=None",
                Secure = true,
                Path = "/",
                HttpOnly = true
            };
And now if we run the application, we can see we have the SameSite attribute set to None.

Disclaimer #1

This solution is completely unsupported and a bit gross. The approved solution is to move to .Net 4.7.2 and if you are able, you should absolutely do that. But sometimes the real world places limits upon us and if you are in that situation, hopefully this will get you out of a bind.

Disclaimer #2

I have only tested this in an MVC solution in .Net 4.6.1. Theoretically, I think it will probably work in versions lower than that unless the cookie value-handling semantics changed massively at some point in the past. If you want to use this, test for yourself and post a comment if it worked as maybe that will help someone else.

Saturday 13 June 2020

API Head-to-head Update : AWS S3 Vs Windows Azure Table Storage Vs Rackspace Cloud Files

This is an update to my last API head to head from August 2014, I'm nothing if not consistent with my inconsistent posting. I've recently changed jobs to a new company that is moving to Azure but has some legacy Rackspace assets, so I thought it'd be fun to redo the test with Rackspace added. Worth noting that the Rackspace support for C# is completely non-existent. The official Rackspace SDK hasn't been updated since 2013 and this test is using the openstack.net SDK which hasn't been updated since 2018.

The code

Initialise Provider

CloudIdentity cloudIdentity = new CloudIdentity()
{
 APIKey = "mykey",
 Username = "myusername"
};
var provider = new CloudFilesProvider(cloudIdentity);

Create container

provider.CreateContainer(containerName);

Upload file

provider.CreateObjectFromFile(containerName, testFile, blobName);

List Blobs (objects in Rackspace parlance)

provider.ListObjects(containerName).ToList();

Delete file

provider.DeleteObject(containerName, blobName);

Delete container

provider.DeleteContainer(containerName);
Can't argue with the simplicity of the code, once you've initialised the provider, everything is one line.

The results

Worth noting that I don't have the original test file, so the file being uploaded here is one I happened to have lying around of this guy. It is only 1k larger, so don't expect it will have a massive effect on the results.
Operation S3 Azure Rackspace
Create Container8476681915
Upload 7Kb file8392230
List Blobs (1)4017251
Delete Blob4735112
Delete Container2404568
I ran the tests a few times and the numbers fluctuated but the positions pretty much stayed the same, except the Upload file winner switched between S3 and Azure.

Conclusion

Rackspace was slowest, but that isn't terribly surprising considering I was using a third-party 2-year old library, it isn't necessarily a realistic comparison, just for my own amusement.