#237. Allow LDAP user to use OTP

This commit is contained in:
Khanh Ngo 2018-08-22 09:43:33 +07:00
parent 9506315a46
commit 421ea627d8
No known key found for this signature in database
GPG Key ID: B9AE3BAF6D5A7B22
3 changed files with 64 additions and 57 deletions

View File

@ -19,7 +19,7 @@
<div class="col-lg-12"> <div class="col-lg-12">
<div class="box box-primary"> <div class="box box-primary">
<div class="box-header with-border"> <div class="box-header with-border">
<h3 class="box-title">Edit my profile{% if external_account %} [Disabled - Authenticated externally]{% endif %}</h3> <h3 class="box-title">Edit my profile{% if session['authentication_type'] != 'LOCAL' %} [Disabled - Authenticated externally]{% endif %}</h3>
</div> </div>
<div class="box-body"> <div class="box-body">
<!-- Custom Tabs --> <!-- Custom Tabs -->
@ -29,10 +29,11 @@
Info</a></li> Info</a></li>
<li><a href="#tabs-avatar" data-toggle="tab">Change <li><a href="#tabs-avatar" data-toggle="tab">Change
Avatar</a></li> Avatar</a></li>
{% if not external_account %}<li><a href="#tabs-password" data-toggle="tab">Change {% if session['authentication_type'] == 'LOCAL' %}
Password</a></li> <li><a href="#tabs-password" data-toggle="tab">Change Password</a></li>
<li><a href="#tabs-authentication" data-toggle="tab">Authentication {% endif %}
</a></li> {% if session['authentication_type'] in ['LOCAL', 'LDAP'] %}
<li><a href="#tabs-authentication" data-toggle="tab">Authentication</a></li>
{% endif %} {% endif %}
</ul> </ul>
<div class="tab-content"> <div class="tab-content">
@ -41,18 +42,18 @@
<div class="form-group"> <div class="form-group">
<label for="firstname">First Name</label> <input type="text" <label for="firstname">First Name</label> <input type="text"
class="form-control" name="firstname" id="firstname" class="form-control" name="firstname" id="firstname"
placeholder="{{ current_user.firstname }}" {% if external_account %}disabled{% endif %}> placeholder="{{ current_user.firstname }}" {% if session['authentication_type'] != 'LOCAL' %}disabled{% endif %}>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="lastname">Last Name</label> <input type="text" <label for="lastname">Last Name</label> <input type="text"
class="form-control" name="lastname" id="lastname" class="form-control" name="lastname" id="lastname"
placeholder="{{ current_user.lastname }}" {% if external_account %}disabled{% endif %}> placeholder="{{ current_user.lastname }}" {% if session['authentication_type'] != 'LOCAL' %}disabled{% endif %}>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="email">E-mail</label> <input type="text" <label for="email">E-mail</label> <input type="text"
class="form-control" name="email" id="email" class="form-control" name="email" id="email"
placeholder="{{ current_user.email }}" {% if external_account %}disabled{% endif %}> placeholder="{{ current_user.email }}" {% if session['authentication_type'] != 'LOCAL' %}disabled{% endif %}>
</div>{% if not external_account %} </div>{% if session['authentication_type'] == 'LOCAL' %}
<div class="form-group"> <div class="form-group">
<button type="submit" class="btn btn-flat btn-primary">Submit</button> <button type="submit" class="btn btn-flat btn-primary">Submit</button>
</div>{% endif %} </div>{% endif %}
@ -70,50 +71,50 @@
else %} <img else %} <img
src="{{ current_user.email|email_to_gravatar_url(size=200) }}" src="{{ current_user.email|email_to_gravatar_url(size=200) }}"
alt="" /> {% endif %} alt="" /> {% endif %}
</div>{% if not external_account %} </div>{% if session['authentication_type'] == 'LOCAL' %}
<div> <div>
<label for="file">Select image</label> <input type="file" <label for="file">Select image</label> <input type="file"
id="file" name="file"> id="file" name="file">
</div>{% endif %} </div>{% endif %}
</div>{% if not external_account %} </div>{% if session['authentication_type'] == 'LOCAL' %}
<div> <div>
<span class="label label-danger">NOTE! </span> <span>&nbsp;Only <span class="label label-danger">NOTE! </span> <span>&nbsp;Only
supports <strong>.PNG, .JPG, .JPEG</strong>. The best size supports <strong>.PNG, .JPG, .JPEG</strong>. The best size
to use is <strong>200x200</strong>. to use is <strong>200x200</strong>.
</span> </span>
</div>{% endif %} </div>{% endif %}
</div>{% if not external_account %} </div>{% if session['authentication_type'] == 'LOCAL' %}
<div class="form-group"> <div class="form-group">
<button type="submit" class="btn btn-flat btn-primary">Submit</button> <button type="submit" class="btn btn-flat btn-primary">Submit</button>
</div>{% endif %} </div>{% endif %}
</form> </form>
</div> </div>
{% if not external_account %}<div class="tab-pane" id="tabs-password"> {% if session['authentication_type'] == 'LOCAL' %}
{% if not current_user.password %} Your account password is <div class="tab-pane" id="tabs-password">
managed via LDAP which isn't supported to change here. {% else {% if not current_user.password %}
%} Your account password is managed via LDAP which isn't supported to change here.
{% else %}
<form action="{{ user_profile }}" method="post"> <form action="{{ user_profile }}" method="post">
<div class="form-group"> <div class="form-group">
<label for="password">New Password</label> <input <label for="password">New Password</label> <input
type="password" class="form-control" name="password" type="password" class="form-control" name="password" id="newpassword"/>
id="newpassword" {% if external_account %}disabled{% endif %} />
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="rpassword">Re-type New Password</label> <input <label for="rpassword">Re-type New Password</label> <input
type="password" class="form-control" name="rpassword" type="password" class="form-control" name="rpassword" id="rpassword"/>
id="rpassword" {% if external_account %}disabled{% endif %} />
</div> </div>
<div class="form-group"> <div class="form-group">
<button type="submit" class="btn btn-flat btn-primary" {% if external_account %}disabled{% endif %}>Change <button type="submit" class="btn btn-flat btn-primary">Change Password</button>
password</button>
</div> </div>
</form> </form>
{% endif %} {% endif %}
</div> </div>
{% endif %}
<!-- {% if session['authentication_type'] in ['LOCAL', 'LDAP'] %} -->
<div class="tab-pane" id="tabs-authentication"> <div class="tab-pane" id="tabs-authentication">
<form action="{{ user_profile }}" method="post"> <form action="{{ user_profile }}" method="post">
<div class="form-group"> <div class="form-group">
<input type="checkbox" id="otp_toggle" class="otp_toggle" {% if current_user.otp_secret %}checked{% endif %} {% if external_account %}disabled{% endif %}> <input type="checkbox" id="otp_toggle" class="otp_toggle" {% if current_user.otp_secret %}checked{% endif %}>
<label for="otp_toggle">Enable Two Factor Authentication</label> <label for="otp_toggle">Enable Two Factor Authentication</label>
{% if current_user.otp_secret %} {% if current_user.otp_secret %}
<div id="token_information"> <div id="token_information">
@ -125,7 +126,8 @@
{% endif %} {% endif %}
</div> </div>
</form> </form>
</div>{% endif %} </div>
<!-- {% endif %} -->
</div> </div>
</div> </div>
</div> </div>

