Skip to content

Commit

Permalink
Add SameSite None to app session
Browse files Browse the repository at this point in the history
  • Loading branch information
jenshenny committed Jan 13, 2020
1 parent 2ac5a76 commit c57ef40
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 0 deletions.
3 changes: 3 additions & 0 deletions lib/shopify_app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ def self.use_webpacker?
require 'shopify_app/managers/webhooks_manager'
require 'shopify_app/managers/scripttags_manager'

# middleware
require 'shopify_app/middleware/same_site_cookie_middleware'

# session
require 'shopify_app/session/session_storage'
require 'shopify_app/session/session_repository'
Expand Down
4 changes: 4 additions & 0 deletions lib/shopify_app/engine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,9 @@ class Engine < Rails::Engine
storage_access.svg
]
end

initializer "shopify_app.middleware" do |app|
app.config.middleware.insert_before(ActionDispatch::Cookies, ShopifyApp::SameSiteCookieMiddleware)
end
end
end
58 changes: 58 additions & 0 deletions lib/shopify_app/middleware/same_site_cookie_middleware.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
module ShopifyApp
class SameSiteCookieMiddleware
def initialize(app)
@app = app
end

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

if headers && headers['Set-Cookie'] && !SameSiteCookieMiddleware.same_site_none_incompatible?(user_agent) &&
ShopifyApp.configuration.embedded_app == true

cookies = headers['Set-Cookie'].split("\n").compact

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

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

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

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

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

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

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
end
end
32 changes: 32 additions & 0 deletions test/shopify_app/middleware/same_site_cookie_middleware_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
require 'test_helper'

class ShopifyApp::SameSiteCookieMiddlewareTest < ActiveSupport::TestCase
INCOMPATIBLE_USER_AGENTS = [
"Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko)"\
" GSA/87.0.279142407 Mobile/15E148 Safari/605.1",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/605.1.15 (KHTML, like Gecko)"\
" Version/12.1.2 Safari/605.1.15",
"Mozilla/5.0 (Linux; U; Android 7.0; en-US; SM-G935F Build/NRD90M) AppleWebKit/534.30 (KHTML, like Gecko) "\
"Version/4.0 UCBrowser/11.3.8.976 U3/0.8.0 Mobile Safari/534.30",
]

INCOMPATIBLE_USER_AGENTS.each do |user_agent|
test "user agent #{user_agent} is correctly marked as incompatible" do
assert ShopifyApp::SameSiteCookieMiddleware.same_site_none_incompatible?(user_agent)
end
end

COMPATIBLE_USER_AGENTS = [
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117"\
" Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:72.0) Gecko/20100101 Firefox/72.0",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.4"\
" Safari/605.1.15",
]

COMPATIBLE_USER_AGENTS.each do |user_agent|
test "user agent #{user_agent} is correctly marked as incompatible" do
refute ShopifyApp::SameSiteCookieMiddleware.same_site_none_incompatible?(user_agent)
end
end
end

0 comments on commit c57ef40

Please sign in to comment.