Utiliser des cookies SameSite dans ASP.NET

Par Rick Anderson

SameSite est un brouillon de norme IETF conçu pour fournir une certaine protection contre les attaques de falsification de requête intersites (CSRF). Initialement rédigé en 2016, l’ébauche de norme a été mise à jour en 2019. La norme mise à jour n’est pas compatible avec la norme précédente, les différences les plus notables étant les suivantes :

  • Les cookies sans en-tête SameSite sont traités comme des SameSite=Lax par défaut.
  • SameSite=None doit être utilisé pour autoriser l’utilisation des cookies intersites.
  • Les cookies qui affirment SameSite=None doivent également être marqués comme Secure.
  • Les applications qui utilisent <iframe> peuvent rencontrer des problèmes avec les cookies sameSite=Lax ou sameSite=Strict, car <iframe> est considéré comme un scénario intersites.
  • La valeur SameSite=None n’est pas autorisée par la norme 2016 et conduit certaines implémentations à traiter ces cookies comme SameSite=Strict. Consultez Prise en charge des navigateurs plus anciens dans ce document.

Le paramètre SameSite=Lax fonctionne pour la plupart des cookies d’application. Certaines formes d’authentification comme OpenID Connect (OIDC) et WS-Federation sont par défaut des redirections basées sur POST. Les redirections basées sur POST déclenchent les protections du navigateur SameSite, de sorte que SameSite est désactivé pour ces composants. La plupart des connexions OAuth ne sont pas affectées en raison de différences dans le mode de flux de la demande.

Chaque composant ASP.NET qui émet des cookies doit décider si SameSite est approprié.

Consultez les problèmes connus liés aux applications après l’installation des mises à jour .Net SameSite 2019.

Utilisation de SameSite dans ASP.NET 4.7.2 et 4.8

.Net 4.7.2 et 4.8 prend en charge la norme préliminaire 2019 pour SameSite depuis la publication des mises à jour en décembre 2019. Les développeurs peuvent contrôler par programmation la valeur de l’en-tête SameSite à l’aide de la propriété HttpCookie.SameSite. La définition de la propriété SameSite à Strict, Lax ou None entraîne l'écriture de ces valeurs sur le réseau avec le cookie. Le fait de le définir à (SameSiteMode)(-1) indique qu’aucun en-tête SameSite ne doit être inclus sur le réseau avec le cookie. La propriété HttpCookie.Secure ou « requireSSL » dans les fichiers de configuration peut être utilisée pour marquer le cookie comme Secure ou non.

Les nouvelles HttpCookie instances sont par défaut SameSite=(SameSiteMode)(-1) et Secure=false. Ces valeurs par défaut peuvent être substituées dans la system.web/httpCookies section de configuration, où la chaîne "Unspecified" est une syntaxe de configuration conviviale uniquement pour (SameSiteMode)(-1):

<configuration>
 <system.web>
  <httpCookies sameSite="[Strict|Lax|None|Unspecified]" requireSSL="[true|false]" />
 <system.web>
<configuration>

ASP.Net émet également quatre cookies spécifiques de ses propres fonctionnalités : Authentification anonyme, Authentification par formulaire, État de session et Gestion des rôles. Les instances de ces cookies obtenues au moment de l’exécution peuvent être manipulées à l’aide des SameSite propriétés et Secure comme n’importe quelle autre instance HttpCookie. Toutefois, en raison de l'émergence en patchwork de la norme SameSite, les options de configuration pour ces quatre principales fonctionnalités liées aux cookies sont incohérentes. Les sections et attributs de configuration pertinents, avec les valeurs par défaut, sont indiqués ci-dessous. S’il n’existe aucun SameSite attribut ou Secure associé pour une fonctionnalité, la fonctionnalité revient sur les valeurs par défaut configurées dans la system.web/httpCookies section décrite ci-dessus.

<configuration>
 <system.web>
  <anonymousIdentification cookieRequireSSL="false" /> <!-- No config attribute for SameSite -->
  <authentication>
   <forms cookieSameSite="Lax" requireSSL="false" />
  </authentication>
  <sessionState cookieSameSite="Lax" /> <!-- No config attribute for Secure -->
  <roleManager cookieRequireSSL="false" /> <!-- No config attribute for SameSite -->
 <system.web>
