Class: WIKK::Web_Auth

Inherits:
Object
  • Object
show all
Defined in:
lib/wikk_web_auth.rb

Overview

Provides common authentication mechanism for all our cgis.

@attr_reader [String] user , the remote user's user name 
@attr_reader [String] session , the persistent Session record for this user

Constant Summary collapse

VERSION =

Gem version

"0.1.2"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(cgi, config, return_url = nil) ⇒ Web_Auth

Create new Web_Auth instance, and proceed through authentication process by creating a login web form, if the user isn’t authenticated.

@param cgi [CGI] Which carries the client data, cookies, and PUT/POST form data.
@param config [WIKK::Configuration|Hash] the location of the password file is embedded here.
@param return_url [String] If we successfully authenticate, return here.
@return [WIKK::Web_Auth]


23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/wikk_web_auth.rb', line 23

def initialize(cgi, config, return_url = nil)
  if config.class == Hash
    sym = config.each_with_object({}) { |(k,v),h| h[k.to_sym] = v }
    @config = Struct.new(*(k = sym.keys)).new(*sym.values_at(*k))
  else
	  @config = config
	end
 @cgi = cgi
  @user = ''
  @session = nil
 begin
    @log = Syslog::Logger.syslog
  rescue
    @log = Syslog::Logger.new("authlib.rbx")
  end
  authenticate(return_url) 
end

Instance Attribute Details

#sessionObject (readonly)

Returns the value of attribute session.



16
17
18
# File 'lib/wikk_web_auth.rb', line 16

def session
  @session
end

#userObject (readonly)

Returns the value of attribute user.



16
17
18
# File 'lib/wikk_web_auth.rb', line 16

def user
  @user
end

Class Method Details

.authenticated?(cgi) ⇒ Boolean

way of checking without doing a full login sequence.

@param cgi [CGI] Which carries the client data, cookies, and PUT/POST form data.
@return [Boolean] authenticated == true.

Returns:

  • (Boolean)


44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/wikk_web_auth.rb', line 44

def self.authenticated?(cgi)
  begin
      session = CGI::Session.new(cgi, Web_Auth.session_config({'new_session' => false}) )
      authenticated = (session != nil && session['session_expires'] > Time.now && session['auth'] == true && session['ip'] == cgi.remote_addr)
      session.close #Writes back the session data
      return authenticated
  rescue ArgumentError => error # if no old session to find.
	  begin
      @log = Syslog::Logger.syslog
    rescue
      @log = Syslog::Logger.new("authlib.rbx")
    end
    @log.error(error.message)
    return false
  end
end

.logout(cgi) ⇒ Object

get the session reference and delete the session.

@param cgi [CGI] Which carries the client data, cookies, and PUT/POST form data.


63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/wikk_web_auth.rb', line 63

def self.logout(cgi)
  begin
      session = CGI::Session.new(cgi, Web_Auth.session_config({'new_session' => false}))
      session.delete if session != nil
  rescue ArgumentError => error # if no old session
	  begin
      @log = Syslog::Logger.syslog
    rescue
      @log = Syslog::Logger.new("authlib.rbx")
    end
    @log.error(error.message)
  end
end

.session_config(extra_arguments = {}) ⇒ Object

Generate the new Session’s config parameters, mixing in and/or overriding the preset values.

@param extra_arguments [Hash] Extra arguments that get added to the hash, or override values with the same key.
@return [Hash] The configuration hash.


97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/wikk_web_auth.rb', line 97

def self.session_config(extra_arguments = {})
  return {
    'database_manager' => CGI::Session::PStore,  # use PStore
    'session_key' => '_wikk_rb_sess_id',              # custom session key
    #'session_id' => ?,
    'session_expires' => (Time.now + 86400),     # 1 day timeout
    'prefix' => 'pstore_sid_',  # PStore option
    'tmpdir' => '/tmp',  # PStore option
    #new_session => ?,#boolean
    #no_hidden => ?,
    #session_domain => ?,
    #session_secure => ?,
    #session_path => ?,
    #no_cookies => ?, #boolean
    #suffix => ?
  }.merge(extra_arguments)
end

Instance Method Details

#authenticate(return_url = nil) ⇒ Object

Test to see if we are already authenticated, and if not, generate an HTML login page.

@param return_url [String] We return here if we sucessfully login


121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/wikk_web_auth.rb', line 121

