lucid-shopify-session 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 9ab531b412e4121b375dfc46db8194436b0a00f42d7abc5a92424663fc8db1a5
4
+ data.tar.gz: 174d49b35b6ee27a16c06033950134eca1f1e8b6a9cc0d7d361075108e3b3a31
5
+ SHA512:
6
+ metadata.gz: e3bb3f3cc25fac5b93c9fe49a64c5bdefcb21c37f439bddfe8c81ed5d698bc52d9fa53f4d1dc04da7aae67bca20c5d60b7af132a65e0d688c6f6d6e3712aa168
7
+ data.tar.gz: cdd5992a9d7b7cbde6f8af8b237d4d3420eb08026c427bdb4dbdf72b89432344d9935d2c209547e3a5649038752859c1b455bac59d38e2bee747ef8b0fa28613
@@ -0,0 +1,30 @@
1
+ lucid-shopify-session
2
+ =====================
3
+
4
+ This is [Shopify's new cookieless authentication][0] method for embedded apps,
5
+ which makes use of session tokens provided by App Bridge to identify the shop.
6
+ Session cookies are no longer viable due to browsers (starting with Safari)
7
+ disabling third-party cookies by default. It is possible to work around, but
8
+ quite impractical and harmful to the user experience, so all embedded apps
9
+ should use this new method going forward.
10
+
11
+ This method also replaces CSRF tokens, as the JWT provides the same protection
12
+ considering that the signed JWT must originate from the Shopify admin (with the
13
+ shared secret), so authenticated requests cannot be forged.
14
+
15
+ [0]: https://shopify.dev/tools/app-bridge/authentication
16
+
17
+
18
+ Installation
19
+ ------------
20
+
21
+ Add the gem to your ‘Gemfile’:
22
+
23
+ gem 'lucid-shopify'
24
+ gem 'lucid-shopify-session'
25
+
26
+
27
+ Usage
28
+ -----
29
+
30
+ _WIP_
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lucid/shopify/session'
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lucid
4
+ module Shopify
5
+ module Session
6
+ autoload :Authorise, 'lucid/shopify/session/authorise'
7
+ autoload :DecodeSessionToken, 'lucid/shopify/session/decode_session_token'
8
+ autoload :Middleware, 'lucid/shopify/session/middleware'
9
+ autoload :VERSION, 'lucid/shopify/session/version'
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'lucid-shopify-session'
5
+
6
+ module Lucid
7
+ module Shopify
8
+ module Session
9
+ class Authorise
10
+ UnauthorisedError = Class.new(Error)
11
+
12
+ # @param env [Hash]
13
+ #
14
+ # @raise [UnauthorisedError]
15
+ def call(env)
16
+ session_token = env['HTTP_AUTHORIZATION']&.[](/Bearer (\S+)/, 1) || ''
17
+
18
+ env['lucid-shopify-session.shop'] = DecodeSessionToken.new.(session_token)
19
+ rescue DecodeSessionToken::Error
20
+ raise UnauthorisedError
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lucid-shopify'
4
+ require 'jwt'
5
+
6
+ module Lucid
7
+ module Shopify
8
+ module Session
9
+ class DecodeSessionToken
10
+ Error = Class.new(Error)
11
+
12
+ # @param token [String]
13
+ #
14
+ # @return [String] the *.myshopify.com domain of the authenticated shop
15
+ #
16
+ # @raise [Error]
17
+ def call(token)
18
+ payload, _ = JWT.decode(token, Shopify.config.shared_secret, true, algorithm: 'HS256')
19
+
20
+ raise Error unless valid?(payload)
21
+
22
+ myshopify_domain(payload)
23
+ rescue JWT::DecodeError
24
+ raise Error
25
+ end
26
+
27
+ # @param payload [Hash]
28
+ #
29
+ # @return [String]
30
+ private def myshopify_domain(payload)
31
+ payload['dest'].sub('https://', '')
32
+ end
33
+
34
+ # @param payload [Hash]
35
+ #
36
+ # @return [Boolean]
37
+ private def valid?(payload)
38
+ return false unless payload['aud'] == Shopify.config.api_key
39
+ return false unless payload['iss'].start_with?(payload['dest'])
40
+ return true
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'lucid-shopify-session'
5
+
6
+ module Lucid
7
+ module Shopify
8
+ module Session
9
+ class Middleware
10
+ # @param app [#call]
11
+ def initialize(app)
12
+ @app = app
13
+ end
14
+
15
+ # @param env [Hash]
16
+ #
17
+ # @param [Array<Integer, Hash{String => String}, Array<String>]
18
+ def call(env)
19
+ Authorise.new.(env)
20
+
21
+ @app.call(env)
22
+ rescue UnauthorisedError
23
+ Rack::Response.new do |res|
24
+ res.status = 401
25
+ res.set_header('Content-Type', 'application/json')
26
+ res.write({
27
+ error: 'Invalid session token',
28
+ }.to_json)
29
+ end.to_a
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lucid
4
+ module Shopify
5
+ module Session
6
+ VERSION = '0.0.1'
7
+ end
8
+ end
9
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lucid-shopify-session
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Kelsey Judson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-12-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.9'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.9'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rubocop
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.89'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.89'
41
+ - !ruby/object:Gem::Dependency
42
+ name: jwt
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.2'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.2'
55
+ - !ruby/object:Gem::Dependency
56
+ name: lucid-shopify
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.64'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.64'
69
+ description:
70
+ email: kelsey@kelseyjudson.dev
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - README.md
76
+ - lib/lucid-shopify-session.rb
77
+ - lib/lucid/shopify/session.rb
78
+ - lib/lucid/shopify/session/authorise.rb
79
+ - lib/lucid/shopify/session/decode_session_token.rb
80
+ - lib/lucid/shopify/session/middleware.rb
81
+ - lib/lucid/shopify/session/version.rb
82
+ homepage: https://github.com/kj/lucid-shopify-session
83
+ licenses:
84
+ - ISC
85
+ metadata: {}
86
+ post_install_message:
87
+ rdoc_options: []
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ required_rubygems_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ requirements: []
101
+ rubygems_version: 3.1.4
102
+ signing_key:
103
+ specification_version: 4
104
+ summary: Shopify client library session token helpers for embedded apps
105
+ test_files: []