changeset 2132:9f5582151d53 beta

Alternative HTTP response codes when client failed to Authenticate correctly
author Marcin Kuzminski <marcin@python-works.com>
date Fri, 16 Mar 2012 23:58:05 +0200
parents d683d8bc4be3
children e1a54d600c89
files development.ini docs/changelog.rst production.ini rhodecode/config/deployment.ini_tmpl rhodecode/lib/base.py
diffstat 5 files changed, 37 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/development.ini	Fri Mar 16 18:49:31 2012 +0200
+++ b/development.ini	Fri Mar 16 23:58:05 2012 +0200
@@ -93,6 +93,11 @@
 ## all running rhodecode instances. Leave empty if you don't use it
 instance_id = 
 
+## alternative return HTTP header for failed authentication. Default HTTP
+## response is 401 HTTPUnauthorized. Currently HG clients have troubles with 
+## handling that. Set this variable to 403 to return HTTPForbidden
+auth_ret_code =
+
 ####################################
 ###        CELERY CONFIG        ####
 ####################################
--- a/docs/changelog.rst	Fri Mar 16 18:49:31 2012 +0200
+++ b/docs/changelog.rst	Fri Mar 16 23:58:05 2012 +0200
@@ -23,6 +23,8 @@
 - #399 added inheritance of permissions for users group on repos groups
 - #401 repository group is automatically pre-selected when adding repos 
   inside a repository group
+- added alternative HTTP 403 response when client failed to authenticate. Helps 
+  solving issues with Mercurial and LDAP
 
 fixes
 +++++
--- a/production.ini	Fri Mar 16 18:49:31 2012 +0200
+++ b/production.ini	Fri Mar 16 23:58:05 2012 +0200
@@ -93,6 +93,11 @@
 ## all running rhodecode instances. Leave empty if you don't use it
 instance_id = 
 
+## alternative return HTTP header for failed authentication. Default HTTP
+## response is 401 HTTPUnauthorized. Currently HG clients have troubles with 
+## handling that. Set this variable to 403 to return HTTPForbidden
+auth_ret_code =
+
 ####################################
 ###        CELERY CONFIG        ####
 ####################################
--- a/rhodecode/config/deployment.ini_tmpl	Fri Mar 16 18:49:31 2012 +0200
+++ b/rhodecode/config/deployment.ini_tmpl	Fri Mar 16 23:58:05 2012 +0200
@@ -93,6 +93,11 @@
 ## all running rhodecode instances. Leave empty if you don't use it
 instance_id = 
 
+## alternative return HTTP header for failed authentication. Default HTTP
+## response is 401 HTTPUnauthorized. Currently HG clients have troubles with 
+## handling that. Set this variable to 403 to return HTTPForbidden
+auth_ret_code =
+
 ####################################
 ###        CELERY CONFIG        ####
 ####################################
--- a/rhodecode/lib/base.py	Fri Mar 16 18:49:31 2012 +0200
+++ b/rhodecode/lib/base.py	Fri Mar 16 23:58:05 2012 +0200
@@ -7,6 +7,8 @@
 import traceback
 
 from paste.auth.basic import AuthBasicAuthenticator
+from paste.httpexceptions import HTTPUnauthorized, HTTPForbidden
+from paste.httpheaders import WWW_AUTHENTICATE
 
 from pylons import config, tmpl_context as c, request, session, url
 from pylons.controllers import WSGIController
@@ -28,6 +30,22 @@
 log = logging.getLogger(__name__)
 
 
+class BasicAuth(AuthBasicAuthenticator):
+
+    def __init__(self, realm, authfunc, auth_http_code=None):
+        self.realm = realm
+        self.authfunc = authfunc
+        self._rc_auth_http_code = auth_http_code
+
+    def build_authentication(self):
+        head = WWW_AUTHENTICATE.tuples('Basic realm="%s"' % self.realm)
+        if self._rc_auth_http_code and self._rc_auth_http_code == '403':
+            # return 403 if alternative http return code is specified in
+            # RhodeCode config
+            return HTTPForbidden(headers=head)
+        return HTTPUnauthorized(headers=head)
+
+
 class BaseVCSController(object):
 
     def __init__(self, application, config):
@@ -36,7 +54,8 @@
         # base path of repo locations
         self.basepath = self.config['base_path']
         #authenticate this mercurial request using authfunc
-        self.authenticate = AuthBasicAuthenticator('', authfunc)
+        self.authenticate = BasicAuth('', authfunc,
+                                      config.get('auth_ret_code'))
         self.ipaddr = '0.0.0.0'
 
     def _handle_request(self, environ, start_response):