<configuration>

Remarque : « Non spécifié » est disponible uniquement pour system.web/httpCookies@sameSite le moment. Nous espérons ajouter une syntaxe similaire aux attributs cookieSameSite précédemment affichés dans les prochaines mises à jour. La définition (SameSiteMode)(-1) du code fonctionne toujours sur les instances de ces cookies.*

Si vous lisez cela dans une langue autre que l’anglais, indiquez-nous dans ce problème de discussion GitHub si vous souhaitez voir les commentaires de code dans votre langue native.

Reciblage des applications .NET

Pour cibler .NET 4.7.2 ou version ultérieure :

  • Vérifiez queweb.config contient les éléments suivants :

    <system.web>
      <compilation targetFramework="4.7.2"/>
      <httpRuntime targetFramework="4.7.2"/>
    </system.web>
    
    
  • Vérifiez que le fichier projet contient la version TargetFrameworkVersion correcte :

    <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
    

    Le Guide de migration .NET contient plus de détails.

  • Vérifiez que les packages NuGet dans le projet sont ciblés sur la version correcte du framework. Vous pouvez vérifier la version correcte de l’infrastructure en examinant le fichier packages.config , par exemple :

    <?xml version="1.0" encoding="utf-8"?>
    <packages>
      <package id="Microsoft.AspNet.Mvc" version="5.2.7" targetFramework="net472" />
      <package id="Microsoft.ApplicationInsights" version="2.4.0" targetFramework="net451" />
    </packages>
    

    Dans le fichier packages.config précédent, le Microsoft.ApplicationInsights package :

    • Est ciblé sur .NET 4.5.1.
    • L'attribut targetFramework doit être mis à jour pour net472 si un package mis à jour pour votre framework cible existe.

Versions .NET antérieures à la version 4.7.2

Microsoft ne prend pas en charge les versions .NET inférieures à 4.7.2 pour écrire l’attribut de cookie de même site. Nous n’avons pas trouvé de moyen fiable pour :

  • Vérifiez que l’attribut est écrit correctement en fonction de la version du navigateur.
  • Interceptez et ajustez les cookies d’authentification et de session sur les versions antérieures de l’infrastructure.

Changements de comportement des correctifs de décembre

Le changement de comportement spécifique pour .NET Framework est la façon dont la SameSite propriété interprète la None valeur :

  • Avant le correctif, une valeur de None signifiait :
    • N’émettez pas l’attribut du tout.
  • Après le correctif :
    • Valeur de None signifie « Émettre l’attribut avec une valeur de None».
    • Une valeur de (SameSiteMode)(-1) de SameSite empêche l'attribut d'être émis.

La valeur SameSite par défaut pour l’authentification par formulaire et les cookies d’état de session est passée de None à Lax.

Résumé de l’impact des modifications sur les navigateurs

Si vous installez le correctif et émettez un cookie avec SameSite.None, l’une des deux choses se produit :

  • Chrome v80 traite ce cookie en fonction de la nouvelle implémentation et n’applique pas les mêmes restrictions de site sur le cookie.
  • Tout navigateur qui n’a pas été mis à jour pour prendre en charge la nouvelle implémentation suit l’ancienne implémentation. L’ancienne implémentation indique :
    • Si vous voyez une valeur que vous ne comprenez pas, ignorez-la et basculez vers des restrictions de site identiques.

Ainsi, soit l’application s’arrête dans Chrome, soit vous vous arrêtez dans de nombreux autres endroits.

Historique et modifications

La prise en charge de SameSite a d’abord été implémentée dans .NET 4.7.2 à l’aide de la norme brouillon 2016.

Les mises à jour du 19 novembre 2019 pour Windows ont mis à jour .NET 4.7.2+ de la norme 2016 vers la norme 2019. Des mises à jour supplémentaires sont disponibles pour d’autres versions de Windows. Pour plus d’informations, consultez les articles de la base de connaissances qui prennent en charge SameSite dans .NET Framework.

