Class: OMF::Web::Rack::SessionAuthenticator

Inherits:
Base::LObject
  • Object
show all
Defined in:
lib/omf-web/rack/session_authenticator.rb

Overview

This rack module maintains a session cookie and redirects any requests to protected pages to a ‘login’ page at the beginning of a session

Calls to the class methods are resolved inthe context of a Session using ‘OMF::Web::SessionStore’

Constant Summary collapse

@@active =
false
@@expire_after =

Expire authenticated session after being idle for that many seconds

2592000

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app, opts = {}) ⇒ SessionAuthenticator

opts -

:login_url - URL to redirect if session is not authenticated
:no_session - Array of regexp on 'path_info' which do not require an authenticated session
:expire_after - Idle time in sec after which to expire a session


110
111
112
113
114
115
116
117
118
# File 'lib/omf-web/rack/session_authenticator.rb', line 110

def initialize(app, opts = {})
  @app = app
  @opts = opts
  @opts[:no_session] = (@opts[:no_session] || []).map { |s| Regexp.new(s) }
  if @opts[:expire_after]
    @@expire_after = @opts[:expire_after]
  end
  @@active = true
end

Class Method Details

.[](key) ⇒ Object

DO NOT CALL DIRECTLY



90
91
92
# File 'lib/omf-web/rack/session_authenticator.rb', line 90

def self.[](key)
  OMF::Web::SessionStore[key, :authenticator]
end

.[]=(key, value) ⇒ Object

DO NOT CALL DIRECTLY



96
97
98
# File 'lib/omf-web/rack/session_authenticator.rb', line 96

def self.[]=(key, value)
  OMF::Web::SessionStore[key, :authenticator] = value
end

.active?Boolean

Returns true if this Rack module has been instantiated in the current Rack stack.

Returns:

  • (Boolean)


24
25
26
# File 'lib/omf-web/rack/session_authenticator.rb', line 24

def self.active?
  @@active
end

.authenticate(expires = nil) ⇒ Object

Calling this method will authenticate the current session



38
39
40
41
# File 'lib/omf-web/rack/session_authenticator.rb', line 38

def self.authenticate(expires = nil)
  self[:authenticated] = true
  self[:valid_until] = Time.now + @@expire_after
end

.authenticate_with(req) ⇒ Object

Attempt to authenticate with the provided ‘req’



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/omf-web/rack/session_authenticator.rb', line 50

def self.authenticate_with(req)
  p = req.params
  #puts ">>>>>>> AA(#{req.host_with_port}): #{p}"
  case t = p['method']
  when 'persona'
    require 'net/http'
    unless assertion = p['assertion']
      raise AuthenticationFailedException.new("Missing assertion")
    end

    http = Net::HTTP.new('verifier.login.persona.org', 443)
    http.use_ssl = true
    data = "assertion=#{assertion}&audience=#{req.host_with_port}"
    headers = {'Content-Type' => 'application/x-www-form-urlencoded'}
    reply = http.post('/verify', data, headers)
    unless reply.code_type == Net::HTTPOK && reply.content_type == "application/json"
      raise AuthenticationFailedException.new("Could not verify Persona - '#{reply.body}'")
    end
    debug "Persona reply: '#{reply.body}'"
    r = JSON.load(reply.body)
    unless ((email = r['email']) && (expires = r['expires']))
      raise AuthenticationFailedException.new("Could not verify Persona - '#{r}'")
    end
    self[:user] = {name: email, email: email, method: 'persona'}
    authenticate(Time.at(expires))
  else
    raise AuthenticationFailedException.new("Unsupported authentication type '#{t}'")
  end
end

.authenticated?Boolean

Return true if the session is authenticated

Returns:

  • (Boolean)


30
31
32
33
34
# File 'lib/omf-web/rack/session_authenticator.rb', line 30

def self.authenticated?
  auth = self[:authenticated] == true && self[:valid_until] > Time.now
  #debug "AUTH: #{auth}"
  auth
end

.logoutObject

Logging out will un-authenticate this session



82
83
84
85
86
# File 'lib/omf-web/rack/session_authenticator.rb', line 82

def self.logout
  debug "LOGOUT"
  self[:authenticated] = false
  self[:user] = nil
end

.userObject

Information about the authenticated user



45
46
47
# File 'lib/omf-web/rack/session_authenticator.rb', line 45

def self.user()
  self[:user]
end

Instance Method Details

#call(env) ⇒ Object



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
154
# File 'lib/omf-web/rack/session_authenticator.rb', line 125

def call(env)
  req = ::Rack::Request.new(env)
  path_info = req.path_info
  sid = req.cookies['sid']
  unless sid
    sid = "s#{(rand * 10000000).to_i}_#{(rand * 10000000).to_i}"
  end
  Thread.current["sessionID"] = sid  # needed for Session Store
  #debug "Request for '#{path_info}' - sid: #{sid} - #{self.class.authenticated?}"
  unless @opts[:no_session].find {|rx| rx.match(path_info) }
    # If 'login_page_url' is defined, check if this session is authenticated
     = @opts[:login_page_url]
    if  &&  != req.path_info
      begin
        check_authenticated
      rescue AuthenticationFailedException => ex
        if err = self.class[:login_error]
           =  + "?msg=#{err}"
        end
        headers = {'Location' => , "Content-Type" => ""}
        Rack::Utils.set_cookie_header!(headers, 'sid', sid)
        return [307, headers, ['Login first']]
      end
    end
  end

  status, headers, body = @app.call(env)
  Rack::Utils.set_cookie_header!(headers, 'sid', sid) # if sid
  [status, headers, body]
end

#check_authenticatedObject



120
121
122
123
# File 'lib/omf-web/rack/session_authenticator.rb', line 120

def check_authenticated
  authenticated = self.class.authenticated?
  raise AuthenticationFailedException.new unless authenticated
end