In the last installment of this series, we discussed how the SameSite cookie specification functioned when it was introduced and how it has changed and is being enforced starting with February the 4th 2020. In this article we try and understand what workflows may be impacted in a website, to help understand if you should take any action.
There are three main scenarios where you may want to change the way in which your website behaves. We shall try and go into some detail in each, and see what can be done to ensure compliance with the new specification.
Scenario 1: the Session cookie and the basket
If you have an ASP.net website where end users are allowed to purchase goods online, and store the information relating to their shopping cart in the session, you may find yourself with the following workflow:
User adds an item to their cart -> Item is added to the session and a cookie is emitted in the response.
User then proceeds to checkout -> your site redirects the user to a payment gateway -> user will supply payment details -> payment gateway will POST some information on the transaction back to your site.
Upon POST-ing information back, since the Session cookie is now marked with SameSite=Lax, it will not be sent along with the form. Remember, the form tag is received along with the response from the payment gateway site after the user has entered the payment details and the transaction was validated, while the POST data is sent to another site (third party site – which happens to be your e-commerce site). If you are relying on the Session cookie being present when processing the cross-site post from the Payment gateway, your site logic will break. This is because the session cookie is now marked as SameSite=Lax by ASP.net by default.
In such cases, changing the Session cookie to be marked with SameSite=None is a good option. However, there is an added constraint: the SameSite specification indicates that SameSite=None attribute can only be added to cookies which are marked as ‘secure’ – meaning they are sent only over https connections and not over http connections. If your site emits a Session cookie marked as SameSite=None over a non-secure connection, it will not be sent back to the server, so make sure all communications involving session state are done over https.
The easiest way to change the Session cookie to incorporate the SameSite=None attribute is to change the configuration of your ASP.net website in the web.config file, like the following:
<sessionState cookieSameSite="None" />
Note that this will only add the SameSite=None attribute to your Session cookie. It will be up to you to ensure that the connection the cookie is sent across is a secure connection. It will also not mitigate the case of older browsers, which will consider SameSite=None as being the same as SameSite=Strict. I will come back to how we can deal with this is code in a later installment.
Scenario 2: the Forms authentication cookie and persistent authentication
This scenario does resemble the Session cookie scenario to some extent. If you are using forms based authentication (not ASP.net Identity – which we may touch upon in a later post), and you have given your users the option to check the ‘Remember me’ checkbox that appears as part of the Login control on a WebForms site, or are just persisting the authentication cookie for longer than the current browser session to allow users to remain logged in, and your site can also receive requests from other websites, then you may face an issue.
On my bookmarking website, www.linqto.me, users are allowed to persist their authentication cookie and remain logged in for convenience. This is done by placing a 30-day expiration on the Authentication cookie when it is emitted:
The site also has a bookmarklet – a piece of Javascript that can be added to the browser’s favorites bar, in order to allow users to bookmark any site they are navigation on from the click of a button. Here is how this looks like in my browser:
If I press the ‘Linqto Bookmarklet’ button, the browser will post some information to www.linqto.me indicating that I would like to bookmark the site which I am currently visiting. This means that I am again cross posting from www.flightradar24.com in this case to www.linqto.me.
If I expect that the POST request arrives with the authentication cookie also set, I will need to make sure that:
- The authentication cookie is emitted with SameSite=None as an attribute to enable cross posting
- The POST by the bookmarklet is made via a secure connection (https)
If this is not the case, I will not be authenticated on my website when doing a POST from the bookmarklet, and this will cause me to lose the data from the POST since I cannot associate it to my account.
To work around this issue, a second piece of configuration can be added to the web.config file, to force the .Net Framework to emit a SameSite=None attribute on the authentication cookie when using Forms Authentication:
<authentication mode="Forms">
<forms ..... cookieSameSite="None" />
</authentication>
Just like before, this will just add the SameSite=None attribute to all authentication cookies emitted. It is up to you as the developer of the site to make sure the cookies are emitted over a secure connection (which should be a good practice for authentication cookies). It will also not deal with the scenario of older browsers which will interpret the attribute to mean SameSite=Strict, effectively inverting the behavior of the browser. I will address how to fix this in code on a per request basis later.
Scenario 3: The Azure Active Directory Authentication
If you have an ASP.net application that uses Azure Active Directory authentication or any other type of federation authentication, like ADFS for example, the authentication workflow will look like the following:
- User request the application’s home page.
- Server detects that no authentication cookie is present and redirects to the Common Authentication Endpoint (https://login.microsoftonline.com in the case of Azure active Directory). It also appends several cookies containing information about the login attempt.
- User Authenticates through various configured methods to the common authentication endpoint
- Authentication Endpoint sends back a response containing a Form element that will POST data back to your website (cross posting)
- The form is automatically POSTed back by the browser to your site. If the cookies that were sent to the client following the first request are not returned, the matching logic will fail, and the authentication will return an error from your application’s Authentication Middleware.
To compensate for this new behavior, starting with the version 4.1.0 of the Microsoft.Owin Nuget package, we can configure the SameSite attribute and the ‘None’ value is part of the possible values for the enumeration.
Scenario 4: All other cookies for you application
As mentioned in the first part of this article series, these cookies remain unchanged: they do not receive an explicit SameSite attribute set to Lax or any other value. However, when they will be received by a browser implementing the new SameSite specification, like Chome version 80 and above, they will implicitly be considered as SameSite=Lax, which can cause some of them to not be sent back to the web-server as described in the table of behaviors described in the previous installment.
Should you wish for a SameSite attribute with a specific value to be added to these cookies as well, you can modify the web.config file of your application as follows:
<configuration>
<system.web>
<httpCookies sameSite="[Strict|Lax|None|Unspecified]" requireSSL="[true|false]" />
<system.web>
<configuration>
Setting the sameSite attribute value to either of the Strict, Lax or None enumeration values will cause a SameSite attribute to be appended on all cookies of your application that are not Authentication or Session related. More information on this can be found here.
Be careful when you set the value to 'None' and also set the requireSSL flag to false - this will not mark the cookie as 'Secure'. As per the new specification, cookies marked with SameSite=None will only be sent back to the server if marked as secure and if the connection between client and server is a secure connection.
In the next part, we will review how we can change the behavior of ASP.net using code to also address the scenarios above.
written by: Paul Cociuba