Class: DuodealerApp::SameSiteCookieMiddleware

Inherits:
Object
  • Object
show all
Defined in:
lib/duodealer_app/middleware/same_site_cookie_middleware.rb

Constant Summary collapse

"\n"

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app) ⇒ SameSiteCookieMiddleware

Returns a new instance of SameSiteCookieMiddleware.



7
8
9
# File 'lib/duodealer_app/middleware/same_site_cookie_middleware.rb', line 7

def initialize(app)
  @app = app
end

Class Method Details

.chromium_based?(sniffer) ⇒ Boolean

Returns:

  • (Boolean)


52
53
54
# File 'lib/duodealer_app/middleware/same_site_cookie_middleware.rb', line 52

def self.chromium_based?(sniffer)
  sniffer.browser_name.downcase.match(/chrom(e|ium)/)
end

.drops_unrecognized_same_site_cookies?(sniffer) ⇒ Boolean

Returns:

  • (Boolean)


47
48
49
50
# File 'lib/duodealer_app/middleware/same_site_cookie_middleware.rb', line 47

def self.drops_unrecognized_same_site_cookies?(sniffer)
  (chromium_based?(sniffer) && sniffer.major_browser_version >= 51 && sniffer.major_browser_version <= 66) ||
    (uc_browser?(sniffer) && !uc_browser_version_at_least?(sniffer: sniffer, major: 12, minor: 13, build: 2))
end

.same_site_none_incompatible?(user_agent) ⇒ Boolean

Returns:

  • (Boolean)


34
35
36
37
38
39
40
# File 'lib/duodealer_app/middleware/same_site_cookie_middleware.rb', line 34

def self.same_site_none_incompatible?(user_agent)
  sniffer = BrowserSniffer.new(user_agent)

  webkit_same_site_bug?(sniffer) || drops_unrecognized_same_site_cookies?(sniffer)
rescue
  true
end

.uc_browser?(sniffer) ⇒ Boolean

Returns:

  • (Boolean)


56
57
58
# File 'lib/duodealer_app/middleware/same_site_cookie_middleware.rb', line 56

def self.uc_browser?(sniffer)
  sniffer.user_agent.downcase.match(/uc\s?browser/)
end

.uc_browser_version_at_least?(sniffer:, major:, minor:, build:) ⇒ Boolean

Returns:

  • (Boolean)


60
61
62
63
64
65
66
67
# File 'lib/duodealer_app/middleware/same_site_cookie_middleware.rb', line 60

def self.uc_browser_version_at_least?(sniffer:, major:, minor:, build:)
  digits = sniffer.browser_version.split(".").map(&:to_i)
  return false unless digits.count >= 3

  return digits[0] > major if digits[0] != major
  return digits[1] > minor if digits[1] != minor
  digits[2] >= build
end

.webkit_same_site_bug?(sniffer) ⇒ Boolean

Returns:

  • (Boolean)


42
43
44
45
# File 'lib/duodealer_app/middleware/same_site_cookie_middleware.rb', line 42

def self.webkit_same_site_bug?(sniffer)
  (sniffer.os == :ios && sniffer.os_version.match(/^([0-9]|1[12])[\.\_]/)) ||
    (sniffer.os == :mac && sniffer.browser == :safari && sniffer.os_version.match(/^10[\.\_]14/))
end

Instance Method Details

#call(env) ⇒ Object



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/duodealer_app/middleware/same_site_cookie_middleware.rb', line 11

def call(env)
  status, headers, body = @app.call(env)
  user_agent = env["HTTP_USER_AGENT"]

  if headers && headers["Set-Cookie"] &&
      !SameSiteCookieMiddleware.same_site_none_incompatible?(user_agent) &&
      DuodealerApp.configuration.enable_same_site_none

    set_cookies = headers["Set-Cookie"]
      .split(COOKIE_SEPARATOR)
      .compact
      .map do |cookie|
        cookie << "; Secure" if not cookie =~ /;\s*secure/i
        cookie << "; SameSite=None" unless /;\s*samesite=/i.match?(cookie)
        cookie
      end

    headers["Set-Cookie"] = set_cookies.join(COOKIE_SEPARATOR)
  end

  [status, headers, body]
end