padlock_auth 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +88 -0
- data/lib/padlock_auth/config.rb +11 -0
- data/lib/padlock_auth/rails/action_cable_channel_helpers.rb +71 -0
- data/lib/padlock_auth/rails/helpers.rb +6 -2
- data/lib/padlock_auth/railtie.rb +4 -0
- data/lib/padlock_auth/version.rb +1 -1
- data/lib/padlock_auth.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d8d0c8061b83de8516e459e26ef96d6e6565f419045c64e7730c4736e7c7c344
|
4
|
+
data.tar.gz: 69972dfbcda669fd154c109ef4512d1719e6dafcc52dba780ce1ec80dd4efbeb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 63297a7bbed887a8120b3c2d7ddd6e33d8d23ddc83352d3d6141d92d23af6271f5c0d866061524649122e90cb67032f995126e5174a7cf7469f583f66674b0ce
|
7
|
+
data.tar.gz: f9d820e5872e376d05b5724bfbf675bf6597cc72065cff1ac56605cfec0a6de9bbd89f38b2e29b6bfcbd4784cac5095351f434a23d51ac60424da4b7a45ce93a
|
data/README.md
CHANGED
@@ -239,6 +239,94 @@ puts response.body
|
|
239
239
|
|
240
240
|
PadlockAuth will extract the username and password using the `from_basic_authorization` method and use them to generate an access token.
|
241
241
|
|
242
|
+
### Securing an Action Cable Connection
|
243
|
+
|
244
|
+
You can use PadlockAuth to secure your Action Cable connections by verifying an access token during the connection process. The access token can be provided via the `"access_token"` or `"bearer_token"` parameters.
|
245
|
+
|
246
|
+
Not all access tokens provide a `subject` method, it is entirely dependent on the implementation.
|
247
|
+
|
248
|
+
Here’s an example implementation:
|
249
|
+
|
250
|
+
```ruby
|
251
|
+
module ApplicationCable
|
252
|
+
class Connection < ActionCable::Connection::Base
|
253
|
+
identified_by :access_token_subject
|
254
|
+
|
255
|
+
def connect
|
256
|
+
self.access_token_subject = find_verified_subject
|
257
|
+
end
|
258
|
+
|
259
|
+
private
|
260
|
+
|
261
|
+
def find_verified_subject
|
262
|
+
if padlock_authorized? "websocket"
|
263
|
+
padlock_auth_token.subject
|
264
|
+
else
|
265
|
+
reject_unauthorized_connection
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
```
|
271
|
+
|
272
|
+
#### Explanation
|
273
|
+
|
274
|
+
- `padlock_authorized?`: Checks if the access token is valid and optionally verifies the required scope (`"websocket"` in this example).
|
275
|
+
- `padlock_auth_token`: Provides access to the verified token, allowing you to retrieve attributes such as `subject`.
|
276
|
+
|
277
|
+
This ensures that only clients with valid access tokens can establish a WebSocket connection. The access token `sub` can then be used to identify the connected client throughout the session.
|
278
|
+
|
279
|
+
#### Example: Connecting to the Action Cable Connection via JS
|
280
|
+
|
281
|
+
```js
|
282
|
+
import { createConsumer } from "@rails/actioncable"
|
283
|
+
|
284
|
+
// Use a function to dynamically generate the URL
|
285
|
+
createConsumer(getWebSocketURL)
|
286
|
+
|
287
|
+
function getWebSocketURL() {
|
288
|
+
const token = localStorage.get('access-token')
|
289
|
+
return `wss://example.com/cable?token=${token}`
|
290
|
+
}
|
291
|
+
```
|
292
|
+
|
293
|
+
### Securing an ActionCable Channel
|
294
|
+
|
295
|
+
PadlockAuth can secure individual Action Cable channels by verifying an access token when a client subscribes. The access token can be provided via the `"access_token"` or `"bearer_token"` parameters.
|
296
|
+
|
297
|
+
Here’s an example implementation:
|
298
|
+
|
299
|
+
```ruby
|
300
|
+
class AuthorizedChannel < ApplicationCable::Channel
|
301
|
+
def subscribed
|
302
|
+
if padlock_authorized? "channel"
|
303
|
+
stream_from "authorized_stream"
|
304
|
+
else
|
305
|
+
reject
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
def unsubscribed
|
310
|
+
# Any cleanup needed when channel is unsubscribed
|
311
|
+
end
|
312
|
+
end
|
313
|
+
```
|
314
|
+
|
315
|
+
#### Explanation
|
316
|
+
|
317
|
+
- `padlock_authorized?`: Validates the access token and ensures it includes the required scope (`"channel"` in this example).
|
318
|
+
|
319
|
+
By leveraging these features, PadlockAuth ensures only authenticated users with the proper access scope can subscribe and receive messages on the channel.
|
320
|
+
|
321
|
+
#### Example: Connecting to the Action Cable Channel via JS
|
322
|
+
|
323
|
+
```js
|
324
|
+
import consumer from "./consumer"
|
325
|
+
|
326
|
+
const token = localStorage.get('access-token')
|
327
|
+
consumer.subscriptions.create({ channel: "AuthorizedChannel", access_token: token })
|
328
|
+
```
|
329
|
+
|
242
330
|
## Installation
|
243
331
|
|
244
332
|
Add this line to your application's Gemfile:
|
data/lib/padlock_auth/config.rb
CHANGED
@@ -94,6 +94,10 @@ module PadlockAuth
|
|
94
94
|
config.instance_variable_set(:@access_token_methods, methods.flatten.compact)
|
95
95
|
end
|
96
96
|
|
97
|
+
def action_cable_methods(*methods)
|
98
|
+
config.instance_variable_set(:@action_cable_methods, methods.flatten.compact)
|
99
|
+
end
|
100
|
+
|
97
101
|
# Calls to `padlock_authorize!` will raise an exception when authentication fails.
|
98
102
|
#
|
99
103
|
def raise_on_errors!
|
@@ -167,6 +171,13 @@ module PadlockAuth
|
|
167
171
|
]
|
168
172
|
end
|
169
173
|
|
174
|
+
def action_cable_methods
|
175
|
+
@action_cable_methods ||= %i[
|
176
|
+
from_access_token_param
|
177
|
+
from_bearer_param
|
178
|
+
]
|
179
|
+
end
|
180
|
+
|
170
181
|
# @!attribute [r] handle_auth_errors
|
171
182
|
#
|
172
183
|
# How to handle authentication errors.
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module PadlockAuth
|
2
|
+
module Rails
|
3
|
+
module ActionCableChannelHelpers
|
4
|
+
module TokenFactory
|
5
|
+
module_function
|
6
|
+
|
7
|
+
# Retreives the access token from the request using the configured methods.
|
8
|
+
def from_params(params, *methods)
|
9
|
+
methods.inject(nil) do |_, method|
|
10
|
+
method = self.method(method) if method.is_a?(Symbol)
|
11
|
+
credentials = method.call(params)
|
12
|
+
break credentials if credentials.present?
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Retreives the access token from the params, and builds an access token object.
|
17
|
+
def authenticate(params)
|
18
|
+
if (token = from_params(params, *PadlockAuth.config.action_cable_methods))
|
19
|
+
PadlockAuth.build_access_token(token)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Extracts the access token from the `access_token` parameter.
|
24
|
+
#
|
25
|
+
# @param params [ActionDispatch::Request] params
|
26
|
+
#
|
27
|
+
# @return [String, nil] Access token
|
28
|
+
#
|
29
|
+
def from_access_token_param(params)
|
30
|
+
params[:access_token]
|
31
|
+
end
|
32
|
+
|
33
|
+
# Extracts the access token from the `bearer_token` parameter.
|
34
|
+
#
|
35
|
+
# @param params [ActiveSupport::HashWithIndifferentAccess] params
|
36
|
+
#
|
37
|
+
# @return [String, nil] Access token
|
38
|
+
#
|
39
|
+
def from_bearer_param(params)
|
40
|
+
params[:bearer_token]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# @!visibility public
|
45
|
+
#
|
46
|
+
# Authorize the request with the given scopes.
|
47
|
+
#
|
48
|
+
# If the request is not authorized, an error response will be rendered
|
49
|
+
# or an exception will be raised, depending on the configuration.
|
50
|
+
#
|
51
|
+
# @param scopes [Array<String>] Scopes required for the request, defaults to the default scopes.
|
52
|
+
# @return [Boolean] Whether the request is authorized.
|
53
|
+
#
|
54
|
+
def padlock_authorized?(*scopes)
|
55
|
+
padlock_auth_token&.acceptable?(scopes.presence || PadlockAuth.config.default_scopes)
|
56
|
+
end
|
57
|
+
|
58
|
+
# @!visibility public
|
59
|
+
#
|
60
|
+
# Retrieve the access token from the request.
|
61
|
+
#
|
62
|
+
# Does not check if the token is valid or matches the required scopes.
|
63
|
+
#
|
64
|
+
# @return [PadlockAuth::AbstractToken, nil] Access token
|
65
|
+
#
|
66
|
+
def padlock_auth_token
|
67
|
+
@padlock_auth_token ||= TokenFactory.authenticate(params)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -16,10 +16,14 @@ module PadlockAuth
|
|
16
16
|
#
|
17
17
|
# @param scopes [Array<String>] Scopes required for the request, defaults to the default scopes.
|
18
18
|
#
|
19
|
-
def padlock_authorize!(
|
19
|
+
def padlock_authorize!(...)
|
20
|
+
padlock_render_error unless padlock_authorized?(...)
|
21
|
+
end
|
22
|
+
|
23
|
+
def padlock_authorized?(*scopes)
|
20
24
|
@_padlock_auth_scopes = scopes.presence || PadlockAuth.config.default_scopes
|
21
25
|
|
22
|
-
|
26
|
+
valid_padlock_auth_token?
|
23
27
|
end
|
24
28
|
|
25
29
|
# Default render options for unauthorized requests.
|
data/lib/padlock_auth/railtie.rb
CHANGED
@@ -11,6 +11,10 @@ module PadlockAuth
|
|
11
11
|
ActiveSupport.on_load(:action_controller) do
|
12
12
|
include PadlockAuth::Rails::Helpers
|
13
13
|
end
|
14
|
+
ActiveSupport.on_load(:action_cable) do
|
15
|
+
ActionCable::Connection::Base.include PadlockAuth::Rails::Helpers
|
16
|
+
ActionCable::Channel::Base.include PadlockAuth::Rails::ActionCableChannelHelpers
|
17
|
+
end
|
14
18
|
end
|
15
19
|
|
16
20
|
initializer "padlock_auth.i18n" do
|
data/lib/padlock_auth/version.rb
CHANGED
data/lib/padlock_auth.rb
CHANGED
@@ -40,7 +40,7 @@ module PadlockAuth
|
|
40
40
|
|
41
41
|
# Rails-specific classes
|
42
42
|
module Rails
|
43
|
-
autoload :
|
43
|
+
autoload :ActionCableChannelHelpers, "padlock_auth/rails/action_cable_channel_helpers"
|
44
44
|
autoload :Helpers, "padlock_auth/rails/helpers"
|
45
45
|
autoload :TokenFactory, "padlock_auth/rails/token_factory"
|
46
46
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: padlock_auth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Morrall
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-12-
|
11
|
+
date: 2024-12-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -104,6 +104,7 @@ files:
|
|
104
104
|
- lib/padlock_auth/http/invalid_token_response.rb
|
105
105
|
- lib/padlock_auth/mixins/build_with.rb
|
106
106
|
- lib/padlock_auth/mixins/hide_attribute.rb
|
107
|
+
- lib/padlock_auth/rails/action_cable_channel_helpers.rb
|
107
108
|
- lib/padlock_auth/rails/helpers.rb
|
108
109
|
- lib/padlock_auth/rails/token_factory.rb
|
109
110
|
- lib/padlock_auth/railtie.rb
|