[Zope-PAS] Cookie Auth Monopolizes Challenge?
Chris McDonough
chrism at plope.com
Thu Aug 11 15:18:43 EDT 2005
Hi Sidnei,
I had to deal with this at some point and I wrote a PAS multiplugin that
implemented the "unauthorized" method (forget which interface that
belongs to)... here it is along with a helper method to figure out if a
request came from a DAV client:
security.declarePublic('unauthorized')
def unauthorized(self):
""" Override cookieauthplugin unauthorized to deal properly
with DAV requests """
req = self.REQUEST
resp = req['RESPONSE']
# If we set the auth cookie before, delete it now.
if resp.cookies.has_key(self.cookie_name):
del resp.cookies[self.cookie_name]
if self.isDAVRequest(req):
# DAV clients/EE can't deal with form-based auth, so
# we give them a basic auth 401 response code
realm = resp.realm
if realm:
resp.addHeader('WWW-Authenticate',
'basic realm="%s"' % realm)
m = "You are not authorized to access this resource."
if resp.debug_mode:
if resp._auth:
m = m + '<p>\nUsername and password are not
correct.'
else:
m = m + '<p>\nNo Authorization header found.'
resp.setBody(m, is_error=1)
resp.setStatus(401)
return 1
# Redirect if desired.
url = self.getLoginURL()
if url is not None:
came_from = req.get('came_from', None)
if came_from is None:
came_from = req.get('URL', '')
query = req.get('QUERY_STRING')
if query:
if not query.startswith('?'):
query = '?' + query
came_from = came_from + query
else:
# If came_from contains a value it means the user
# must be coming through here a second time
# Reasons could be typos when providing credentials
# or a redirect loop (see below)
req_url = req.get('URL', '')
if req_url and req_url == url:
# Oops... The login_form cannot be reached by the
user -
# it might be protected itself due to
misconfiguration -
# the only sane thing to do is to give up because we
are
# in an endless redirect loop.
return 0
url = url + '?came_from=%s' % quote(came_from)
resp.redirect(url, lock=1)
return 1
# Could not challenge.
return 0
security.declarePublic('isDAVRequest')
def isDAVRequest(self, request):
method = request.get('REQUEST_METHOD', 'GET')
if method in DAV_METHODS:
return True
if request.maybe_webdav_client and not method in ('GET',
'POST'):
return True
useragent = request.get_header('User-Agent') or ''
for agent in DAV_USERAGENTS:
if useragent.find(agent) != -1:
return True
return False
On Thu, 2005-08-11 at 15:46 -0300, Sidnei da Silva wrote:
> So, leaving other issues aside *wink*, I'm no puzzled by the challenge
> code in PAS. It looks like there was some attempt at distinguishing
> challenging by some sort of 'protocol', but it leaves a lot to be
> desired, or I don't understand how it's supposed to work.
>
> The problem I'm facing now is that using the Cookie Auth plugin
> effectively breaks WebDAV (and possibly FTP and XML-RPC), because as
> soon as the Cookie Auth plugin is hit on challenge, it does a redirect
> to the login form.
>
> Changing the Cookie Auth to come after Basic Auth doesn't help either,
> as then instead of a browser client being directed to the login form
> it gets a basic auth dialog instead.
>
> Is it possible that nobody noticed this yet? Or is it just me not
> getting enough sleep last night?
>
More information about the Zope-PAS
mailing list