clerk-sdk-ruby 2.0.2 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 14a199089622ba34863506e79d0dc93dfe86f88c7d1d2c2543bb6b15fb5fd927
4
- data.tar.gz: 58e580b74208bcc0da98492257975c9d155c39b0e1c9c1704fae04e9cbeec57e
3
+ metadata.gz: 8a1b17c701d86ec55c4519f72231005a5b83efc07af4180ae98a292a63e422a5
4
+ data.tar.gz: 204eb5ac27340d5d4fc64c7edfc93287c293b9c3d973977b5aa1f87e3ba53ea9
5
5
  SHA512:
6
- metadata.gz: 2dec6b419ca2398552cfb9806b046acee03a5440d122e53fac73446863f52c04d1ffc5009fa3458d88774092b79de2d603b10fc5beb7b3ab6124a0137e2aa679
7
- data.tar.gz: d92a5e3dbf790b9ad0459f3c209ab2721077075bd9c574523b4ce6f7b2f8d7b1023fcf33aa9f21572215db63eb270c1f68e51cd2d5ed501206ff664c1e5d6e25
6
+ metadata.gz: af8693eb43e6f61133966fc47d3ee884697df94c1415fd05d921e6ff35f66807c47e65fba24d51d09db2f9e6177c0624267181ac42f0ea566c580c4c503c95fd
7
+ data.tar.gz: b46bd350059257dcb2b8f8b6d164ead13b563921417ea766b1a4d9847ed5aaa992755f21445ba899503b4f5587b95493121ff3d1a0c7206634f21125611d34ed
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  ## unreleased
2
2
 
3
+ ## 2.1.1 - 2022-02-24
4
+
5
+ - fix: Make Authv2 middleware thread-safe
6
+
3
7
  ## 2.0.0 - 2021-10-21
4
8
 
5
9
  This release introduces the new networkless middleware which works with the new
data/README.md CHANGED
@@ -1,20 +1,25 @@
1
1
  # Clerk Ruby SDK
2
2
 
