clerk-sdk-ruby 2.0.3 → 2.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 692cc6e564176d884eb9697a0bfe4a02affda01032c73a9bf704700e45265e4f
4
- data.tar.gz: 1f425dd5b92b2bb51e20661d2415c4c1d094c781c2b4a7c0b0199dce29897c74
3
+ metadata.gz: dd893298c9206f7cacd07fd7c8db9278c2f1c8353d43582a3275ac2a98558bfb
4
+ data.tar.gz: 7dc3976d5c922f648df6fbf77afd43ea1d2b185d828d23617dad0ac960ea9503
5
5
  SHA512:
6
- metadata.gz: f6497dff3fb8bc8f9a32747dd790a8481571d5b460ee83737c9ca6e43ef98db1dfa5fb8277d10f79b516c62fc58233088dcebd3aa3fd7770ba1f6311d7881b57
7
- data.tar.gz: 8ed32ac76cdd9d9c3615375310808919b139bfc22480a2cdcd05cd8ec1a2b3ce68c62864576c91694888e2164856c341577dc89a2adede157996e68421b3fa1f
6
+ metadata.gz: 17db456db28fc892f2df82e7ee84d2f3799a804c223e7b1e815fc7f6b0ec5a439ac23c7a781495fa8fc5ff0d3b6d2b52171081349f7ce9f27f53bcb1251d91e1
7
+ data.tar.gz: 02fb997d526e9d4116558c88201f2da5db5c8cbeef947dd6aac73373b8d8ed235225f661f9f8d11a538c346140edd66bb8a9b3d503949b226195f374fc86e51e
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  ## unreleased
2
2
 
3
+ ## 2.1.2 - 2022-08-26
4
+
5
+ - fix: Gracefully handle invalid JSON in Authorization header [https://github.com/clerkinc/clerk-sdk-ruby/pull/16]
6
+
7
+ ## 2.1.1 - 2022-02-24
8
+
9
+ - fix: Make Authv2 middleware thread-safe
10
+
3
11
  ## 2.0.0 - 2021-10-21
4
12
 
5
13
  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
 
@@ -10,7 +10,7 @@ module Clerk
10
10
  # the Session object. Subsequent calls to this method will return the cached
11
11
  # Session object.
12
12
  #
13
- # NOTE: For better performance, you can instead use `#clerk_session_claims`
13
+ # NOTE: For better performance, you can instead use `#clerk_verified_session_claims`
14
14
  # which already contains the verified claims as retrieved from the session
15
15
  # token.
16
16
  def clerk_session
@@ -20,7 +20,7 @@ module Clerk
20
20
  # Makes a request to the Clerk API to verify the session again. Returns the
21
21
  # session object as fetched from the API.
22
22
  #
23
- # NOTE: For better performance, you can instead use `#clerk_session_claims`
23
+ # NOTE: For better performance, you can instead use `#clerk_verified_session_claims`
24
24
  # which already contains the verified claims as retrieved from the session
25
25
  # token.
26
26
  #
@@ -1,93 +1,107 @@
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
80
-
81
- token = verify_token(@header_token)
82
- return signed_in(token, @header_token) if token
79
+ if header_token
80
+ begin
81
+ return signed_out(env) if !sdk.decode_token(header_token) # malformed JWT
82
+ rescue JWT::DecodeError
83
+ return signed_out(env) # malformed JSON authorization header
84
+ end
85
+
86
+ token = verify_token(header_token)
87
+ return signed_in(env, token, header_token) if token
83
88
 
84
89
  # Clerk.js should refresh the token and retry
85
90
  return unknown(interstitial: false)
86
91
  end
87
92
 
88
93
  # in cross-origin XHRs the use of Authorization header is mandatory.
89
- if cross_origin_request?(@req)
90
- return signed_out
94
+ if cross_origin_request?(req)
95
+ return signed_out(env)
96
+ end
97
+
98
+ if development_or_staging? && !browser_request?(req)
99
+ # the interstitial won't work if the user agent is not a browser, so
100
+ # short-circuit and avoid rendering it
101
+ #
102
+ # We only limit this to dev/stg because we're not yet sure how robust
103
+ # this strategy is, yet. In the future, we might enable it for prod too.
104
+ return signed_out(env)
91
105
  end
92
106
 
93
107
  ##########################################################################
@@ -95,22 +109,22 @@ module Clerk
95
109
  # COOKIE AUTHENTICATION #
96
110
  # #
97
111
  ##########################################################################
98
- if development_or_staging? && (@req.referrer.nil? || cross_origin_request?(@req))
112
+ if development_or_staging? && (req.referrer.nil? || cross_origin_request?(req))
99
113
  return unknown(interstitial: true)
100
114
  end
101
115
 
102
- if production? && @client_uat.nil?
103
- return signed_out
116
+ if production? && client_uat.nil?
117
+ return signed_out(env)
104
118
  end
105
119
 
106
- if @client_uat == "0"
107
- return signed_out
120
+ if client_uat == "0"
121
+ return signed_out(env)
108
122
  end
109
123
 
110
- token = verify_token(@cookie_token)
124
+ token = verify_token(cookie_token)
111
125
 
112
- if token && token["iat"] && @client_uat && Integer(@client_uat) <= token["iat"]
113
- return signed_in(token, @cookie_token)
126
+ if token && token["iat"] && client_uat && Integer(client_uat) <= token["iat"]
127
+ return signed_in(env, token, cookie_token)
114
128
  end
115
129
 
116
130
  unknown(interstitial: true)
@@ -119,15 +133,15 @@ module Clerk
119
133
  private
120
134
 
121
135
  # Outcome A
122
- def signed_in(claims, token)
123
- @env["clerk"] = ProxyV2.new(session_claims: claims, session_token: token)
136
+ def signed_in(env, claims, token)
137
+ env["clerk"] = ProxyV2.new(session_claims: claims, session_token: token)
124
138
 
125
- @app.call(@env)
139
+ @app.call(env)
126
140
  end
127
141
 
128
142
  # Outcome B
129
- def signed_out
130
- @app.call(@env)
143
+ def signed_out(env)
144
+ @app.call(env)
131
145
  end
132
146
 
133
147
  # Outcome C
@@ -153,7 +167,7 @@ module Clerk
153
167
  return false if origin.nil?
154
168
 
155
169
  # strip scheme
156
- origin = origin.strip.sub(/(^\w+:|^)\/\//, '')
170
+ origin = origin.strip.sub(/\A(\w+:)?\/\//, '')
157
171
  return false if origin.empty?
158
172
 
159
173
  # Rack's host and port helpers are reverse-proxy-aware; that
@@ -164,18 +178,24 @@ module Clerk
164
178
  origin != request_host
165
179
  end
166
180
 
181
+ def browser_request?(req)
182
+ user_agent = req.env["HTTP_USER_AGENT"]
183
+
184
+ !user_agent.nil? && user_agent.starts_with?("Mozilla/")
185
+ end
186
+
167
187
  def verify_token(token)
168
188
  return false if token.nil? || token.strip.empty?
169
189
 
170
190
  begin
171
- @session = sdk.verify_token(token)
191
+ sdk.verify_token(token)
172
192
  rescue JWT::DecodeError, JWT::RequiredDependencyError => e
173
193
  false
174
194
  end
175
195
  end
176
196
 
177
197
  def sdk
178
- @sdk ||= Clerk::SDK.new
198
+ Clerk::SDK.new
179
199
  end
180
200
  end
181
201
  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.3"
4
+ VERSION = "2.1.2"
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.3
4
+ version: 2.1.2
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-08-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday