Class: SameSiteCookieFix::Middleware

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

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app) ⇒ Middleware

Returns a new instance of Middleware.



3
4
5
# File 'lib/same_site_cookie_fix/middleware.rb', line 3

def initialize(app)
  @app = app
end

Class Method Details

.chromium_based?(sniffer) ⇒ Boolean

Returns:

  • (Boolean)


41
42
43
# File 'lib/same_site_cookie_fix/middleware.rb', line 41

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

.drops_unrecognized_same_site_cookies?(sniffer) ⇒ Boolean

Returns:

  • (Boolean)


36
37
38
39
# File 'lib/same_site_cookie_fix/middleware.rb', line 36

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)


23
24
25
26
27
28
29
# File 'lib/same_site_cookie_fix/middleware.rb', line 23

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)


45
46
47
# File 'lib/same_site_cookie_fix/middleware.rb', line 45

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)


49
50
51
52
53
54
55
56
# File 'lib/same_site_cookie_fix/middleware.rb', line 49

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)


31
32
33
34
# File 'lib/same_site_cookie_fix/middleware.rb', line 31

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



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/same_site_cookie_fix/middleware.rb', line 7

def call(env)
  _status, headers, _body = @app.call(env)
ensure
  user_agent = env['HTTP_USER_AGENT']

  if headers && headers['Set-Cookie'] && !SameSiteCookieFix::Middleware.same_site_none_incompatible?(user_agent)
    cookies = headers['Set-Cookie'].split("\n").compact

    cookies.each do |cookie|
      unless cookie.include?("; SameSite")
        headers['Set-Cookie'] = headers['Set-Cookie'].gsub("#{cookie}", "#{cookie}; secure; SameSite=None\n")
      end
    end
  end
end