Le brouillon 2019 de la spécification SameSite :

  • N’est pas rétrocompatible avec la version provisoire de 2016. Pour plus d’informations, consultez Prise en charge des navigateurs plus anciens dans ce document.
  • Spécifie que les cookies sont traités comme des SameSite=Lax par défaut.
  • Spécifier que les cookies qui affirment explicitement SameSite=None pour activer la livraison intersites doivent également être marqués comme Secure.
  • Est pris en charge par les correctifs émis comme décrit dans les KB répertoriés ci-dessus.
  • Est prévu pour être activé par Chrome par défaut en février 2020. Les navigateurs ont commencé à passer à cette norme en 2019.

Problèmes connus

Étant donné que les spécifications préliminaires de 2016 et 2019 ne sont pas compatibles, la mise à jour de novembre 2019 du Framework .NET introduit des modifications pouvant être préjudiciables.

  • Les cookies d’état de session et d’authentification par formulaire sont désormais écrits sur le réseau au Lax lieu d’être non spécifiés.
    • Bien que la plupart des applications fonctionnent avec SameSite=Lax des cookies, les applications qui POSTent sur des sites ou des applications qui utilisent iframe peuvent constater que leurs cookies d'état de session ou d'autorisation de formulaires ne sont pas utilisés comme prévu. Pour résoudre ce problème, modifiez la cookieSameSite valeur dans la section de configuration appropriée, comme indiqué précédemment.
  • HttpCookies qui définit SameSite=None explicitement du code ou de la configuration a maintenant cette valeur écrite avec le cookie, alors qu’elle a été précédemment omise. Cela peut entraîner des problèmes avec les navigateurs plus anciens qui prennent uniquement en charge la norme provisoire de 2016.
    • Lorsque vous ciblez des navigateurs prenant en charge la norme brouillon 2019 avec SameSite=None des cookies, n’oubliez pas de les marquer également, sinon ils peuvent ne pas être reconnus.
    • Pour revenir au comportement 2016 de ne pas écrire SameSite=None, utilisez le paramètre aspnet:SupressSameSiteNone=trued’application . Notez que cela s’applique à tous les HttpCookies dans l’application.

Pour plus d’informations sur la configuration des comportements SameSite dans les applications .Net 4.7.2, consultez Azure App Service : gestion des cookies SameSite et correctif .NET Framework 4.7.2 .

Prise en charge des navigateurs plus anciens

La norme SameSite 2016 a exigé que les valeurs inconnues soient traitées comme SameSite=Strict valeurs. Les applications accessibles à partir de navigateurs plus anciens qui prennent en charge la norme SameSite 2016 peuvent s’interrompre lorsqu’elles obtiennent une propriété SameSite avec la valeur None. Les applications web doivent implémenter la détection de navigateur si elles ont l’intention de prendre en charge les navigateurs plus anciens. ASP.NET n’implémente pas la détection du navigateur, car les valeurs User-Agents sont très volatiles et changent fréquemment.

L’approche de Microsoft pour résoudre le problème consiste à implémenter des composants de détection de navigateur pour supprimer l’attribut sameSite=None des cookies si un navigateur est connu pour ne pas le prendre en charge. L’avis de Google était de émettre des cookies doubles, un avec le nouvel attribut, et un sans l’attribut du tout. Toutefois, nous considérons que les conseils de Google sont limités. Certains navigateurs, en particulier les navigateurs mobiles, ont des limites très petites sur le nombre de cookies qu’un site, ou un nom de domaine peut envoyer. L’envoi de plusieurs cookies, notamment les cookies d’authentification, peut rapidement atteindre la limite du navigateur mobile, ce qui peut entraîner des défaillances de l'application difficiles à diagnostiquer et à corriger. En outre, en tant que framework, il existe un vaste écosystème de code et de composants tiers qui peuvent ne pas être mis à jour pour utiliser une approche double cookie.

Le code de détection du navigateur utilisé dans les exemples de projets de ce dépôt GitHub est contenu dans deux fichiers

