Module: Arrow::AppletAuthentication

Included in:
AccessControls
Defined in:
lib/arrow/appletmixins.rb

Overview

A collection of functions for abstracting authentication and authorization away from Arrow::Applets. Applets which include this module should provide implementations of at least the #get_authenticated_user method, and may provide implementations of other methods to tailor the authentication for their particular applet.

Customization API

[#get_authenticated_user]

Override this method to provide the particulars of your authentication system. The method is given the Arrow::Transaction object that wraps the incoming request, and should return whatever kind of “user” object they wish to use. The only requirement for a user object as far as this mixin is concerned is that it must have a #to_s method, so even a simple username in a String will suffice. If no authorization is possible, return nil, which will cause the #login_action to be invoked.

[#user_is_authorized]

Override this method to provide authorization checks of an authenticated user (the one returned from #get_authenticated_user) against the incoming request. If the user is authorized to run the action, return true, else return false. Failed authorization will cause the #deny_access_action to be invoked.

[#login_action]

Override this method if you wish to customize the login process. By default, this returns a response that prompts the client using Basic HTTP authentication.

[#logout_action]

Override this method if you wish to customize the logout process. By default, this declines the request, which will tell Apache to try to handle the request itself.

[#deny_access_action]

Override this method if you wish to customize what happens when the client sends a request for a resource they are not authorized to interact with. By default, this method returns a simple HTTP FORBIDDEN response.

VCS Id

 $Id$

Authors

  • Michael Granger

:include: LICENSE

Please see the file LICENSE in the top-level directory for licensing details.

Instance Method Summary

Instance Method Details

- (Object) deny_access_action(txn, *args)

Default AppletAuthentication API: provides a hook for applets which have some actions which require authorization to run; override this to provide a “Forbidden” page. By default, this just returns an HTTP FORBIDDEN response.



83
84
85
86
87
# File 'lib/arrow/appletmixins.rb', line 83

def deny_access_action( txn, *args )
  self.log.error "Unauthorized request for %s" % [ txn.uri ]
  txn.status = Apache::FORBIDDEN
  return "access denied"
end

- (Object) get_authenticated_user(txn) (protected)

Default AppletAuthentication API: return a “user” object if the specified txn object provides authentication. Applets wishing to authenticate uses should provide an overriding implementation of this method. The base implementation always returns nil.



134
135
136
137
138
# File 'lib/arrow/appletmixins.rb', line 134

def get_authenticated_user( txn )
  self.log.notice "No implementation of get_authenticated_user for %s" %
    [ self.class.signature.name ]
  return nil
end

- (Object) login_action(txn, *args)

Default AppletAuthentication API: provides login functionality for actions that require authorization; override this to provide a login form. By default, this just returns an HTTP UNAUTHORIZED response.



63
64
65
66
67
68
# File 'lib/arrow/appletmixins.rb', line 63

def ( txn, *args )
  self.log.info "Prompting the client for authentication"
  # :TODO: This really needs to set the WWW-Authenticate header...
  txn.status = Apache::HTTP_UNAUTHORIZED
  return "this resource requires authentication"
end

- (Object) logout_action(txn, *args)

Default AppletAuthentication API: provides login functionality for actions that require authorization; override this to customize the logout process. By default, this just returns nil, which will decline the request.



74
75
76
77
# File 'lib/arrow/appletmixins.rb', line 74

def logout_action( txn, *args )
  self.log.info "No logout action provided, passing the request off to the server"
  return Apache::DECLINED
end

- (Object) user_is_authorized(user, txn, *args) (protected)

Default AppletAuthentication API: returns true if the specified user is authorized to run the applet. Applets wishing to authorize users should provide an overriding implementation of this method. The base implementation always returns false.



145
146
147
148
149
# File 'lib/arrow/appletmixins.rb', line 145

def user_is_authorized( user, txn, *args )
  self.log.notice "No implementation of user_is_authorized for %s" %
    [ self.class.signature.name ]
  return false
end

- (Object) with_authentication(txn, *args) (protected)

Check to see that the user is authenticated. If not attempt to authenticate them via a form. If they are authenticated, or become authenticated after the form action, call the supplied block with the authenticated user.



98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/arrow/appletmixins.rb', line 98

def with_authentication( txn, *args )
  self.log.debug "wrapping a block in authentication"

  # If the user doesn't have a session user, go to the login form.
  if user = self.get_authenticated_user( txn )
    return yield( user )
  else
    self.log.warning "Authentication failed from %s for %s" %
      [ txn.remote_host(Apache::REMOTE_NOLOOKUP), txn.the_request ]
    return self.subrun( :login, txn, *args )
  end
end

- (Object) with_authorization(txn, *args) (protected)

Wrap a block in authorization. If the given user has all of the necessary permissions to run the given applet_chain (an Array of Arrow::AppRegistry::ChainLink structs), call the provided block. Otherwise run the ‘deny_access’ action and return the result.



116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/arrow/appletmixins.rb', line 116

def with_authorization( txn, *args )
  self.with_authentication( txn ) do |user|
    self.log.debug "Checking permissions of '%s' to execute %s" % [ user, txn.uri ]

    if self.user_is_authorized( user, txn, *args )
      return yield
    else
      self.log.warning "Access denied to %s for %s" % [ user, txn.the_request ]
      return self.subrun( :deny_access, txn )
    end
  end
end