isomorfeus-transport 1.0.0.zeta16 → 1.0.0.zeta17
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/isomorfeus-transport.rb +5 -1
- data/lib/isomorfeus/transport/config.rb +21 -3
- data/lib/isomorfeus/transport/dbm_session_store.rb +51 -0
- data/lib/isomorfeus/transport/handler/authentication_handler.rb +24 -13
- data/lib/isomorfeus/transport/rack_middleware.rb +32 -2
- data/lib/isomorfeus/transport/server_socket_processor.rb +0 -2
- data/lib/isomorfeus/transport/ssr_login.rb +28 -0
- data/lib/isomorfeus/transport/version.rb +1 -1
- data/lib/lucid_authentication/mixin.rb +17 -10
- metadata +10 -9
- data/lib/isomorfeus/transport/thread_session_store.rb +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 22eeb2de4df1584feb9dd4cb3eb042b8a281125b82368fa3b3e173cbcf5e63bb
|
4
|
+
data.tar.gz: c9466283b250e36751be1474d8a862c3146a76e296f740c8ef4999fa91d2e8ca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27ab776d59f7faf791cda3cad826634e317bbf8876811a5eb243ea84c0cf71556f3e29322116870d979f490bdc0083762829ab732c7b56eed43475df005783d7
|
7
|
+
data.tar.gz: 809334de83bd13045111ce18cbfe1b0948757e6b06473b14fa3a55991c118787f9c26a34f44b70c4b2539cd8018f861f857c2b3c90c23739797561702af939dd
|
data/lib/isomorfeus-transport.rb
CHANGED
@@ -10,20 +10,24 @@ if RUBY_ENGINE == 'opal'
|
|
10
10
|
require 'isomorfeus/transport/client_processor'
|
11
11
|
require 'isomorfeus/transport/websocket'
|
12
12
|
require 'isomorfeus/transport'
|
13
|
+
require 'isomorfeus/transport/ssr_login'
|
13
14
|
require 'lucid_channel/mixin'
|
14
15
|
require 'lucid_channel/base'
|
15
16
|
Isomorfeus.zeitwerk.push_dir('channels')
|
16
17
|
Isomorfeus.add_client_init_class_name('Isomorfeus::Transport')
|
18
|
+
Isomorfeus.add_transport_init_class_name('Isomorfeus::Transport::SsrLogin') if Isomorfeus.on_ssr?
|
17
19
|
else
|
18
20
|
require 'base64'
|
19
21
|
require 'digest'
|
22
|
+
require 'bcrypt'
|
20
23
|
require 'ostruct'
|
21
24
|
require 'socket'
|
22
25
|
require 'oj'
|
23
26
|
require 'websocket/driver'
|
24
27
|
require 'active_support'
|
25
28
|
require 'iodine'
|
26
|
-
require '
|
29
|
+
require 'dbm'
|
30
|
+
require 'isomorfeus/transport/dbm_session_store'
|
27
31
|
require 'isomorfeus/config'
|
28
32
|
require 'isomorfeus/promise'
|
29
33
|
require 'isomorfeus/transport/version'
|
@@ -3,6 +3,7 @@ module Isomorfeus
|
|
3
3
|
|
4
4
|
if RUBY_ENGINE == 'opal'
|
5
5
|
add_client_option(:api_websocket_path)
|
6
|
+
add_client_option(:cookie_eater_path)
|
6
7
|
add_client_option(:transport_init_class_names, [])
|
7
8
|
|
8
9
|
def self.add_transport_init_class_name(init_class_name)
|
@@ -10,16 +11,31 @@ module Isomorfeus
|
|
10
11
|
end
|
11
12
|
|
12
13
|
def self.current_user
|
13
|
-
@current_user ||=
|
14
|
+
@current_user ||= init_current_user
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.init_current_user
|
18
|
+
if Isomorfeus.current_user_sid
|
19
|
+
Isomorfeus.instance_from_sid(Isomorfeus.current_user_sid)
|
20
|
+
else
|
21
|
+
Anonymous.new
|
22
|
+
end
|
14
23
|
end
|
15
24
|
|
16
25
|
def self.set_current_user(user)
|
17
|
-
|
26
|
+
if user
|
27
|
+
@current_user = user
|
28
|
+
Isomorfeus.current_user_sid = user.to_sid
|
29
|
+
else
|
30
|
+
@current_user = Anonymous.new
|
31
|
+
end
|
18
32
|
end
|
19
33
|
else
|
20
34
|
class << self
|
21
35
|
attr_accessor :api_websocket_path
|
36
|
+
attr_accessor :cookie_eater_path
|
22
37
|
attr_accessor :session_store
|
38
|
+
attr_accessor :cookie_dbm_path
|
23
39
|
|
24
40
|
def add_middleware(middleware)
|
25
41
|
Isomorfeus.middlewares << middleware
|
@@ -132,9 +148,11 @@ module Isomorfeus
|
|
132
148
|
end
|
133
149
|
end
|
134
150
|
|
135
|
-
self.
|
151
|
+
self.cookie_dbm_path = 'cookie'
|
152
|
+
self.session_store = Isomorfeus::Transport::DbmSessionStore.new # dont use this one, but we keep it here to have at least something
|
136
153
|
end
|
137
154
|
|
138
155
|
# defaults
|
139
156
|
self.api_websocket_path = '/isomorfeus/api/websocket'
|
157
|
+
self.cookie_eater_path = '/isomorfeus/cookie/eat'
|
140
158
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Isomorfeus
|
2
|
+
module Transport
|
3
|
+
class DbmSessionStore
|
4
|
+
def initialize
|
5
|
+
DBM.open(Isomorfeus.cookie_dbm_path, 0640, DBM::NEWDB).close
|
6
|
+
end
|
7
|
+
|
8
|
+
def add(session_id:, cookie:, user:, accessor:)
|
9
|
+
DBM.open(Isomorfeus.cookie_dbm_path, 0640, DBM::WRITER) do |dbm|
|
10
|
+
dbm[session_id] = Oj.dump([user.class.to_s, user.key], mode: :strict)
|
11
|
+
dbm[accessor] = cookie
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def take_cookie(accessor:)
|
16
|
+
DBM.open(Isomorfeus.cookie_dbm_path, 0640, DBM::WRITER) do |dbm|
|
17
|
+
cookie = dbm[accessor]
|
18
|
+
if cookie
|
19
|
+
session_info = cookie.split('; ').first
|
20
|
+
session_id = session_info.split('=').last.strip
|
21
|
+
dbm["eaten_#{accessor}"] = session_id
|
22
|
+
dbm.delete(accessor)
|
23
|
+
else
|
24
|
+
# asked for the same cookie a second time
|
25
|
+
# can probably only be due to session hijacking
|
26
|
+
# so delete all sessions associated with that accessor
|
27
|
+
session_id = dbm["eaten_#{accessor}"]
|
28
|
+
dbm.delete(session_id) if session_id
|
29
|
+
end
|
30
|
+
cookie
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_user(session_id:)
|
35
|
+
json = DBM.open(Isomorfeus.cookie_dbm_path, 0640, DBM::READER) do |dbm|
|
36
|
+
dbm[session_id]
|
37
|
+
end
|
38
|
+
if json
|
39
|
+
user_info = Oj.load(json, mode: :strict)
|
40
|
+
user_info[0].constantize.load(key: user_info[1]) if user_info
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def remove(session_id:)
|
45
|
+
DBM.open(Isomorfeus.cookie_dbm_path, 0640, DBM::WRITER) do |dbm|
|
46
|
+
dbm.delete(session_id)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -18,26 +18,37 @@ module Isomorfeus
|
|
18
18
|
user = nil
|
19
19
|
if Isomorfeus.valid_user_class_name?(user_class_name)
|
20
20
|
user_class = Isomorfeus.cached_user_class(user_class_name)
|
21
|
-
response_agent.request['login'][user_class_name].
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
end
|
21
|
+
user_identifier = response_agent.request['login'][user_class_name].keys.first
|
22
|
+
promise = user_class.promise_login(user: user_identifier, pass: response_agent.request['login'][user_class_name][user_identifier])
|
23
|
+
unless promise.realized?
|
24
|
+
start = Time.now
|
25
|
+
until promise.realized?
|
26
|
+
break if (Time.now - start) > TIMEOUT
|
27
|
+
sleep 0.01
|
29
28
|
end
|
30
|
-
user = promise.value
|
31
|
-
break if user
|
32
29
|
end
|
30
|
+
user = promise.value
|
33
31
|
end
|
34
32
|
if user
|
35
|
-
|
33
|
+
session_id = SecureRandom.uuid
|
34
|
+
session_cookie = "session=#{session_id}; SameSite=Strict; HttpOnly; Path=/; Max-Age=2592000#{'; Secure' if Isomorfeus.production?}"
|
35
|
+
session_cookie_accessor = SecureRandom.uuid
|
36
36
|
Isomorfeus.pub_sub_client.instance_variable_set(:@isomorfeus_user, user)
|
37
37
|
Isomorfeus.pub_sub_client.instance_variable_set(:@isomorfeus_authentication_tries, nil)
|
38
38
|
Isomorfeus.pub_sub_client.instance_variable_set(:@isomorfeus_session_cookie, session_cookie)
|
39
|
-
Isomorfeus.session_store.add(cookie: session_cookie, user: user)
|
40
|
-
response_agent.agent_result = { success: 'ok', data: user.to_transport,
|
39
|
+
Isomorfeus.session_store.add(session_id: session_id, cookie: session_cookie, user: user, accessor: session_cookie_accessor)
|
40
|
+
response_agent.agent_result = { success: 'ok', data: user.to_transport, session_cookie_accessor: session_cookie_accessor }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
elsif login_or_logout == 'ssr_login'
|
44
|
+
response_agent.agent_result = { error: 'Authentication failed' }
|
45
|
+
response_agent.request['ssr_login'].each_key do |session_id|
|
46
|
+
user = Isomorfeus.session_store.get_user(session_id: session_id)
|
47
|
+
if user
|
48
|
+
Isomorfeus.pub_sub_client.instance_variable_set(:@isomorfeus_user, user)
|
49
|
+
Isomorfeus.pub_sub_client.instance_variable_set(:@isomorfeus_authentication_tries, nil)
|
50
|
+
Isomorfeus.pub_sub_client.instance_variable_set(:@isomorfeus_session_cookie, nil)
|
51
|
+
response_agent.agent_result = { success: 'ok', data: user.to_transport }
|
41
52
|
end
|
42
53
|
end
|
43
54
|
elsif login_or_logout == 'logout'
|
@@ -12,12 +12,42 @@ module Isomorfeus
|
|
12
12
|
def call(env)
|
13
13
|
if env['PATH_INFO'] == Isomorfeus.api_websocket_path
|
14
14
|
if env['rack.upgrade?'] == :websocket
|
15
|
-
# TODO get session cookie
|
16
15
|
env['rack.upgrade'] = Isomorfeus::Transport::ServerSocketProcessor.new
|
17
16
|
end
|
18
17
|
WS_RESPONSE
|
18
|
+
elsif env['PATH_INFO'] == Isomorfeus.cookie_eater_path
|
19
|
+
cookie_accessor, new_path = env['QUERY_STRING'].split('=')
|
20
|
+
cookie = Isomorfeus.session_store.take_cookie(accessor: cookie_accessor)
|
21
|
+
if new_path.start_with?('/')
|
22
|
+
if cookie
|
23
|
+
[302, { 'Location' => new_path, 'Set-Cookie' => cookie }, ["Cookie eaten!"]]
|
24
|
+
else
|
25
|
+
[302, { 'Location' => new_path }, ["No Cookie!"]]
|
26
|
+
end
|
27
|
+
else
|
28
|
+
[404, {}, ["Must specify relative path!"]]
|
29
|
+
end
|
19
30
|
else
|
20
|
-
|
31
|
+
cookies = env['HTTP_COOKIE']
|
32
|
+
if cookies
|
33
|
+
cookies = cookies.split('; ')
|
34
|
+
cookie = cookies.detect { |c| c.start_with?('session=') }
|
35
|
+
if cookie
|
36
|
+
session_id = cookie[8..-1]
|
37
|
+
user = Isomorfeus.session_store.get_user(session_id: session_id)
|
38
|
+
if user
|
39
|
+
Thread.current[:isomorfeus_user] = user
|
40
|
+
Thread.current[:isomorfeus_session_id] = session_id
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
begin
|
45
|
+
result = @app.call(env)
|
46
|
+
ensure
|
47
|
+
Thread.current[:isomorfeus_user] = nil
|
48
|
+
Thread.current[:isomorfeus_session_id] = nil
|
49
|
+
end
|
50
|
+
result
|
21
51
|
end
|
22
52
|
end
|
23
53
|
end
|
@@ -45,10 +45,8 @@ module Isomorfeus
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def user(client)
|
48
|
-
# TODO get session cooke and load user from session
|
49
48
|
current_user = client.instance_variable_get(:@isomorfeus_user)
|
50
49
|
return current_user if current_user
|
51
|
-
# TODO get session cooke and load user from session
|
52
50
|
Anonymous.new
|
53
51
|
end
|
54
52
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Isomorfeus
|
2
|
+
module Transport
|
3
|
+
class SsrLogin
|
4
|
+
def self.init
|
5
|
+
session_id = `global.IsomorfeusSessionId`
|
6
|
+
if session_id && session_id.size > 0
|
7
|
+
Isomorfeus::Transport.promise_send_path('Isomorfeus::Transport::Handler::AuthenticationHandler', 'ssr_login', session_id).then do |agent|
|
8
|
+
if agent.processed
|
9
|
+
agent.result
|
10
|
+
else
|
11
|
+
agent.processed = true
|
12
|
+
if agent.response.key?(:success)
|
13
|
+
Isomorfeus.store.dispatch(type: 'DATA_LOAD', data: agent.response[:data])
|
14
|
+
class_name = agent.response[:data].keys.first
|
15
|
+
key = agent.response[:data][class_name].keys.first
|
16
|
+
logged_in_user = Isomorfeus.cached_data_class(class_name).new(key: key)
|
17
|
+
Isomorfeus.set_current_user(logged_in_user)
|
18
|
+
else
|
19
|
+
error = agent.response[:error]
|
20
|
+
Isomorfeus.raise_error(message: "SSR Login failed, #{error}!") # triggers .fail
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -10,11 +10,11 @@ module LucidAuthentication
|
|
10
10
|
def execute_login(&block)
|
11
11
|
end
|
12
12
|
|
13
|
-
def promise_login(user: nil, pass: nil, scheme: :isomorfeus)
|
14
|
-
|
13
|
+
def promise_login(user: nil, pass: nil, scheme: :isomorfeus, &block)
|
14
|
+
send("promise_authentication_with_#{scheme}", user: user, pass: pass, &block)
|
15
15
|
end
|
16
16
|
|
17
|
-
def promise_authentication_with_isomorfeus(user: nil, pass: nil)
|
17
|
+
def promise_authentication_with_isomorfeus(user: nil, pass: nil, &block)
|
18
18
|
if Isomorfeus.production?
|
19
19
|
Isomorfeus.raise_error(message: "Connection not secure, can't login") unless Isomorfeus::Transport.socket.url.start_with?('wss:')
|
20
20
|
else
|
@@ -29,12 +29,19 @@ module LucidAuthentication
|
|
29
29
|
Isomorfeus.store.dispatch(type: 'DATA_LOAD', data: agent.response[:data])
|
30
30
|
class_name = agent.response[:data].keys.first
|
31
31
|
key = agent.response[:data][class_name].keys.first
|
32
|
-
|
33
|
-
# TODO set session cookie
|
34
|
-
# agent.response[:session_cookie]
|
35
32
|
logged_in_user = Isomorfeus.cached_data_class(class_name).new(key: key)
|
36
|
-
|
37
|
-
|
33
|
+
cookie_accessor = agent.response[:session_cookie_accessor]
|
34
|
+
begin
|
35
|
+
target = if block_given?
|
36
|
+
block.call(logged_in_user)
|
37
|
+
else
|
38
|
+
`window.location.pathname`
|
39
|
+
end
|
40
|
+
rescue
|
41
|
+
target = `window.location.pathname`
|
42
|
+
end
|
43
|
+
cookie_query = "#{Isomorfeus.cookie_eater_path}?#{cookie_accessor}=#{target}"
|
44
|
+
`window.location = cookie_query` # doing page load and redirect
|
38
45
|
else
|
39
46
|
error = agent.response[:error]
|
40
47
|
`console.err(error)` if error
|
@@ -52,9 +59,9 @@ module LucidAuthentication
|
|
52
59
|
|
53
60
|
def promise_deauthentication_with_isomorfeus
|
54
61
|
Isomorfeus::Transport.promise_send_path('Isomorfeus::Transport::Handler::AuthenticationHandler', 'logout', 'logout').then do |agent|
|
55
|
-
|
56
|
-
# agent.response[:session_cookie]
|
62
|
+
`document.cookie = "session="`
|
57
63
|
Isomorfeus.set_current_user(nil)
|
64
|
+
Isomorfeus.force_init_store!
|
58
65
|
agent.processed = true
|
59
66
|
agent.response.key?(:success) ? true : raise('Logout failed!')
|
60
67
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: isomorfeus-transport
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.
|
4
|
+
version: 1.0.0.zeta17
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jan Biedermann
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-02-
|
11
|
+
date: 2020-02-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -100,28 +100,28 @@ dependencies:
|
|
100
100
|
requirements:
|
101
101
|
- - ">="
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: 16.12.
|
103
|
+
version: 16.12.18
|
104
104
|
type: :runtime
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: 16.12.
|
110
|
+
version: 16.12.18
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: isomorfeus-policy
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - '='
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: 1.0.0.
|
117
|
+
version: 1.0.0.zeta17
|
118
118
|
type: :runtime
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - '='
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: 1.0.0.
|
124
|
+
version: 1.0.0.zeta17
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: websocket-driver
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -142,14 +142,14 @@ dependencies:
|
|
142
142
|
requirements:
|
143
143
|
- - '='
|
144
144
|
- !ruby/object:Gem::Version
|
145
|
-
version: 1.0.0.
|
145
|
+
version: 1.0.0.zeta17
|
146
146
|
type: :development
|
147
147
|
prerelease: false
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
150
150
|
- - '='
|
151
151
|
- !ruby/object:Gem::Version
|
152
|
-
version: 1.0.0.
|
152
|
+
version: 1.0.0.zeta17
|
153
153
|
- !ruby/object:Gem::Dependency
|
154
154
|
name: opal-webpack-loader
|
155
155
|
requirement: !ruby/object:Gem::Requirement
|
@@ -204,6 +204,7 @@ files:
|
|
204
204
|
- lib/isomorfeus/transport.rb
|
205
205
|
- lib/isomorfeus/transport/client_processor.rb
|
206
206
|
- lib/isomorfeus/transport/config.rb
|
207
|
+
- lib/isomorfeus/transport/dbm_session_store.rb
|
207
208
|
- lib/isomorfeus/transport/handler/authentication_handler.rb
|
208
209
|
- lib/isomorfeus/transport/middlewares.rb
|
209
210
|
- lib/isomorfeus/transport/rack_middleware.rb
|
@@ -211,7 +212,7 @@ files:
|
|
211
212
|
- lib/isomorfeus/transport/response_agent.rb
|
212
213
|
- lib/isomorfeus/transport/server_processor.rb
|
213
214
|
- lib/isomorfeus/transport/server_socket_processor.rb
|
214
|
-
- lib/isomorfeus/transport/
|
215
|
+
- lib/isomorfeus/transport/ssr_login.rb
|
215
216
|
- lib/isomorfeus/transport/version.rb
|
216
217
|
- lib/isomorfeus/transport/websocket.rb
|
217
218
|
- lib/lucid_authentication/mixin.rb
|
@@ -1,20 +0,0 @@
|
|
1
|
-
module Isomorfeus
|
2
|
-
module Transport
|
3
|
-
class ThreadSessionStore
|
4
|
-
|
5
|
-
def add(cookie:, user:)
|
6
|
-
store[cookie] = user
|
7
|
-
end
|
8
|
-
|
9
|
-
def remove(cookie:)
|
10
|
-
store.delete(cookie)
|
11
|
-
end
|
12
|
-
|
13
|
-
private
|
14
|
-
|
15
|
-
def store
|
16
|
-
Thread.current[:isomorfeus_session_store] ||= {}
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|