[web auth] fix authentication pb when anonymous are allowed, avoiding the first authentifier to return an anon connection while a following one may find correct authentication info. This make things simpler (eventually) stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Tue, 16 Mar 2010 12:34:29 +0100
branchstable
changeset 4910 f40fddaa79ad
parent 4909 a13c1d1ecc5b
child 4911 898c35be5873
[web auth] fix authentication pb when anonymous are allowed, avoiding the first authentifier to return an anon connection while a following one may find correct authentication info. This make things simpler (eventually)
web/views/authentication.py
--- a/web/views/authentication.py	Tue Mar 16 12:31:06 2010 +0100
+++ b/web/views/authentication.py	Tue Mar 16 12:34:29 2010 +0100
@@ -39,19 +39,13 @@
     __regid__ = 'loginpwdauth'
     order = 10
 
-    def __init__(self, vreg):
-        self.anoninfo = vreg.config.anonymous_user()
-
     def authentication_information(self, req):
         """retreive authentication information from the given request, raise
         NoAuthInfo if expected information is not found.
         """
         login, password = req.get_authorization()
         if not login:
-            # No session and no login -> try anonymous
-            login, password = self.anoninfo
-            if not login: # anonymous not authorized
-                raise NoAuthInfo()
+            raise NoAuthInfo()
         return login, {'password': password}
 
 
@@ -65,6 +59,7 @@
         self.authinforetreivers = sorted(vreg['webauth'].possible_objects(vreg),
                                     key=lambda x: x.order)
         assert self.authinforetreivers
+        self.anoninfo = vreg.config.anonymous_user()
 
     def validate_session(self, req, session):
         """check session validity, and return eventually hijacked session
@@ -116,37 +111,38 @@
                 continue
             try:
                 cnx = self._authenticate(req, login, authinfo)
-                break
             except ExplicitLogin:
                 continue # the next one may succeed
+            for retreiver_ in self.authinforetreivers:
+                retreiver_.authenticated(req, cnx, retreiver)
+            break
         else:
-            raise ExplicitLogin()
-        for retreiver_ in self.authinforetreivers:
-            retreiver_.authenticated(req, cnx, retreiver)
+            # false if no authentication info found, eg this is not an
+            # authentication failure
+            if 'login' in locals():
+                req.set_message(req._('authentication failure'))
+            cnx = self._open_anonymous_connection(req)
         return cnx
 
     def _authenticate(self, req, login, authinfo):
-        # remove possibly cached cursor coming from closed connection
         cnxprops = ConnectionProperties(self.vreg.config.repo_method,
                                         close=False, log=self.log_queries)
         try:
             cnx = repo_connect(self.repo, login, cnxprops=cnxprops, **authinfo)
         except AuthenticationError:
-            req.set_message(req._('authentication failure'))
-            # restore an anonymous connection if possible
-            anonlogin, anonpassword = self.vreg.config.anonymous_user()
-            if anonlogin and anonlogin != login:
-                cnx = repo_connect(self.repo, anonlogin, password=anonpassword,
-                                   cnxprops=cnxprops)
-                self._init_cnx(cnx, anonlogin, {'password': anonpassword})
-            else:
-                raise ExplicitLogin()
-        else:
-            self._init_cnx(cnx, login, authinfo)
+            raise ExplicitLogin()
+        self._init_cnx(cnx, login, authinfo)
         # associate the connection to the current request
         req.set_connection(cnx)
         return cnx
 
+    def _open_anonymous_connection(self, req):
+        # restore an anonymous connection if possible
+        login, password = self.anoninfo
+        if login:
+            return self._authenticate(req, login, {'password': password})
+        raise ExplicitLogin()
+
     def _init_cnx(self, cnx, login, authinfo):
         # decorate connection
         if login == self.vreg.config.anonymous_user()[0]: