wikk_web_auth 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.txt +20 -0
- data/lib/wikk_web_auth.rb +199 -106
- 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: 671e30332d7611b59813c740329597c67743e6dfb1d14f5624b0d2f048f735ed
|
4
|
+
data.tar.gz: 370ae2207160bb1d6b7304c2451cdf9de71ea0f0da2e760e60642c9f3a8c822b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 80f9e4d1c65fdd6d96f35399ba86fa2a11ff09a505bfa8154fc6f0f3f464bb1ec9b4f5697655822439e7523cde7da2c4dddc210e78aeaeca690d499c04231cfa
|
7
|
+
data.tar.gz: 874afd4511eae12ece2931f7bce38bcb991ae6ae76660d30c53e3aa2254660fa778d3d31eed573e33b66d9dd23d3ed7cf19da263ea1f52c554ba4647c0b75cc8
|
data/History.txt
CHANGED
@@ -1,3 +1,23 @@
|
|
1
|
+
robertburrowes Sat Apr 15 16:18:34 2023 +1200
|
2
|
+
deleted an end in error
|
3
|
+
robertburrowes Sat Apr 15 16:05:26 2023 +1200
|
4
|
+
removed the syslogs. Getting odd errors, depending on the context.
|
5
|
+
robertburrowes Sat Apr 15 15:53:04 2023 +1200
|
6
|
+
factor out code into new_session() Clean up old cookie entries in cgi instance.
|
7
|
+
robertburrowes Sat Apr 15 15:49:37 2023 +1200
|
8
|
+
more output from the tests
|
9
|
+
robertburrowes Wed Apr 12 18:31:54 2023 +1200
|
10
|
+
Add test for authenticated on a reconnect Add test for trying to reauthenticate, by sending a previous response.
|
11
|
+
robertburrowes Wed Apr 12 18:30:25 2023 +1200
|
12
|
+
Initialize instance vars earlier @log.error now failing. Replaced with full call, using LOG_NOTICE session and @session mix up Explicitly set no_cookies and no_hidden to false (should be default)
|
13
|
+
robertburrowes Tue Apr 11 17:56:27 2023 +1200
|
14
|
+
bumped the version
|
15
|
+
robertburrowes Tue Apr 11 17:56:01 2023 +1200
|
16
|
+
Added test/direct_test.rb Cleaned up test, moving conf files into test/conf Created test/conf/pstore for the pstore temp files (which need cleaning out after the test)
|
17
|
+
robertburrowes Tue Apr 11 15:06:47 2023 +1200
|
18
|
+
refactor: Bump version Set return_url globally Initialize @session globally Separate generating challenge into its own method (for new rpc) Optionally call to authencate in initialize (for new rpc) Added check for the username changing during login. Fail authorized step, if challenge not set (i.e. we jumped straight to step 2. nil cgi params get converted to '' seed now reset, if authorization fails. Authorized? should have been private session_state_init should have been private
|
19
|
+
robertburrowes Sun Apr 9 17:57:33 2023 +1200
|
20
|
+
not used
|
1
21
|
robertburrowes Wed Mar 29 22:03:06 2023 +1300
|
2
22
|
Test against the new lib version, not the gem
|
3
23
|
robertburrowes Wed Mar 29 22:02:44 2023 +1300
|
data/lib/wikk_web_auth.rb
CHANGED
@@ -3,25 +3,30 @@ module WIKK
|
|
3
3
|
require 'cgi/session'
|
4
4
|
require 'cgi/session/pstore' # provides CGI::Session::PStore
|
5
5
|
require 'digest/sha2'
|
6
|
-
require '
|
7
|
-
require 'wikk_aes_256'
|
6
|
+
require 'securerandom'
|
8
7
|
require 'wikk_password'
|
9
8
|
|
10
9
|
# Provides common authentication mechanism for all our cgis.
|
10
|
+
# Uses standard cgi parameters, unless overridden e.g. cgi?user=x&response=y
|
11
|
+
# Returns values imbedded as hidden fields in the login form
|
11
12
|
# @attr_reader [String] user , the remote user's user name
|
12
13
|
# @attr_reader [String] session , the persistent Session record for this user
|
13
14
|
class Web_Auth
|
14
|
-
VERSION = '0.1.
|
15
|
+
VERSION = '0.1.6' # Gem version
|
15
16
|
|
16
|
-
attr_reader :user, :
|
17
|
+
attr_reader :user, :challenge
|
18
|
+
attr_accessor :response
|
17
19
|
|
18
20
|
# Create new Web_Auth instance, and proceed through authentication process by creating a login web form, if the user isn't authenticated.
|
19
21
|
# @param cgi [CGI] Which carries the client data, cookies, and PUT/POST form data.
|
20
22
|
# @param pwd_config [WIKK::Configuration|Hash] the location of the password file is embedded here.
|
23
|
+
# @param user [String] overrides cgi['user']
|
24
|
+
# @param response [String] overrides cgi['response']
|
25
|
+
# @param user_logout [Boolean] overrides cgi['logout']
|
21
26
|
# @param pstore_config [Hash] overrides default pstore settings
|
22
27
|
# @param return_url [String] If we successfully authenticate, return here.
|
23
28
|
# @return [WIKK::Web_Auth]
|
24
|
-
def initialize(cgi, pwd_config = nil, return_url = nil, pstore_config: nil)
|
29
|
+
def initialize(cgi, pwd_config = nil, return_url = nil, user: nil, response: nil, user_logout: false, pstore_config: nil, run_auth: true)
|
25
30
|
if pwd_config.instance_of?(Hash)
|
26
31
|
sym = pwd_config.each_with_object({}) { |(k, v), h| h[k.to_sym] = v }
|
27
32
|
@config = Struct.new(*(k = sym.keys)).new(*sym.values_at(*k))
|
@@ -31,14 +36,56 @@ module WIKK
|
|
31
36
|
|
32
37
|
@cgi = cgi
|
33
38
|
@pstore_config = pstore_config
|
34
|
-
|
35
|
-
|
39
|
+
|
40
|
+
# Set variables from the method's params, or alternately, from the CGI params
|
41
|
+
@user = user.nil? ? cgi_param('Username') : user
|
42
|
+
@response = response.nil? ? cgi_param('Response') : response
|
43
|
+
@return_url = return_url.nil? ? cgi_param('ReturnURL') : return_url
|
44
|
+
|
45
|
+
# Look for existing session, but don't start a new one.
|
36
46
|
begin
|
37
|
-
@
|
38
|
-
rescue
|
39
|
-
@
|
47
|
+
@session = CGI::Session.new(@cgi, Web_Auth.session_config( { 'new_session' => false }, pstore_config: @pstore_config ))
|
48
|
+
rescue ArgumentError => _e # if no old session
|
49
|
+
@session = nil
|
50
|
+
rescue Exception => e # rubocop:disable Lint/RescueException In CGI, we want to handle every exception
|
51
|
+
raise e.class, 'Authenticate, CGI::Session.new ' + e.message
|
52
|
+
end
|
53
|
+
|
54
|
+
if @session.nil?
|
55
|
+
@challenge = '' # there is no current challenge
|
56
|
+
elsif @session['session_expires'].nil? || # Shouldn't be the case
|
57
|
+
@session['session_expires'] < Time.now || # Session has expired
|
58
|
+
@session['ip'] != @cgi.remote_addr || # Not coming from same IP address
|
59
|
+
# @session['user'] != @user || # Not the same user
|
60
|
+
cgi_param('logout') != '' || # Requested a logout
|
61
|
+
user_logout # Alternate way to request a logout
|
62
|
+
logout
|
63
|
+
else
|
64
|
+
# We ignore the cgi['Challenge'] value, and always get this from the pstore
|
65
|
+
@challenge = @session['seed'] # Recover the challenge from the pstore entry. It may be ''
|
66
|
+
end
|
67
|
+
|
68
|
+
authenticate if run_auth # This generates html output, so it is now conditionally run.
|
69
|
+
end
|
70
|
+
|
71
|
+
# Debug dump of session keys
|
72
|
+
def session_to_s
|
73
|
+
return '' if @session.nil?
|
74
|
+
|
75
|
+
s = '{'
|
76
|
+
[ 'auth', 'seed', 'ip', 'user', 'session_expires' ].each do |k|
|
77
|
+
s += "'#{k}':'#{@session[k]}', "
|
40
78
|
end
|
41
|
-
|
79
|
+
s += '}'
|
80
|
+
return s
|
81
|
+
end
|
82
|
+
|
83
|
+
# expose the session_id. This is also returned by modifying the cgi instance passed in to initialize
|
84
|
+
# * The cgi.output_cookies Array of Cookies gets modified if no_cookies is false (the default)
|
85
|
+
# * And cgi.output_hidden Hash get modified if no_hidden is false (the default)
|
86
|
+
# @return [String] random session id
|
87
|
+
def session_id
|
88
|
+
@session.nil? ? '' : @session.session_id
|
42
89
|
end
|
43
90
|
|
44
91
|
# way of checking without doing a full login sequence.
|
@@ -48,52 +95,39 @@ module WIKK
|
|
48
95
|
def self.authenticated?(cgi, pstore_config: nil )
|
49
96
|
begin
|
50
97
|
session = CGI::Session.new(cgi, Web_Auth.session_config( { 'new_session' => false }, pstore_config: pstore_config ) )
|
51
|
-
authenticated = (session != nil && session['session_expires'] > Time.now && session['auth'] == true && session['ip'] == cgi.remote_addr)
|
52
|
-
session.close #
|
98
|
+
authenticated = (session != nil && !session['session_expires'].nil? && session['session_expires'] > Time.now && session['auth'] == true && session['ip'] == cgi.remote_addr)
|
99
|
+
session.close # Tidy up, so we don't leak file descriptors
|
53
100
|
return authenticated
|
54
|
-
rescue ArgumentError =>
|
55
|
-
begin
|
56
|
-
@log = Syslog::Logger.syslog
|
57
|
-
rescue StandardError
|
58
|
-
@log = Syslog::Logger.new('wikk_web_auth')
|
59
|
-
end
|
60
|
-
@log.error(e.message)
|
101
|
+
rescue ArgumentError => _e # if no old session to find.
|
61
102
|
return false
|
62
103
|
end
|
63
104
|
end
|
64
105
|
|
106
|
+
# Test to see if user authenticated.
|
107
|
+
# If this is the only call, then follow this with close_session()
|
108
|
+
# @return [Boolean] True, if this session is authenticated
|
109
|
+
def authenticated?
|
110
|
+
@session != nil && !@session['session_expires'].nil? && @session['session_expires'] > Time.now && @session['auth'] == true && @session['ip'] == @cgi.remote_addr
|
111
|
+
end
|
112
|
+
|
65
113
|
# get the session reference and delete the session.
|
66
114
|
# @param pstore_config [Hash] overrides default pstore settings
|
67
115
|
# @param cgi [CGI] Which carries the client data, cookies, and PUT/POST form data.
|
68
116
|
def self.logout(cgi, pstore_config: nil)
|
69
117
|
begin
|
70
118
|
session = CGI::Session.new(cgi, Web_Auth.session_config( { 'new_session' => false }, pstore_config: pstore_config ))
|
71
|
-
session.delete
|
72
|
-
rescue ArgumentError =>
|
73
|
-
|
74
|
-
@log = Syslog::Logger.syslog
|
75
|
-
rescue StandardError
|
76
|
-
@log = Syslog::Logger.new('wikk_web_auth')
|
77
|
-
end
|
78
|
-
@log.error(e.message)
|
119
|
+
session.delete unless session.nil? # Also closes the session
|
120
|
+
rescue ArgumentError => _e # if no old session
|
121
|
+
# Not an error.
|
79
122
|
end
|
80
123
|
end
|
81
124
|
|
82
|
-
#
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
begin
|
89
|
-
return WIKK::Password.valid_sha256_response?(user, @pwd_config, challenge, received_hash)
|
90
|
-
rescue IndexError => e # User didn't exist
|
91
|
-
@log.error("authorized?(#{user}) User not found: " + e.message)
|
92
|
-
return false
|
93
|
-
rescue Exception => e # rubocop:disable Lint/RescueException # In a cgi, we want to log all errors.
|
94
|
-
@log.error("authorized?(#{user}): " + e.message)
|
95
|
-
return false
|
96
|
-
end
|
125
|
+
# clean up the session, deleting the session state.
|
126
|
+
def logout
|
127
|
+
@session.delete unless @session.nil? # Will close the existing session
|
128
|
+
@session = nil
|
129
|
+
@challenge = '' # no current session, so no challenge string
|
130
|
+
clear_cgi_cookies
|
97
131
|
end
|
98
132
|
|
99
133
|
# Generate the new Session's config parameters, mixing in and/or overriding the preset values.
|
@@ -104,100 +138,105 @@ module WIKK
|
|
104
138
|
instance_of?(Hash)
|
105
139
|
session_conf = {
|
106
140
|
'database_manager' => CGI::Session::PStore, # use PStore
|
107
|
-
'session_key' => '_wikk_rb_sess_id',
|
108
|
-
'session_expires' => (Time.now + 86400),
|
109
|
-
'prefix' => 'pstore_sid_',
|
141
|
+
'session_key' => '_wikk_rb_sess_id', # custom session key
|
142
|
+
'session_expires' => (Time.now + 86400), # 1 day timeout
|
143
|
+
'prefix' => 'pstore_sid_', # Prefix for pstore file
|
144
|
+
# 'suffix' => ?
|
110
145
|
'tmpdir' => '/tmp', # PStore option. Under Apache2, this is a private namespace /tmp
|
111
|
-
'session_path' => '/'
|
112
|
-
# 'session_id' => ?, # Created for new sessions. Merged in for existing sessions
|
146
|
+
'session_path' => '/', # The cookie gets returned for URLs starting with this path
|
113
147
|
# 'new_session' => true, # Default, is to create a new session if it doesn't already exist
|
114
|
-
# 'no_hidden' => ?,
|
115
148
|
# 'session_domain' => ?,
|
116
149
|
# 'session_secure' => ?,
|
117
|
-
# '
|
118
|
-
|
150
|
+
# 'session_id' => ?, # Created for new sessions. Merged in for existing sessions
|
151
|
+
'no_cookies' => false, # boolean. Do fill in cgi output_cookies array of Cookies
|
152
|
+
'no_hidden' => false # boolean fill in the cgi output_hidden Hash key=cookie, value=session_id
|
119
153
|
}
|
120
154
|
session_conf.merge!(pstore_config) if pstore_config.instance_of?(Hash)
|
121
155
|
session_conf.merge!(extra_arguments) if extra_arguments.instance_of?(Hash)
|
122
156
|
return session_conf
|
123
157
|
end
|
124
158
|
|
125
|
-
|
126
|
-
|
159
|
+
# Generate a challenge, as step 1 of a login
|
160
|
+
# If this is the only call, then follow this with close_session()
|
161
|
+
def gen_challenge
|
162
|
+
# Short session, which gets replaced if we successfully authenticate
|
163
|
+
new_session( { 'session_expires' => Time.now + 120 } )
|
164
|
+
raise 'gen_challenge: @session == nil' if @session.nil?
|
165
|
+
|
166
|
+
@challenge = SecureRandom.base64(32)
|
167
|
+
# Store the challenge in the pstore, ready for the 2nd login step, along with browser details
|
168
|
+
session_state_init('auth' => false, 'seed' => @challenge, 'ip' => @cgi.remote_addr, 'user' => @user, 'session_expires' => @session_options['session_expires'])
|
169
|
+
@session.update
|
170
|
+
return @challenge
|
171
|
+
end
|
172
|
+
|
173
|
+
# Test the response against the password file
|
174
|
+
# If this is the only call, then follow this with close_session()
|
175
|
+
# @return [Boolean] We got authorized
|
176
|
+
def valid_response?
|
177
|
+
if authorized?
|
178
|
+
# We got a challenge string, so we are on step 2 of the authentication
|
179
|
+
# And have passed the password check ( authorized?() )
|
180
|
+
new_session # regenerate the cookie with a longer lifetime.
|
181
|
+
raise 'valid_response?: @session == nil' if @session.nil?
|
182
|
+
|
183
|
+
session_state_init('auth' => true, 'seed' => '', 'ip' => @cgi.remote_addr, 'user' => @user, 'session_expires' => @session_options['session_expires'])
|
184
|
+
@session.update # Should also update on close, which we probably do next
|
185
|
+
return true
|
186
|
+
else # Failed to authorize. The temporary challenge session cookie is no longer valid.
|
187
|
+
logout
|
188
|
+
return false
|
189
|
+
end
|
127
190
|
end
|
128
191
|
|
129
192
|
# Test to see if we are already authenticated, and if not, generate an HTML login page.
|
130
|
-
# @param return_url [String] We return here if we sucessfully login
|
193
|
+
# @param return_url [String] We return here if we sucessfully login. Overrides initialize value
|
131
194
|
def authenticate(return_url = nil)
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
raise e.class, 'Authenticate, CGI::Session.new ' + e.message
|
195
|
+
@return_url = return_url unless return_url.nil? # Update the return url (Backward compatibility)
|
196
|
+
|
197
|
+
# We have no session setup, or haven't sent the challenge yet.
|
198
|
+
# So we are at step 1 of the authentication
|
199
|
+
if @session.nil? || @challenge == ''
|
200
|
+
gen_html_login_page(message: 'no current challenge')
|
201
|
+
return
|
140
202
|
end
|
141
203
|
|
204
|
+
# We are now at step 2, expecting a response to the challenge
|
142
205
|
begin
|
143
|
-
|
206
|
+
# Might be a while since we initialized the class, so repeat this test
|
207
|
+
@session['auth'] = false if @session['session_expires'].nil? || # Shouldn't ever happen, but has
|
144
208
|
@session['session_expires'] < Time.now || # Session has expired
|
145
|
-
@session['ip'] != @cgi.remote_addr ||
|
146
|
-
|
209
|
+
@session['ip'] != @cgi.remote_addr # || # Not coming from same IP address
|
210
|
+
# @session['user'] != @user # Username not the same as the session
|
147
211
|
|
148
212
|
return if @session['auth'] == true # if this is true, then we have already authenticated this session.
|
149
213
|
|
150
|
-
|
151
|
-
|
152
|
-
response = CGI.escapeHTML(@cgi['Response'])
|
153
|
-
if @user != '' && response != '' && authorized?(@user, challenge, response)
|
154
|
-
@session['auth'] = true # Response valid.
|
155
|
-
@session['user'] = @user
|
156
|
-
@session['ip'] = @cgi.remote_addr
|
157
|
-
@session['seed'] = '' # Don't use the same one twice.
|
158
|
-
@session.close
|
159
|
-
return
|
160
|
-
end
|
214
|
+
unless valid_response?
|
215
|
+
gen_html_login_page(message: 'invalid response:')
|
161
216
|
end
|
162
|
-
|
163
|
-
@session.delete # Start a new session.
|
164
|
-
gen_html_login_page(return_url)
|
165
|
-
@session.close if @session != nil # Saves the session state.
|
217
|
+
@session.close unless @session.nil? # Saves the session state.
|
166
218
|
rescue Exception => e # rubocop:disable Lint/RescueException
|
167
|
-
@log.error("authenticate(#{@session}): #{e.message}")
|
168
219
|
raise e.class, 'Authenticate, CGI::Session.new ' + e.message
|
169
220
|
end
|
170
221
|
end
|
171
222
|
|
172
|
-
#
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
# Test to see if user authenticated,
|
178
|
-
# @return [Boolean] i.e @authenticated's value.
|
179
|
-
def authenticated?
|
180
|
-
@session != nil && @session['session_expires'] > Time.now && @session['auth'] == true && session['ip'] == @cgi.remote_addr
|
223
|
+
# Ensure we don't consume all file descriptors
|
224
|
+
# Call after last call (though most calls do close the session)
|
225
|
+
def close_session
|
226
|
+
@session.close unless @session.nil?
|
227
|
+
@session = nil
|
181
228
|
end
|
182
229
|
|
183
230
|
# Used by calling cgi to generate a standard login page
|
184
|
-
|
185
|
-
|
186
|
-
session_options = Web_Auth.session_config( pstore_config: @pstore_config )
|
187
|
-
@session = CGI::Session.new(@cgi, session_options ) # Start a new session for future authentications.
|
188
|
-
|
189
|
-
raise 'gen_html_login_page: @session == nil' if @session.nil?
|
190
|
-
|
191
|
-
challenge = WIKK::AES_256.gen_key_to_s
|
192
|
-
session_state_init('auth' => false, 'seed' => challenge, 'ip' => @cgi.remote_addr, 'session_expires' => session_options['session_expires'])
|
231
|
+
def gen_html_login_page(message: '')
|
232
|
+
gen_challenge
|
193
233
|
@cgi.header('type' => 'text/html')
|
194
234
|
@cgi.out do
|
195
235
|
@cgi.html do
|
196
236
|
@cgi.head { @cgi.title { 'login' } + html_nocache + html_script } +
|
197
|
-
@cgi.body { html_login_form(
|
237
|
+
@cgi.body { html_login_form(message: message) + "\n" }
|
198
238
|
end
|
199
239
|
end
|
200
|
-
@session.update
|
201
240
|
end
|
202
241
|
|
203
242
|
# Used by calling cgi to inject a return URL into the html response.
|
@@ -223,6 +262,59 @@ module WIKK
|
|
223
262
|
HTML
|
224
263
|
end
|
225
264
|
|
265
|
+
# Get a CGI param
|
266
|
+
# @param key [String] name of the CGI param
|
267
|
+
# @return [String] Either the value, or ''
|
268
|
+
private def cgi_param(key)
|
269
|
+
value = @cgi[key]
|
270
|
+
return value.nil? ? '' : CGI.escapeHTML(value)
|
271
|
+
end
|
272
|
+
|
273
|
+
# Short hand for set up of the pstore session entry
|
274
|
+
# @param session_options [Hash] key pairs for the pstore session
|
275
|
+
private def session_state_init(session_options = {})
|
276
|
+
session_options.each { |k, v| @session[k] = v }
|
277
|
+
end
|
278
|
+
|
279
|
+
# Blat the session cookies, that would have been sent back to the server
|
280
|
+
private def clear_cgi_cookies
|
281
|
+
# Update the cgi record, removing the cookies
|
282
|
+
@cgi.instance_eval do
|
283
|
+
@output_hidden = {}
|
284
|
+
@output_cookies = []
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
# Create a new session in the pstore, having deleted any existing session.
|
289
|
+
# @param session_params [Hash] Optionally alter the session params
|
290
|
+
private def new_session(session_params = nil)
|
291
|
+
@session.delete unless @session.nil? # Closes and Deletes the existing session
|
292
|
+
clear_cgi_cookies
|
293
|
+
# Start a new session for future authentications.
|
294
|
+
# This resets the expiry timestamp
|
295
|
+
@session_options = Web_Auth.session_config( session_params, pstore_config: @pstore_config )
|
296
|
+
@session = CGI::Session.new(@cgi, @session_options )
|
297
|
+
end
|
298
|
+
|
299
|
+
# Checks password file to see if the response from the user matches generating a hash from the password locally.
|
300
|
+
# @param user [String] Who the remote user claims to be
|
301
|
+
# @param challenge [String] Random string we sent to this user, and they used in hashing their password.
|
302
|
+
# @param response [String] The hex_SHA256(password + challenge) string that the user sent back.
|
303
|
+
# @return [Boolean] True for authorization test suceeded.
|
304
|
+
private def authorized?
|
305
|
+
begin
|
306
|
+
unless @session.nil? ||
|
307
|
+
@challenge.nil? || @challenge == '' ||
|
308
|
+
@user.nil? || @user.empty? ||
|
309
|
+
@response.nil? || @response.empty?
|
310
|
+
return WIKK::Password.valid_sha256_response?(@user, @pwd_config, @challenge, @response)
|
311
|
+
end
|
312
|
+
rescue IndexError => _e # User didn't exist
|
313
|
+
# Not an error.
|
314
|
+
end
|
315
|
+
return false
|
316
|
+
end
|
317
|
+
|
226
318
|
# Login form javascript helper to SHA256 Hash a password and the challenge string sent by the server.
|
227
319
|
# @return [String] Javascript to embed in html response.
|
228
320
|
private def html_script
|
@@ -246,16 +338,17 @@ module WIKK
|
|
246
338
|
# Generate html login form.
|
247
339
|
# @param user [String] user's login name.
|
248
340
|
# @param challenge [String] Random bytes to add to password, before sending back to server.
|
249
|
-
# @param return_url [String]
|
341
|
+
# @param return_url [String] We return here if we sucessfully login. Overrides initialize value
|
250
342
|
# @return [String] Login form to embed in html response to user.
|
251
|
-
private def html_login_form(
|
343
|
+
private def html_login_form(message: '')
|
252
344
|
<<~HTML
|
253
345
|
<form NAME="login" ACTION="/ruby/login.rbx" METHOD="post">
|
254
|
-
<input TYPE="hidden" NAME="Challenge" VALUE="#{challenge}">
|
346
|
+
<input TYPE="hidden" NAME="Challenge" VALUE="#{@challenge}">
|
255
347
|
<input TYPE="hidden" NAME="Response" VALUE="">
|
256
|
-
<input TYPE="hidden" NAME="ReturnURL" VALUE="#{return_url}">
|
348
|
+
<input TYPE="hidden" NAME="ReturnURL" VALUE="#{@return_url}">
|
349
|
+
<span hidden>#{message}</span>
|
257
350
|
<table>
|
258
|
-
<tr><th>User name</th><td><input TYPE="text" NAME="Username" VALUE="#{user}" SIZE="32" MAXLENGTH="32"></td></tr>
|
351
|
+
<tr><th>User name</th><td><input TYPE="text" NAME="Username" VALUE="#{@user}" SIZE="32" MAXLENGTH="32"></td></tr>
|
259
352
|
<tr><th>Password</th><td><input TYPE="password" NAME="Password" VALUE="" SIZE="32" MAXLENGTH="32"></td></tr>
|
260
353
|
<tr><td> </td><td>
|
261
354
|
<input ONCLICK="sendhash(); return false;" TYPE="submit" NAME="login" VALUE="Login">
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wikk_web_auth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rob Burrowes
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-04-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: wikk_password
|