Custom Authenticators¶
Let’s peek at the Authenticator classes:
In [1]:
from jupyterhub.auth import Authenticator, PAMAuthenticator
In [2]:
Authenticator.authenticate?
[0;31mSignature:[0m Authenticator.authenticate(self, handler, data)
[0;31mDocstring:[0m
Authenticate a user with login form data
This must be a tornado gen.coroutine.
It must return the username on successful authentication,
and return None on failed authentication.
Checking the whitelist is handled separately by the caller.
Args:
handler (tornado.web.RequestHandler): the current request handler
data (dict): The formdata of the login form.
The default form has 'username' and 'password' fields.
Returns:
username (str or None): The username of the authenticated user,
or None if Authentication failed
[0;31mFile:[0m ~/dev/jpy/jupyterhub/jupyterhub/auth.py
[0;31mType:[0m function
PAM calls out to a library with the given username and password:
In [3]:
PAMAuthenticator.authenticate??
[0;31mSignature:[0m PAMAuthenticator.authenticate(self, handler, data)
[0;31mSource:[0m
@gen.coroutine
def authenticate(self, handler, data):
"""Authenticate with PAM, and return the username if login is successful.
Return None otherwise.
"""
username = data['username']
try:
pamela.authenticate(username, data['password'], service=self.service)
except pamela.PAMError as e:
if handler is not None:
self.log.warning("PAM Authentication failed (%s@%s): %s", username, handler.request.remote_ip, e)
else:
self.log.warning("PAM Authentication failed: %s", e)
else:
return username
[0;31mFile:[0m ~/dev/jpy/jupyterhub/jupyterhub/auth.py
[0;31mType:[0m function
Here’s a super advanced Authenticator that does very secure password verification:
In [4]:
class SuperSecureAuthenticator(Authenticator):
def authenticate(self, handler, data):
username = data['username']
# check password:
if data['username'] == data['password']:
return username
Exercise:¶
Write a custom username+password Authenticator where:
- passwords are loaded from a dict
- hashed+salted passwords are stored somewhere, but not cleartext passwords
In [5]:
# possibly useful:
from jupyterhub.utils import hash_token, compare_token
hash_token('mypassword')
Out[5]:
'sha512:16384:98400e241da5a64d:6e2c468dea2e6ec6f185936f6ac1a96e6046c4cdf6c0156aecb03fcd2e9963c5058cbc7cf9d7792ed9edc5bc1703f6e14274b7ba5804781499e49bb077aacccb'
In [6]:
compare_token(_, 'mypassword')
Out[6]:
True