Compare commits
No commits in common. "master" and "v0.11" have entirely different histories.
5 changed files with 3 additions and 116 deletions
11
README.md
11
README.md
|
@ -47,20 +47,9 @@ For security Reasons. Users are likely to set an, insecure password at
|
|||
login time, and you do not want a brute-force/dictionary attack to manage to
|
||||
login by attacking via ssh or another mean.
|
||||
|
||||
#### How can I change my password?
|
||||
|
||||
To change your password, you should login in your jupyterhub account,
|
||||
go to `<your_server_ip>/hub/auth/change-password` and change the password.
|
||||
|
||||
#### I'm getting an error when creating my username
|
||||
|
||||
Usernames cannot contain spaces or commas. Please check if your username is free
|
||||
of these characters.
|
||||
|
||||
## Security
|
||||
|
||||
When using `FirstUseAuthenticator` it is advised to automatically prepend the
|
||||
name of the user with a known-prefix (for example `jupyter`). This would prevent
|
||||
for example, someone to log-in as `root`, as the created user would be
|
||||
`jupyter-root`.
|
||||
|
||||
|
|
|
@ -6,60 +6,15 @@ password for that account. It is hashed with bcrypt & stored
|
|||
locally in a dbm file, and checked next time they log in.
|
||||
"""
|
||||
import dbm
|
||||
import os
|
||||
from jinja2 import ChoiceLoader, FileSystemLoader
|
||||
from jupyterhub.auth import Authenticator
|
||||
from jupyterhub.handlers import BaseHandler
|
||||
from jupyterhub.orm import User
|
||||
|
||||
from tornado import gen, web
|
||||
from tornado import gen
|
||||
from traitlets.traitlets import Unicode, Bool
|
||||
|
||||
import bcrypt
|
||||
|
||||
|
||||
TEMPLATE_DIR = os.path.join(os.path.dirname(__file__), 'templates')
|
||||
|
||||
|
||||
class ResetPasswordHandler(BaseHandler):
|
||||
"""Render the reset password page."""
|
||||
def __init__(self, *args, **kwargs):
|
||||
self._loaded = False
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def _register_template_path(self):
|
||||
if self._loaded:
|
||||
return
|
||||
|
||||
self.log.debug('Adding %s to template path', TEMPLATE_DIR)
|
||||
loader = FileSystemLoader([TEMPLATE_DIR])
|
||||
|
||||
env = self.settings['jinja2_env']
|
||||
previous_loader = env.loader
|
||||
env.loader = ChoiceLoader([previous_loader, loader])
|
||||
|
||||
self._loaded = True
|
||||
|
||||
@web.authenticated
|
||||
async def get(self):
|
||||
self._register_template_path()
|
||||
html = self.render_template('reset.html')
|
||||
self.finish(html)
|
||||
|
||||
@web.authenticated
|
||||
async def post(self):
|
||||
user = self.get_current_user()
|
||||
new_password = self.get_body_argument('password', strip=False)
|
||||
self.authenticator.reset_password(user.name, new_password)
|
||||
|
||||
html = self.render_template(
|
||||
'reset.html',
|
||||
result=True,
|
||||
result_message='your password has been changed successfully',
|
||||
)
|
||||
self.finish(html)
|
||||
|
||||
|
||||
class FirstUseAuthenticator(Authenticator):
|
||||
"""
|
||||
JupyterHub authenticator that lets users set password on first use.
|
||||
|
@ -93,12 +48,6 @@ class FirstUseAuthenticator(Authenticator):
|
|||
"""
|
||||
return self.db.query(User).filter_by(name=username).first() is not None
|
||||
|
||||
def validate_username(self, name):
|
||||
invalid_chars = [',', ' ']
|
||||
if any((char in name) for char in invalid_chars):
|
||||
return False
|
||||
return super().validate_username(name)
|
||||
|
||||
@gen.coroutine
|
||||
def authenticate(self, handler, data):
|
||||
username = data['username']
|
||||
|
@ -114,8 +63,7 @@ class FirstUseAuthenticator(Authenticator):
|
|||
if bcrypt.hashpw(password.encode(), stored_pw) != stored_pw:
|
||||
return None
|
||||
else:
|
||||
db[username] = bcrypt.hashpw(password.encode(),
|
||||
bcrypt.gensalt())
|
||||
db[username] = bcrypt.hashpw(password.encode(), bcrypt.gensalt())
|
||||
return username
|
||||
|
||||
def delete_user(self, user):
|
||||
|
@ -126,16 +74,3 @@ class FirstUseAuthenticator(Authenticator):
|
|||
"""
|
||||
with dbm.open(self.dbm_path, 'c', 0o600) as db:
|
||||
del db[user.name]
|
||||
|
||||
def reset_password(self, username, new_password):
|
||||
"""
|
||||
This allow to change password of a logged user.
|
||||
"""
|
||||
with dbm.open(self.dbm_path, 'c', 0o600) as db:
|
||||
db[username] = bcrypt.hashpw(new_password.encode(),
|
||||
bcrypt.gensalt())
|
||||
return username
|
||||
|
||||
def get_handlers(self, app):
|
||||
return super().get_handlers(app) + [(r'/auth/change-password',
|
||||
ResetPasswordHandler)]
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
{% extends "page.html" %}
|
||||
{% block main %}
|
||||
<div class="container">
|
||||
<form action="{{post_url}}" method="post" role="form">
|
||||
<h2>
|
||||
Change Password
|
||||
</h2>
|
||||
<div>
|
||||
<div class="form-group">
|
||||
<label for='password_input'>New Password:</label>
|
||||
<input
|
||||
type="password"
|
||||
class="form-control"
|
||||
name="password"
|
||||
id="password_input"
|
||||
tabindex="2"
|
||||
/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input
|
||||
type="submit"
|
||||
id="login_submit"
|
||||
class='btn btn-jupyter'
|
||||
value='Change Password'
|
||||
tabindex="3"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% if result %}
|
||||
<div class="alert alert-success" role="alert">{{result_message}}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
5
setup.py
5
setup.py
|
@ -9,8 +9,5 @@ setup(
|
|||
author_email='yuvipanda@gmail.com',
|
||||
license='3 Clause BSD',
|
||||
packages=find_packages(),
|
||||
install_requires=['bcrypt'],
|
||||
package_data={
|
||||
'': ['*.html'],
|
||||
}
|
||||
install_requires=['bcrypt']
|
||||
)
|
||||
|
|
Loading…
Add table
Reference in a new issue