View File

@ -263,7 +263,7 @@ def saml_authorized():
history.add() history.add()
user.plain_text_password = None user.plain_text_password = None
user.update_profile() user.update_profile()
session['external_auth'] = True session['authentication_type'] = 'SAML'
login_user(user, remember=False) login_user(user, remember=False)
return redirect(url_for('index')) return redirect(url_for('index'))
else: else:
@ -300,7 +300,7 @@ def login():
session['user_id'] = user.id session['user_id'] = user.id
login_user(user, remember = False) login_user(user, remember = False)
session['external_auth'] = True session['authentication_type'] = 'OAuth'
return redirect(url_for('index')) return redirect(url_for('index'))
if 'github_token' in session: if 'github_token' in session:
@ -324,7 +324,7 @@ def login():
return redirect(url_for('login')) return redirect(url_for('login'))
session['user_id'] = user.id session['user_id'] = user.id
session['external_auth'] = True session['authentication_type'] = 'OAuth'
login_user(user, remember = False) login_user(user, remember = False)
return redirect(url_for('index')) return redirect(url_for('index'))
@ -343,8 +343,7 @@ def login():
email = request.form.get('email') email = request.form.get('email')
rpassword = request.form.get('rpassword') rpassword = request.form.get('rpassword')
if auth_method != 'LOCAL': session['authentication_type'] = 'LDAP' if auth_method != 'LOCAL' else 'LOCAL'
session['external_auth'] = True
if None in [firstname, lastname, email]: if None in [firstname, lastname, email]:
#login case #login case
@ -399,6 +398,7 @@ def clear_session():
session.pop('user_id', None) session.pop('user_id', None)
session.pop('github_token', None) session.pop('github_token', None)
session.pop('google_token', None) session.pop('google_token', None)
session.pop('authentication_type', None)
session.clear() session.clear()
logout_user() logout_user()
@ -411,9 +411,9 @@ def logout():
if app.config.get('SAML_LOGOUT_URL'): if app.config.get('SAML_LOGOUT_URL'):
return redirect(auth.logout(name_id_format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", return redirect(auth.logout(name_id_format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
return_to = app.config.get('SAML_LOGOUT_URL'), return_to = app.config.get('SAML_LOGOUT_URL'),
session_index = session['samlSessionIndex'], name_id=session['samlNameId'])) session_index = session['samlSessionIndex'], name_id=session['samlNameId']))
return redirect(auth.logout(name_id_format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", return redirect(auth.logout(name_id_format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
session_index = session['samlSessionIndex'], session_index = session['samlSessionIndex'],
name_id=session['samlNameId'])) name_id=session['samlNameId']))
clear_session() clear_session()
return redirect(url_for('login')) return redirect(url_for('login'))
@ -1464,45 +1464,50 @@ def admin_setting_authentication():
@app.route('/user/profile', methods=['GET', 'POST']) @app.route('/user/profile', methods=['GET', 'POST'])
@login_required @login_required
def user_profile(): def user_profile():
external_account = False if request.method == 'GET':
if 'external_auth' in session: return render_template('user_profile.html')
external_account = session['external_auth']
if request.method == 'GET' or external_account:
return render_template('user_profile.html', external_account=external_account)
if request.method == 'POST': if request.method == 'POST':
# get new profile info if session['authentication_type'] == 'LOCAL':
firstname = request.form['firstname'] if 'firstname' in request.form else '' firstname = request.form['firstname'] if 'firstname' in request.form else ''
lastname = request.form['lastname'] if 'lastname' in request.form else '' lastname = request.form['lastname'] if 'lastname' in request.form else ''
email = request.form['email'] if 'email' in request.form else '' email = request.form['email'] if 'email' in request.form else ''
new_password = request.form['password'] if 'password' in request.form else '' new_password = request.form['password'] if 'password' in request.form else ''
else:
firstname = lastname = email = new_password = ''
logging.warning('Authenticated externally. User {0} information will not allowed to update the profile'.format(current_user.username))
# json data
if request.data: if request.data:
jdata = request.json jdata = request.json
data = jdata['data'] data = jdata['data']
if jdata['action'] == 'enable_otp': if jdata['action'] == 'enable_otp':
enable_otp = data['enable_otp'] if session['authentication_type'] in ['LOCAL', 'LDAP']:
user = User(username=current_user.username) enable_otp = data['enable_otp']
user.update_profile(enable_otp=enable_otp) user = User(username=current_user.username)
return make_response(jsonify( { 'status': 'ok', 'msg': 'Change OTP Authentication successfully. Status: {0}'.format(enable_otp) } ), 200) user.update_profile(enable_otp=enable_otp)
return make_response(jsonify( { 'status': 'ok', 'msg': 'Change OTP Authentication successfully. Status: {0}'.format(enable_otp) } ), 200)
else:
return make_response(jsonify( { 'status': 'error', 'msg': 'User {0} is externally. You are not allowed to update the OTP'.format(current_user.username) } ), 400)
# get new avatar # get new avatar
save_file_name = None save_file_name = None
if 'file' in request.files: if 'file' in request.files:
file = request.files['file'] if session['authentication_type'] in ['LOCAL', 'LDAP']:
if file: file = request.files['file']
filename = secure_filename(file.filename) if file:
file_extension = filename.rsplit('.', 1)[1] filename = secure_filename(file.filename)
file_extension = filename.rsplit('.', 1)[1]
if file_extension.lower() in ['jpg', 'jpeg', 'png']: if file_extension.lower() in ['jpg', 'jpeg', 'png']:
save_file_name = current_user.username + '.' + file_extension save_file_name = current_user.username + '.' + file_extension
file.save(os.path.join(app.config['UPLOAD_DIR'], 'avatar', save_file_name)) file.save(os.path.join(app.config['UPLOAD_DIR'], 'avatar', save_file_name))
else:
logging.error('Authenticated externally. User {0} is not allowed to update the avatar')
abort(400)
# update user profile
user = User(username=current_user.username, plain_text_password=new_password, firstname=firstname, lastname=lastname, email=email, avatar=save_file_name, reload_info=False) user = User(username=current_user.username, plain_text_password=new_password, firstname=firstname, lastname=lastname, email=email, avatar=save_file_name, reload_info=False)
user.update_profile() user.update_profile()
return render_template('user_profile.html', external_account=external_account) return render_template('user_profile.html')
@app.route('/user/avatar/<path:filename>') @app.route('/user/avatar/<path:filename>')

View File

@ -26,10 +26,10 @@ SQLA_DB_NAME = 'pda'
SQLALCHEMY_TRACK_MODIFICATIONS = True SQLALCHEMY_TRACK_MODIFICATIONS = True
# DATBASE - MySQL # DATBASE - MySQL
SQLALCHEMY_DATABASE_URI = 'mysql://'+SQLA_DB_USER+':'+SQLA_DB_PASSWORD+'@'+SQLA_DB_HOST+'/'+SQLA_DB_NAME #SQLALCHEMY_DATABASE_URI = 'mysql://'+SQLA_DB_USER+':'+SQLA_DB_PASSWORD+'@'+SQLA_DB_HOST+'/'+SQLA_DB_NAME
# DATABSE - SQLite # DATABSE - SQLite
#SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'pdns.db') SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'pdns.db')
# SAML Authnetication # SAML Authnetication
SAML_ENABLED = False SAML_ENABLED = False