diff --git a/gluon/tools.py b/gluon/tools.py index 3945d854..00ffc17e 100644 --- a/gluon/tools.py +++ b/gluon/tools.py @@ -1755,19 +1755,45 @@ 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. + + :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: + if callable(basic_auth_realm): + 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): """