Allow auth backends to provide login and password
This is used to implement an auth backend that takes the credentials from an HTTP header (e.g. accounts are managed by an reverse proxy)
This commit is contained in:
parent
8bc45aeb24
commit
09bde14e50
2
config
2
config
@ -66,7 +66,7 @@
|
|||||||
[auth]
|
[auth]
|
||||||
|
|
||||||
# Authentication method
|
# Authentication method
|
||||||
# Value: None | htpasswd
|
# Value: None | htpasswd | remote_user | http_x_remote_user
|
||||||
#type = None
|
#type = None
|
||||||
|
|
||||||
# Htpasswd filename
|
# Htpasswd filename
|
||||||
|
@ -371,15 +371,19 @@ class Application:
|
|||||||
function = getattr(self, "do_%s" % environ["REQUEST_METHOD"].upper())
|
function = getattr(self, "do_%s" % environ["REQUEST_METHOD"].upper())
|
||||||
|
|
||||||
# Ask authentication backend to check rights
|
# Ask authentication backend to check rights
|
||||||
authorization = environ.get("HTTP_AUTHORIZATION", None)
|
external_login = self.Auth.get_external_login(environ)
|
||||||
if authorization and authorization.startswith("Basic"):
|
authorization = environ.get("HTTP_AUTHORIZATION", "")
|
||||||
|
if external_login:
|
||||||
|
login, password = external_login
|
||||||
|
elif authorization.startswith("Basic"):
|
||||||
authorization = authorization[len("Basic"):].strip()
|
authorization = authorization[len("Basic"):].strip()
|
||||||
login, password = self.decode(base64.b64decode(
|
login, password = self.decode(base64.b64decode(
|
||||||
authorization.encode("ascii")), environ).split(":", 1)
|
authorization.encode("ascii")), environ).split(":", 1)
|
||||||
user = self.Auth.map_login_to_user(login)
|
|
||||||
else:
|
else:
|
||||||
user = self.Auth.map_login_to_user(environ.get("REMOTE_USER", ""))
|
# DEPRECATED: use remote_user backend instead
|
||||||
|
login = environ.get("REMOTE_USER", "")
|
||||||
password = ""
|
password = ""
|
||||||
|
user = self.Auth.map_login_to_user(login)
|
||||||
|
|
||||||
# If "/.well-known" is not available, clients query "/"
|
# If "/.well-known" is not available, clients query "/"
|
||||||
if path == "/.well-known" or path.startswith("/.well-known/"):
|
if path == "/.well-known" or path.startswith("/.well-known/"):
|
||||||
@ -437,7 +441,7 @@ class Application:
|
|||||||
status, headers, answer = NOT_ALLOWED
|
status, headers, answer = NOT_ALLOWED
|
||||||
|
|
||||||
if (status, headers, answer) == NOT_ALLOWED and not (
|
if (status, headers, answer) == NOT_ALLOWED and not (
|
||||||
user and is_authenticated):
|
user and is_authenticated) and not external_login:
|
||||||
# Unknown or unauthorized user
|
# Unknown or unauthorized user
|
||||||
self.logger.debug("Asking client for authentication")
|
self.logger.debug("Asking client for authentication")
|
||||||
status = client.UNAUTHORIZED
|
status = client.UNAUTHORIZED
|
||||||
|
@ -67,6 +67,10 @@ def load(configuration, logger):
|
|||||||
logger.debug("Authentication type is %s", auth_type)
|
logger.debug("Authentication type is %s", auth_type)
|
||||||
if auth_type == "None":
|
if auth_type == "None":
|
||||||
class_ = NoneAuth
|
class_ = NoneAuth
|
||||||
|
elif auth_type == "remote_user":
|
||||||
|
class_ = RemoteUserAuth
|
||||||
|
elif auth_type == "http_x_remote_user":
|
||||||
|
class_ = HttpXRemoteUserAuth
|
||||||
elif auth_type == "htpasswd":
|
elif auth_type == "htpasswd":
|
||||||
class_ = Auth
|
class_ = Auth
|
||||||
else:
|
else:
|
||||||
@ -79,6 +83,14 @@ class BaseAuth:
|
|||||||
self.configuration = configuration
|
self.configuration = configuration
|
||||||
self.logger = logger
|
self.logger = logger
|
||||||
|
|
||||||
|
def get_external_login(self, environ):
|
||||||
|
"""Optionally provide the login and password externally.
|
||||||
|
|
||||||
|
Returns a tuple (login, password) or ().
|
||||||
|
|
||||||
|
"""
|
||||||
|
return ()
|
||||||
|
|
||||||
def is_authenticated(self, user, password):
|
def is_authenticated(self, user, password):
|
||||||
"""Validate credentials.
|
"""Validate credentials.
|
||||||
|
|
||||||
@ -201,3 +213,13 @@ class Auth(BaseAuth):
|
|||||||
if login_ok & password_ok:
|
if login_ok & password_ok:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class RemoteUserAuth(NoneAuth):
|
||||||
|
def get_external_login(self, environ):
|
||||||
|
return environ.get("REMOTE_USER", ""), ""
|
||||||
|
|
||||||
|
|
||||||
|
class HttpXRemoteUserAuth(NoneAuth):
|
||||||
|
def get_external_login(self, environ):
|
||||||
|
return environ.get("HTTP_X_REMOTE_USER", ""), ""
|
||||||
|
Loading…
Reference in New Issue
Block a user