[Zope-PAS] Struggling with 'challenge' support.
Mark Hammond
mhammond at skippinet.com.au
Fri Sep 24 01:07:34 EDT 2004
Upon reflection, I don't believe a simple 'challenge' concept will give us
what we need.
Most sites don't want to use HTTP auth - they prefer web-based
authentication. As far as I can tell, this is how Plone works out of the
box (via the CookieCrumbler). As far as I can tell, this is also how your
CAS plugin wants to work.
However, let's assume a site actually *wanted* to prefer HTTP
authentication, and if that failed, fall back to a web-based login screen.
(This makes sense if the scheme is NTLM/Kerebros, which can authenticate
without any UI)
The question is how we handle this second scenario, and the cause of my
confusion about your 'challenge' implementation and mine.
Consider a new category of plugin - along with 'challenge', we have a new
'redirector'. 'challenge' is used to initiate true challenge/response
schemes. 'redirector' is used to explicitly acquire credentials handles via
redirects. It is used *only* when no challengers have issued a challenge -
if challenges have been issued, we want to give the client a chance to
choose one and offer the appropriate response.
The process is roughly this:
num_challenges = 0
for plugin in challengers:
if plugin.challenge():
num_challenges += 1
if num_challengers == 0: # no one issued a challenge.
for plugin in redirectors:
if plugin.redirect():
# A redirector redirected!
return
The CAS plugin would look roughly like:
def challenge(self, resp):
# For 'challenge', we set the response body to point
# to the login page.
# This will only ever been seen by the user if another challenger
# issued a challenge (eg, http auth), but the response was invalid
# (eg, no username, user cancelled login dialog). In that case,
# the user sees the original 404, and our link in the body.
# If no other challengers configured, we will end up redirecting
# so this will not be seen.
url = self.getLoginURL()
response.setBody('You may logon manually <a href="%s">here</a>' % url)
return 0 # we did not issue a challenge (just screwed with resp!)
def redirect(self, resp):
# do the actual redirection - this means there were no challengers.
resp.redirect()
The HTTPAuthHelper and the NTLM plugins *only* challenge. They do not
implement redirect().
This allows you to configure PAS exactly as you want, and you still get a
good result. So long as you did *not* enable HTTPAuth, CAS/Cookie sites
still operate correctly (there are no 'challengers' configured, so we always
redirect). If you do enable HTTP auth, you will first be prompted for a
password by the browser. If that fails, the 404 page will include a link to
the CAS logon page. This way, HTTP auth can 'override' CAS authentication.
Does that make sense? Am I barking mad? At least I understand the problem
a bit more now, even if I don't quite have the solution :)
Mark.
More information about the Zope-PAS
mailing list