Custom Authenticators¶
Let’s peek at the Authenticator classes:
In [1]:
from jupyterhub.auth import Authenticator, PAMAuthenticator
In [2]:
Authenticator.authenticate?
Signature: Authenticator.authenticate(self, handler, data)
Docstring:
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.
Return:
str: the username of the authenticated user
None: Authentication failed
File: ~/conda/envs/jupyterhub-tutorial/lib/python3.5/site-packages/jupyterhub/auth.py
Type: function
PAM calls out to a library with the given username and password:
In [3]:
PAMAuthenticator.authenticate??
Signature: PAMAuthenticator.authenticate(self, handler, data)
Source:
@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
File: ~/conda/envs/jupyterhub-tutorial/lib/python3.5/site-packages/jupyterhub/auth.py
Type: function
Here’s a super advanced Authenticator that does very secure password verification:
In [4]:
class SecureAuthenticator(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:703fa736d506ca25:d47727cb57a2bd3c0fba618aea1dd71fc053de5d406d43d1ea81676cf386fa5e8a9dd364b59456c4ad65a096d9fab08b51795994376caf642016f43f5b44f4bf'
In [6]:
compare_token(_, 'mypassword')
Out[6]:
True