thecore_backend_commons 3.9.0 → 3.9.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: 4ab4135c3f942d5333ade592af3ae92b194dd0aa6c32b8ee26d6992b8fa30e51
4
- data.tar.gz: 317b0d39134b558ffa1cabfe7f2a6b137269e95438dc736c230ed557608554db
3
+ metadata.gz: 3aa559045828d8dc8ca4981fad05e6ff9ef2f80a7191f2e16db4f45ddcaf1c24
4
+ data.tar.gz: cd8fe33d14e2373a1b01ccd7290ceba1cb75048df57b6591a35c9cb135e077d5
5
5
  SHA512:
6
- metadata.gz: 70d5413c5d89753ed3c1b011d2e76b216a016df55db0dbf90d7162949912a9b4f3e7f363f5a6d9ae257468dd62de6a67358086bf1d0dfe85226a40691459fa8b
7
- data.tar.gz: c88ad248c63439a693e8d6f726cc5066a8765d628774b46ef6a5a9150ed016a6981d96040c0cb7f2f52b844e4e33a47acb3c2fef4a1771202f3bdbbcbf09e653
6
+ metadata.gz: 2a94d02e27478addb9660b69f693d4c8760e92dd11c5698130a7dc38601e1a745d3ca041ee6103204e4aeb070d138ef64877537debba042153ad5d2125650414
7
+ data.tar.gz: 15fc51c68e34e67042f8a02699639d5fb953e8710fce8e5923c225fa414e6c7c52c6ca5e22d3d618b817b88df09597dff65d31b35935bcbbc884b3678029ae2c
@@ -13,5 +13,5 @@ Rails.application.config.action_cable.allowed_request_origins = [/http:\/\/*/, /
13
13
  # and mounts Sidekiq::Web unconditionally (thecore_background_jobs), so ActiveJob should actually
14
14
  # route through it rather than defaulting to Rails' in-process :async, which silently drops any
15
15
  # job in flight when its process restarts. Production only: :async remains the default in
16
- # development/test so neither requires a reachable Redis. See docs/adr/0001, CONTEXT.md.
16
+ # development/test so neither requires a reachable Redis. See docs/adr/0001, GLOSSARY.md.
17
17
  Rails.application.config.active_job.queue_adapter = :sidekiq if Rails.env.production?
@@ -11,22 +11,51 @@ module CableConnectionConcern
11
11
 
12
12
  protected
13
13
 
14
- def find_verified_user
15
- # this checks whether a user is authenticated with devise
16
- # It looks for a token in the query parameters, or in the headers
17
- m = request.query_parameters["token"].presence || request.headers["Authorization"].split(" ").second.strip rescue nil
18
-
19
- # check for m2m token
20
- user = User.where.not(encrypted_access_token: nil).find { |u| BCrypt::Password.new(u.encrypted_access_token) == m } rescue false
21
- return user if user
22
-
23
- # check for JWT token
24
- body = (::HashWithIndifferentAccess.new(::JWT.decode(m, ::Rails.application.credentials.dig(:secret_key_base).presence||ENV["SECRET_KEY_BASE"], false)[0]) rescue nil)
25
- verified_user = env['warden'].user.presence || User.find_by(id: body[:user_id]) rescue false
26
- return verified_user if verified_user
27
-
28
- # The Token is not m2m nor JWT, fail
29
- return reject_unauthorized_connection
14
+ def find_verified_user
15
+ # An already-authenticated Devise/Warden session (e.g. RailsAdmin in the browser) is
16
+ # trusted as-is, before looking at any token.
17
+ warden_user = env["warden"]&.user
18
+ return warden_user if warden_user
19
+
20
+ # Looks for a token in the query parameters, or in the "Authorization" header.
21
+ m = request.query_parameters["token"].presence ||
22
+ request.headers["Authorization"].to_s.split(" ").second&.strip
23
+ return reject_unauthorized_connection if m.blank?
24
+
25
+ # Machine-to-machine token (bcrypt-compared against each user's stored token). Guarded by a
26
+ # column check so this generic gem also works in a host without m2m tokens (and so its own
27
+ # dummy app, whose users table has no such column, doesn't abort the transaction).
28
+ if User.column_names.include?("encrypted_access_token")
29
+ m2m_user = User.where.not(encrypted_access_token: nil)
30
+ .find { |u| BCrypt::Password.new(u.encrypted_access_token) == m } rescue nil
31
+ return m2m_user if m2m_user
32
+ end
33
+
34
+ # JWT: the signature MUST be verified, exactly like every REST request. Decoding with the
35
+ # verification disabled (the previous behaviour) let a forged token carrying an arbitrary
36
+ # user_id authenticate as any user over the WebSocket — and ActivityLogChannel streams every
37
+ # record change, so that was a full read bypass. See docs/adr and the issue tracker.
38
+ body = decode_verified_jwt(m)
39
+ jwt_user = User.find_by(id: body[:user_id]) if body && body[:user_id]
40
+ return jwt_user if jwt_user
41
+
42
+ # Neither a valid m2m nor a valid JWT token: refuse the connection.
43
+ reject_unauthorized_connection
44
+ end
45
+
46
+ # Decodes and VERIFIES a JWT. Reuses model_driven_api's JsonWebToken when present, so the
47
+ # WebSocket shares the REST API's signing key, key-rotation and single-session handling;
48
+ # falls back to a signature-verifying decode so this gem still works on its own. Returns nil
49
+ # on any invalid, forged or expired token.
50
+ def decode_verified_jwt(token)
51
+ if defined?(::JsonWebToken)
52
+ ::JsonWebToken.decode(token)
53
+ else
54
+ secret = ::Rails.application.credentials.dig(:secret_key_base).presence || ENV["SECRET_KEY_BASE"]
55
+ ::HashWithIndifferentAccess.new(::JWT.decode(token, secret, true, algorithm: "HS256")[0])
56
+ end
57
+ rescue StandardError
58
+ nil
30
59
  end
31
60
  end
32
61
  end
@@ -1,3 +1,3 @@
1
1
  module ThecoreBackendCommons
2
- VERSION = "3.9.0".freeze
2
+ VERSION = "3.9.1".freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: thecore_backend_commons
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.9.0
4
+ version: 3.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gabriele Tassoni