def authenticate(return_url = nil)
  begin
    @session = CGI::Session.new(@cgi, Web_Auth.session_config({'new_session' => false})) #Look for existing session.
    return (return_url) if @session == nil
  rescue ArgumentError => error # if no old session
    return (return_url)
  rescue Exception => error
    raise Exception, "Authenticate, CGI::Session.new " + error.message
  end
  
  @session['auth'] = false if @session['session_expires'] < Time.now || #Session has expired
                              @session['ip'] != @cgi.remote_addr || #Not coming from same IP address
                              CGI::escapeHTML(@cgi['logout']) != '' #Are trying to logout
                              
  return if(@session['auth'] == true) #if this is true, then we have already authenticated this session.       

  if (challenge = @session['seed']) != '' #see if we are looking at a login response.
    @user = CGI::escapeHTML(@cgi['Username'])
    response = CGI::escapeHTML(@cgi['Response'])
    if  @user != '' && response != '' && authorized?(@user, challenge, response)
      @session['auth'] = true #Response valid.
      @session['user'] = @user
      @session['ip'] = @cgi.remote_addr
      @session['seed'] = '' #Don't use the same one twice.
      @session.close 
      return
    end
  end

  @session.delete #Start a new session.
  (return_url)
  @session.close if @session != nil #Saves the session state.
end

#authenticated?Boolean

Test to see if user authenticated,

@return [Boolean] i.e @authenticated's value.

Returns:

  • (Boolean)


162
163
164
# File 'lib/wikk_web_auth.rb', line 162

def authenticated?
  @session != nil && @session['session_expires'] > Time.now && @session['auth'] == true && session['ip'] == @cgi.remote_addr
end

#authorized?(user, challenge, received_hash) ⇒ Boolean

Checks password file to see if the response from the user matches generating a hash from the password locally.

@param user [String] Who the remote user claims to be
@param challenge [String] Random string we sent to this user, and they used in hashing their password.
@param received_hash [String] The hex_SHA256(password + challenge) string that the user sent back.
@return [Boolean] True for authorization test suceeded.

Returns:

  • (Boolean)


82
83
84
85
86
87
88
89
90
91
92
# File 'lib/wikk_web_auth.rb', line 82

def authorized?(user, challenge, received_hash)
 begin
   return WIKK::Password.valid_sha256_response?(user, @config, challenge, received_hash)
 rescue IndexError => error #User didn't exist
   @log.err("authorized?(#{user}): " + error.message)
   return false
 rescue Exception => error #Something else
   @log.err("authorized?(#{user}): " + error.message)
   return false
 end
end

#gen_html_login_page(return_url = nil) ⇒ Object

Used by calling cgi to generate a standard login page

@param return_url [String] We return here if we sucessfully login


169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/wikk_web_auth.rb', line 169

def (return_url = nil)
  session_options = Web_Auth.session_config()
  @session = CGI::Session.new(@cgi, session_options) #Start a new session for future authentications.
  raise "gen_html_login_page: @session == nil" if @session == nil
  challenge = WIKK::AES_256.gen_key_to_s
  session_state_init('auth' => false, 'seed' => challenge, 'ip' => "10.2.2.193", 'session_expires' => session_options['session_expires'])
  @cgi.header("type"=>"text/html")
  @cgi.out do
    @cgi.html do
      @cgi.head{ @cgi.title{"login"} + html_nocache + html_script() } +
      @cgi.body {  (user, challenge, return_url) + "\n" }
    end
  end
  @session.update
end

#html_logout_form(cgi_dir) ⇒ Object

Used by calling cgi to generate logout with this form.

@param cgi_dir [String] directory holding the login.rbx cgi.
@return [String] Html logout form.


200
201
202
203
204
205
206
# File 'lib/wikk_web_auth.rb', line 200

def html_logout_form(cgi_dir)
  <<-EOHTMLF2
  <form NAME="login" ACTION="#{cgi_dir}/login.rbx" METHOD="post">
  <input TYPE="submit" NAME="logout" VALUE="logout" >
  </form>
  EOHTMLF2
end

#html_reload(url = nil) ⇒ Object

Used by calling cgi to inject a return URL into the html response. Called by calling cgi, when constructing their html headers.

@param url [String] URL to redirect to.
@return [String] The HTML meta header, or "", if url is empty.


189
190
191
192
193
194
195
# File 'lib/wikk_web_auth.rb', line 189

def html_reload(url = nil)
  if url != nil && url != ''
    "<meta http-equiv=\"Refresh\" content=\"0; URL=#{url}\">\n"
  else
    ""
  end
end

#logoutObject

clean up the session, setting @authenticated to false and deleting the session state.



156
157
158
# File 'lib/wikk_web_auth.rb', line 156

def logout 
  @session.delete if @session != nil
end

#session_state_init(session_options = {}) ⇒ Object



115
116
117
# File 'lib/wikk_web_auth.rb', line 115

def session_state_init(session_options = {})
  session_options.each { |k,v| @session[k] = v }
end