3
+
3
4
  Thank you for choosing [Clerk](https://clerk.dev/) for your authentication,
4
5
  session & user management needs!
5
6
 
6
7
  This SDK allows you to call the Clerk Backend API from Ruby code without having
7
8
  to implement the calls yourself.
8
9
 
9
- ---------
10
-
11
- **Note**: This is the v2 branch, which requires that you use [Auth
10
+ **Note**: You're looking at the main branch, which requires that you use [Auth
12
11
  v2](https://docs.clerk.dev/main-concepts/auth-v2).
13
12
 
14
- If you're looking for the legacy authentication scheme (Auth v1), refer to the
15
- [`main`](https://github.com/clerkinc/clerk-sdk-ruby/tree/main) branch.
13
+ If you're looking for the legacy authentication scheme, refer to the
14
+ [`v1`](https://github.com/clerkinc/clerk-sdk-ruby/tree/v1) branch.
15
+
16
+ ---
17
+
18
+ **Clerk is Hiring!**
19
+
20
+ Would you like to work on Open Source software and help maintain this repository? Apply today https://apply.workable.com/clerk-dev/.
16
21
 
17
- ----------
22
+ ---
18
23
 
19
24
  ## Installation
20
25
 
@@ -1,93 +1,103 @@
1
1
  require "clerk"
2
2
 
3
3
  module Clerk
4
- class RackMiddlewareV2
5
- class ProxyV2
6
- CACHE_TTL = 60 # seconds
4
+ class ProxyV2
5
+ CACHE_TTL = 60 # seconds
7
6
 
8
- attr_reader :session_claims, :session_token
7
+ attr_reader :session_claims, :session_token
9
8
 
10
- def initialize(session_claims: nil, session_token: nil)
11
- @session_claims = session_claims
12
- @session_token = session_token
13
- @session = nil
14
- end
9
+ def initialize(session_claims: nil, session_token: nil)
10
+ @session_claims = session_claims
11
+ @session_token = session_token
12
+ @session = nil
13
+ end
15
14
 
16
- def session
17
- return nil if @session_claims.nil?
15
+ def session
16
+ return nil if @session_claims.nil?
18
17
 
19
- @session ||= verify_session
20
- end
18
+ @session ||= verify_session
19
+ end
21
20
 
22
- def verify_session
23
- return nil if @session_claims.nil?
21
+ def verify_session
22
+ return nil if @session_claims.nil?
24
23
 
25
- sdk.sessions.verify_token(@session_claims["sid"], @session_token)
26
- end
24
+ sdk.sessions.verify_token(@session_claims["sid"], @session_token)
25
+ end
27
26
 
28
- def user
29
- return nil if user_id.nil?
27
+ def user
28
+ return nil if user_id.nil?
30
29
 
31
- @user ||= fetch_user(user_id)
32
- end
30
+ @user ||= fetch_user(user_id)
31
+ end
33
32
 
34
- def user_id
35
- return nil if @session_claims.nil?
33
+ def user_id
34
+ return nil if @session_claims.nil?
36
35
 
37
- @session_claims["sub"]
38
- end
36
+ @session_claims["sub"]
37
+ end
39
38
 
40
- private
39
+ private
41
40
 
42
- def fetch_user(user_id)
43
- cached_fetch("clerk_user:#{user_id}") do
44
- sdk.users.find(user_id)
45
- end
41
+ def fetch_user(user_id)
42
+ cached_fetch("clerk_user:#{user_id}") do
43
+ sdk.users.find(user_id)
46
44
  end
45
+ end
47
46
 
48
- def cached_fetch(key, &block)
49
- if store = Clerk.configuration.middleware_cache_store
50
- store.fetch(key, expires_in: CACHE_TTL, &block)
51
- else
52
- yield
53
- end
47
+ def cached_fetch(key, &block)
48
+ if store = Clerk.configuration.middleware_cache_store
49
+ store.fetch(key, expires_in: CACHE_TTL, &block)
50
+ else
51
+ yield
54
52
  end
53
+ end
55
54
 
56
- def sdk
57
- @sdk ||= Clerk::SDK.new
58
- end
55
+ def sdk
56
+ @sdk ||= Clerk::SDK.new
59
57
  end
58
+ end
60
59
 
60
+ class RackMiddlewareV2
61
61
  def initialize(app)
62
62
  @app = app
63
63
  end
64
64
 
65
65
  def call(env)
66
- @env = env
67
- @req = Rack::Request.new(env)
68
- @env["clerk"] = ProxyV2.new
69
- @header_token = @req.env["HTTP_AUTHORIZATION"]&.strip
70
- @cookie_token = @req.cookies["__session"]
71
- @client_uat = @req.cookies["__client_uat"]
66
+ env = env
67
+ req = Rack::Request.new(env)
68
+ env["clerk"] = Clerk::ProxyV2.new
69
+ header_token = req.env["HTTP_AUTHORIZATION"]
70
+ header_token = header_token.strip.sub(/\ABearer /, '') if header_token
71
+ cookie_token = req.cookies["__session"]
72
+ client_uat = req.cookies["__client_uat"]
72
73
 
73
74
  ##########################################################################
74
75
  # #
75
76
  # HEADER AUTHENTICATION #
76
77
  # #
77
78
  ##########################################################################
78
- if @header_token
79
- return signed_out if !sdk.decode_token(@header_token) # malformed JWT
79
+ if header_token
80
+ return signed_out(env) if !sdk.decode_token(header_token) # malformed JWT
80
81
 
81
- token = verify_token(@header_token)
82
- return signed_in(token, @header_token) if token
82
+ token = verify_token(header_token)
83
+ return signed_in(env, token, header_token) if token
83
84
 
84
85
  # Clerk.js should refresh the token and retry
85
86
  return unknown(interstitial: false)
86
87
  end
87
88
 
88
89
  # in cross-origin XHRs the use of Authorization header is mandatory.
89
- if cross_origin_request?(@req)
90
- return signed_out
90
+ if cross_origin_request?(req)
91
+ return signed_out(env)
92
+ end
93
+
94
+ if development_or_staging? && !browser_request?(req)
95
+ # the interstitial won't work if the user agent is not a browser, so
96
+ # short-circuit and avoid rendering it
97
+ #
98
+ # We only limit this to dev/stg because we're not yet sure how robust
99
+ # this strategy is, yet. In the future, we might enable it for prod too.
100
+ return signed_out(env)
91
101
  end
92
102
 
93
103
  ##########################################################################
@@ -95,22 +105,22 @@ module Clerk
95
105
  # COOKIE AUTHENTICATION #
96
106
  # #
97
107
  ##########################################################################
98
- if development_or_staging? && (@req.referrer.nil? || cross_origin_request?(@req))
108
+ if development_or_staging? && (req.referrer.nil? || cross_origin_request?(req))
99
109
  return unknown(interstitial: true)
100
110
  end
101
111
 
102
- if production? && @client_uat.nil?
103
- return signed_out
112
+ if production? && client_uat.nil?
113
+ return signed_out(env)
104
114
  end
105
115
 
106
- if @client_uat == "0"
107
- return signed_out
116
+ if client_uat == "0"
117
+ return signed_out(env)
108
118
  end
109
119
 
110
- token = verify_token(@cookie_token)
120
+ token = verify_token(cookie_token)
111
121
 
112
- if token && token["iat"] && @client_uat && Integer(@client_uat) <= token["iat"]
113
- return signed_in(token, @cookie_token)
122
+ if token && token["iat"] && client_uat && Integer(client_uat) <= token["iat"]
123
+ return signed_in(env, token, cookie_token)
114
124
  end
115
125
 
116
126
  unknown(interstitial: true)
@@ -119,15 +129,15 @@ module Clerk
119
129
  private
120
130
 
121
131
  # Outcome A
122
- def signed_in(claims, token)
123
- @env["clerk"] = ProxyV2.new(session_claims: claims, session_token: token)
132
+ def signed_in(env, claims, token)
133
+ env["clerk"] = ProxyV2.new(session_claims: claims, session_token: token)
124
134
 
125
- @app.call(@env)
135
+ @app.call(env)
126
136
  end
127
137
 
128
138
  # Outcome B
129
- def signed_out
130
- @app.call(@env)
139
+ def signed_out(env)
140
+ @app.call(env)
131
141
  end
132
142
 
133
143
  # Outcome C
@@ -153,7 +163,7 @@ module Clerk
153
163
  return false if origin.nil?
154
164
 
155
165
  # strip scheme
156
- origin = origin.strip.sub(/(^\w+:|^)\/\//, '')
166
+ origin = origin.strip.sub(/\A(\w+:)?\/\//, '')
157
167
  return false if origin.empty?
158
168
 
159
169
  # Rack's host and port helpers are reverse-proxy-aware; that
@@ -161,21 +171,27 @@ module Clerk
161
171
  request_host = req.host
162
172
  request_host << ":#{req.port}" if req.port != 80 && req.port != 443
163
173
 
164
- origin == request_host
174
+ origin != request_host
175
+ end
176
+
177
+ def browser_request?(req)
178
+ user_agent = req.env["HTTP_USER_AGENT"]
179
+
180
+ !user_agent.nil? && user_agent.starts_with?("Mozilla/")
165
181
  end
166
182
 
167
183
  def verify_token(token)
168
184
  return false if token.nil? || token.strip.empty?
169
185
 
170
186
  begin
171
- @session = sdk.verify_token(token)
187
+ sdk.verify_token(token)
172
188
  rescue JWT::DecodeError, JWT::RequiredDependencyError => e
173
189
  false
174
190
  end
175
191
  end
176
192
 
177
193
  def sdk
178
- @sdk ||= Clerk::SDK.new
194
+ Clerk::SDK.new
179
195
  end
180
196
  end
181
197
  end
data/lib/clerk/sdk.rb CHANGED
@@ -20,7 +20,8 @@ require_relative "errors"
20
20
  module Clerk
21
21
  class SDK
22
22
  DEFAULT_HEADERS = {
23
- "User-Agent" => "Clerk/#{Clerk::VERSION}; Faraday/#{Faraday::VERSION}; Ruby/#{RUBY_VERSION}"
23
+ "User-Agent" => "Clerk/#{Clerk::VERSION}; Faraday/#{Faraday::VERSION}; Ruby/#{RUBY_VERSION}",
24
+ "X-Clerk-SDK" => "ruby/#{Clerk::VERSION}"
24
25
  }
25
26
 
26
27
  # How often (in seconds) should JWKs be refreshed
data/lib/clerk/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Clerk
4
- VERSION = "2.0.2"
4
+ VERSION = "2.1.1"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: clerk-sdk-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.2
4
+ version: 2.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Clerk
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-10-22 00:00:00.000000000 Z
11
+ date: 2022-02-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -127,7 +127,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
127
127
  - !ruby/object:Gem::Version
128
128
  version: '0'
129
129
  requirements: []
130
- rubygems_version: 3.2.5
130
+ rubygems_version: 3.2.15
131
131
  signing_key:
132
132
  specification_version: 4
133
133
  summary: Clerk SDK for Ruby.