SameSiteCookiesServiceCollectionExtensions.cs 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. using Microsoft.AspNetCore.Builder;
  2. using Microsoft.AspNetCore.Http;
  3. using Microsoft.Extensions.DependencyInjection;
  4. namespace AuthServer.Host
  5. {
  6. public static class SameSiteCookiesServiceCollectionExtensions
  7. {
  8. public static IServiceCollection AddSameSiteCookiePolicy(this IServiceCollection services)
  9. {
  10. services.Configure<CookiePolicyOptions>(options =>
  11. {
  12. options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
  13. options.OnAppendCookie = cookieContext =>
  14. CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
  15. options.OnDeleteCookie = cookieContext =>
  16. CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
  17. });
  18. return services;
  19. }
  20. private static void CheckSameSite(HttpContext httpContext, CookieOptions options)
  21. {
  22. if (options.SameSite == SameSiteMode.None)
  23. {
  24. var userAgent = httpContext.Request.Headers["User-Agent"].ToString();
  25. if (!httpContext.Request.IsHttps || DisallowsSameSiteNone(userAgent))
  26. {
  27. // For .NET Core < 3.1 set SameSite = (SameSiteMode)(-1)
  28. options.SameSite = SameSiteMode.Unspecified;
  29. }
  30. }
  31. }
  32. private static bool DisallowsSameSiteNone(string userAgent)
  33. {
  34. // Cover all iOS based browsers here. This includes:
  35. // - Safari on iOS 12 for iPhone, iPod Touch, iPad
  36. // - WkWebview on iOS 12 for iPhone, iPod Touch, iPad
  37. // - Chrome on iOS 12 for iPhone, iPod Touch, iPad
  38. // All of which are broken by SameSite=None, because they use the iOS networking stack
  39. if (userAgent.Contains("CPU iPhone OS 12") || userAgent.Contains("iPad; CPU OS 12"))
  40. {
  41. return true;
  42. }
  43. // Cover Mac OS X based browsers that use the Mac OS networking stack. This includes:
  44. // - Safari on Mac OS X.
  45. // This does not include:
  46. // - Chrome on Mac OS X
  47. // Because they do not use the Mac OS networking stack.
  48. if (userAgent.Contains("Macintosh; Intel Mac OS X 10_14") &&
  49. userAgent.Contains("Version/") && userAgent.Contains("Safari"))
  50. {
  51. return true;
  52. }
  53. // Cover Chrome 50-69, because some versions are broken by SameSite=None,
  54. // and none in this range require it.
  55. // Note: this covers some pre-Chromium Edge versions,
  56. // but pre-Chromium Edge does not require SameSite=None.
  57. if (userAgent.Contains("Chrome/5") || userAgent.Contains("Chrome/6"))
  58. {
  59. return true;
  60. }
  61. return false;
  62. }
  63. }
  64. }