Ces détections sont les agents de navigateur les plus courants que nous avons vus qui prennent en charge la norme 2016 et pour laquelle l’attribut doit être complètement supprimé. Il n’est pas destiné à une implémentation complète :

  • Votre application peut voir des navigateurs que nos sites de test ne détectent pas.
  • Vous devez être prêt à ajouter des détections si nécessaire pour votre environnement.

La façon dont vous configurez la détection varie en fonction de la version de .NET et du framework web que vous utilisez. Le code suivant peut être appelé sur le site d’appel HttpCookie :

private void CheckSameSite(HttpContext httpContext, HttpCookie cookie)
{
    if (cookie.SameSite == SameSiteMode.None)
    {
        var userAgent = httpContext.Request.UserAgent;
        if (BrowserDetection.DisallowsSameSiteNone(userAgent))
        {
            cookie.SameSite = (SameSiteMode)(-1);
        }
    }
}

Consultez les rubriques suivantes sur les cookies ASP.NET 4.7.2 SameSite :

S’assurer que votre site est redirigé vers HTTPS

Pour ASP.NET 4.x, WebForms et MVC, la fonctionnalité de réécriture d’URL d’IIS peut être utilisée pour rediriger toutes les requêtes vers HTTPS. Le code XML suivant montre un exemple de règle :

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="Redirect to https" stopProcessing="true">
          <match url="(.*)"/>
          <conditions>
            <add input="{HTTPS}" pattern="Off"/>
            <add input="{REQUEST_METHOD}" pattern="^get$|^head$" />
          </conditions>
          <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent"/>
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

Dans les installations locales de IIS URL Rewrite, c'est une fonctionnalité optionnelle qui peut nécessiter une installation.

Tester les applications pour les problèmes sameSite

Vous devez tester votre application avec les navigateurs que vous prenez en charge et parcourir vos scénarios qui impliquent des cookies. Les scénarios de cookies impliquent généralement

  • Formulaires de connexion
  • Mécanismes de connexion externes tels que Facebook, Azure AD, OAuth et OIDC
  • Pages qui acceptent les demandes d’autres sites
  • Pages de votre application conçues pour être incorporées dans des iframes

Vous devez vérifier que les cookies sont créés, conservés et supprimés correctement dans votre application.

Les applications qui interagissent avec des sites distants, par le biais d’une connexion tierce, par exemple, doivent :

  • Testez l’interaction sur plusieurs navigateurs.
  • Appliquez la détection et l’atténuation du navigateur décrites dans ce document.

Testez des applications web à l’aide d’une version cliente qui peut accepter le nouveau comportement SameSite. Chrome, Firefox et Chromium Edge ont tous de nouveaux indicateurs de fonctionnalités d’adhésion qui peuvent être utilisés pour les tests. Une fois que votre application a appliqué les correctifs SameSite, testez-le avec des versions clientes plus anciennes, en particulier Safari. Pour plus d’informations, consultez Prise en charge des navigateurs plus anciens dans ce document.

Tester avec Chrome

Chrome 78+ donne des résultats trompeurs, car une atténuation temporaire est en place. L’atténuation temporaire de Chrome 78+ autorise les cookies de moins de deux minutes. Chrome 76 ou 77 avec les indicateurs de test appropriés activés fournit des résultats plus précis. Pour tester le nouveau comportement SameSite, basculez chrome://flags/#same-site-by-default-cookies sur Activé. Les versions antérieures de Chrome (75 et versions ultérieures) échouent avec le nouveau None paramètre. Consultez Prise en charge des navigateurs plus anciens dans ce document.

Google ne met pas à disposition d’anciennes versions de Chrome. Suivez les instructions fournies dans Télécharger Chromium pour tester les anciennes versions de Chrome. Ne téléchargez pas Chrome à partir des liens fournis en recherchant des versions antérieures de Chrome.

À compter de la version Canary 80.0.3975.0, l’atténuation temporaire Lax+POST peut être désactivée à des fins de test à l’aide du nouvel indicateur --enable-features=SameSiteDefaultChecksMethodRigorously pour permettre le test des sites et des services dans l’état final de la fonctionnalité où l’atténuation a été supprimée. Pour plus d’informations, consultez Mises à jour SameSite des projets Chromium

