From 3644d081f63ef022b42dfcc7d488e8e55769ea03 Mon Sep 17 00:00:00 2001 From: Michele Comitini Date: Mon, 11 Mar 2013 13:13:08 +0100 Subject: [PATCH 1/2] rfc compliant basic auth --- gluon/tools.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/gluon/tools.py b/gluon/tools.py index 3945d854..4d7437cc 100644 --- a/gluon/tools.py +++ b/gluon/tools.py @@ -1755,7 +1755,7 @@ class Auth(object): self.add_membership(self.settings.everybody_group_id, user_id) return user - def basic(self): + def basic(self, basic_auth_realm=False): """ perform basic login. reads current.request.env.http_authorization @@ -1764,10 +1764,25 @@ class Auth(object): if not self.settings.allow_basic_login: return (False, False, False) basic = current.request.env.http_authorization + if basic_auth_realm: + import types + if isinstance(basic_auth_realm, types.FunctionType): + basic_auth_realm = basic_auth_auth() + elif isinstance(basic_auth_realm, (unicode, str)): + basic_realm = unicode(basic_auth_realm) + elif basic_auth_realm is True: + basic_realm = u'' + current.request.application + http_401 = HTTP(401, u'Not Authorized', + **{u'WWW-Authenticate': u'Basic realm="' + basic_realm + '"'}) if not basic or not basic[:6].lower() == 'basic ': + if basic_auth_realm: + raise http_401 return (True, False, False) (username, password) = base64.b64decode(basic[6:]).split(':') - return (True, True, self.login_bare(username, password)) + is_valid_user = self.login_bare(username, password) + if not is_valid_user and basic_auth_realm: + raise http_401 + return (True, True, is_valid_user) def login_user(self, user): """ From 812ba9d52bbec70abb1ab291e418daf3f2ca32eb Mon Sep 17 00:00:00 2001 From: Michele Comitini Date: Mon, 11 Mar 2013 14:40:34 +0100 Subject: [PATCH 2/2] docstring improved --- gluon/tools.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/gluon/tools.py b/gluon/tools.py index 4d7437cc..00ffc17e 100644 --- a/gluon/tools.py +++ b/gluon/tools.py @@ -1758,15 +1758,26 @@ class Auth(object): def basic(self, basic_auth_realm=False): """ perform basic login. + + :param basic_auth_realm: optional basic http authentication realm. + :type basic_auth_realm: str or unicode or function or callable or boolean. + reads current.request.env.http_authorization - and returns basic_allowed,basic_accepted,user + and returns basic_allowed,basic_accepted,user. + + if basic_auth_realm is defined is a callable it's return value + is used to set the basic authentication realm, if it's a string + its content is used instead. Otherwise basic authentication realm + is set to the application name. + If basic_auth_realm is None or False (the default) the behavior + is to skip sending any challenge. + """ if not self.settings.allow_basic_login: return (False, False, False) basic = current.request.env.http_authorization if basic_auth_realm: - import types - if isinstance(basic_auth_realm, types.FunctionType): + if callable(basic_auth_realm): basic_auth_realm = basic_auth_auth() elif isinstance(basic_auth_realm, (unicode, str)): basic_realm = unicode(basic_auth_realm)