clerk-sdk-ruby 2.0.3 → 2.1.2
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 +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +11 -6
- data/lib/clerk/authenticatable.rb +2 -2
- data/lib/clerk/rack_middleware_v2.rb +88 -68
- data/lib/clerk/sdk.rb +2 -1
- data/lib/clerk/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dd893298c9206f7cacd07fd7c8db9278c2f1c8353d43582a3275ac2a98558bfb
|
4
|
+
data.tar.gz: 7dc3976d5c922f648df6fbf77afd43ea1d2b185d828d23617dad0ac960ea9503
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
15
|
-
[`
|
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 `#
|
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 `#
|
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
|
5
|
-
|
6
|
-
CACHE_TTL = 60 # seconds
|
4
|
+
class ProxyV2
|
5
|
+
CACHE_TTL = 60 # seconds
|
7
6
|
|
8
|
-
|
7
|
+
attr_reader :session_claims, :session_token
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
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
|
-
|
17
|
-
|
15
|
+
def session
|
16
|
+
return nil if @session_claims.nil?
|
18
17
|
|
19
|
-
|
20
|
-
|
18
|
+
@session ||= verify_session
|
19
|
+
end
|
21
20
|
|
22
|
-
|
23
|
-
|
21
|
+
def verify_session
|
22
|
+
return nil if @session_claims.nil?
|
24
23
|
|
25
|
-
|
26
|
-
|
24
|
+
sdk.sessions.verify_token(@session_claims["sid"], @session_token)
|
25
|
+
end
|
27
26
|
|
28
|
-
|
29
|
-
|
27
|
+
def user
|
28
|
+
return nil if user_id.nil?
|
30
29
|
|
31
|
-
|
32
|
-
|
30
|
+
@user ||= fetch_user(user_id)
|
31
|
+
end
|
33
32
|
|
34
|
-
|
35
|
-
|
33
|
+
def user_id
|
34
|
+
return nil if @session_claims.nil?
|
36
35
|
|
37
|
-
|
38
|
-
|
36
|
+
@session_claims["sub"]
|
37
|
+
end
|
39
38
|
|
40
|
-
|
39
|
+
private
|
41
40
|
|
42
|
-
|
43
|
-
|
44
|
-
|
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
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
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
|
-
|
57
|
-
|
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
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
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
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
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?(
|
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? && (
|
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? &&
|
103
|
-
return signed_out
|
116
|
+
if production? && client_uat.nil?
|
117
|
+
return signed_out(env)
|
104
118
|
end
|
105
119
|
|
106
|
-
if
|
107
|
-
return signed_out
|
120
|
+
if client_uat == "0"
|
121
|
+
return signed_out(env)
|
108
122
|
end
|
109
123
|
|
110
|
-
token = verify_token(
|
124
|
+
token = verify_token(cookie_token)
|
111
125
|
|
112
|
-
if token && token["iat"] &&
|
113
|
-
return signed_in(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
|
-
|
136
|
+
def signed_in(env, claims, token)
|
137
|
+
env["clerk"] = ProxyV2.new(session_claims: claims, session_token: token)
|
124
138
|
|
125
|
-
@app.call(
|
139
|
+
@app.call(env)
|
126
140
|
end
|
127
141
|
|
128
142
|
# Outcome B
|
129
|
-
def signed_out
|
130
|
-
@app.call(
|
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(
|
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
|
-
|
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
|
-
|
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
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.
|
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:
|
11
|
+
date: 2022-08-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|