Tester avec Chrome 80+

Téléchargez une version de Chrome qui prend en charge son nouvel attribut. Au moment de l’écriture, la version actuelle est Chrome 80. Chrome 80 a besoin que l’indicateur chrome://flags/#same-site-by-default-cookies soit activé pour utiliser le nouveau comportement. Vous devez également activer (chrome://flags/#cookies-without-same-site-must-be-secure) pour tester le comportement à venir pour les cookies qui n’ont pas l'attribut sameSite activé. Chrome 80 est prêt à opérer la transition pour traiter les cookies sans cet attribut comme SameSite=Lax, mais avec une période de grâce limitée dans le temps pour certaines demandes. Pour désactiver la période de grâce chronométrée, Chrome 80 peut être lancé avec l’argument de ligne de commande suivant :

--enable-features=SameSiteDefaultChecksMethodRigorously

Chrome 80 contient des messages d’avertissement dans la console du navigateur concernant les attributs sameSite manquants. Utilisez F12 pour ouvrir la console du navigateur.

Tester avec Safari

Safari 12 a strictement implémenté le brouillon précédent et échoue lorsque la nouvelle None valeur se trouve dans un cookie. None est évité via le code de détection du navigateur Prise en charge des navigateurs plus anciens dans ce document. Testez les connexions de type "système d'exploitation" utilisant Safari 12, Safari 13, ou les technologies basées sur WebKit, ainsi que les bibliothèques telles que MSAL, ADAL, ou toute autre bibliothèque que vous utilisez. Le problème dépend de la version sous-jacente du système d’exploitation. OSX Mojave (10.14) et iOS 12 sont connus pour avoir des problèmes de compatibilité avec le nouveau comportement SameSite. La mise à niveau du système d’exploitation vers OSX Catalina (10.15) ou iOS 13 résout le problème. Safari ne dispose pas actuellement d’un indicateur d’adhésion pour tester le nouveau comportement de spécification.

Tester avec Firefox

La prise en charge de Firefox pour la nouvelle norme peut être testée sur la version 68+ en acceptant sur la page about:config avec l’indicateur de fonctionnalité network.cookie.sameSite.laxByDefault. Il n’y a pas eu de rapports de problèmes de compatibilité avec les versions antérieures de Firefox.

Tester avec le navigateur Edge (hérité)

Edge prend en charge l’ancienne norme SameSite. Edge version 44+ n’a aucun problème de compatibilité connu avec la nouvelle norme.

Tester avec Edge (Chromium)

Les indicateurs SameSite sont définis sur la edge://flags/#same-site-by-default-cookies page. Aucun problème de compatibilité n’a été détecté avec Edge Chromium.

Tester avec Electron

Les versions d’Electron incluent des versions antérieures de Chromium. Par exemple, la version d’Electron utilisée par Teams est Chromium 66, qui présente l’ancien comportement. Vous devez effectuer vos propres tests de compatibilité avec la version d’Electron utilisée par votre produit. Consultez Prise en charge des navigateurs plus anciens.

Annulation des correctifs SameSite

Vous pouvez rétablir le comportement sameSite mis à jour dans les applications .NET Framework à son comportement précédent où l'attribut sameSite n'est pas émis pour une valeur de None, et rétablir également les cookies d'authentification et de session afin qu'ils n'émettent pas la valeur. Cela doit être considéré comme un correctif extrêmement temporaire, car les modifications de Chrome interrompent toutes les demandes POST externes ou l’authentification pour les utilisateurs utilisant des navigateurs qui prennent en charge les modifications apportées à la norme.

Restauration du comportement de .NET 4.7.2

Mettez à jour web.config pour inclure les paramètres de configuration suivants :

<configuration> 
  <appSettings>
    <add key="aspnet:SuppressSameSiteNone" value="true" />
  </appSettings>
 
  <system.web> 
    <authentication> 
      <forms cookieSameSite="None" /> 
    </authentication> 
    <sessionState cookieSameSite="None" /> 
  </system.web> 
</configuration>

Ressources additionnelles