Authenticator: automatically choose authentication backend

and test other backends, if one fails.

Written-by: Rudolf Mayerhofer <rm@eightyfive.net>
Signed-off-by: Ralf Ramsauer <ralf@binary-kitchen.de>
[ralf: also remove the authentication method from any other code path]
This commit is contained in:
Ralf Ramsauer 2018-11-27 08:40:23 +01:00
parent 90ea795c1b
commit eaf2537d83
3 changed files with 9 additions and 36 deletions

View File

@ -102,14 +102,10 @@ class Authenticator:
if self._simulate: if self._simulate:
log.info('SIMULATION MODE! ACCEPTING ANYTHING!') log.info('SIMULATION MODE! ACCEPTING ANYTHING!')
return DoorlockResponse.Success return DoorlockResponse.Success
if AuthMethod.LDAP_USER_PW in self._backends:
method = credentials[0] retval = self._try_auth_ldap(credentials[0], credentials[1])
if method not in self._backends: if retval == DoorlockResponse.Success:
return DoorlockResponse.InternalError return retval
if AuthMethod.LOCAL_USER_DB in self._backends:
if method == AuthMethod.LDAP_USER_PW: return self._try_auth_local(credentials[0], credentials[1])
return self._try_auth_ldap(credentials[1], credentials[2]) return DoorlockResponse.Perm
elif method == AuthMethod.LOCAL_USER_DB:
return self._try_auth_local(credentials[1], credentials[2])
return DoorlockResponse.InternalError

View File

@ -45,7 +45,6 @@ def emit_doorstate(response=None):
class AuthenticationForm(FlaskForm): class AuthenticationForm(FlaskForm):
username = StringField('Username', [Length(min=3, max=25)]) username = StringField('Username', [Length(min=3, max=25)])
password = PasswordField('Password', [DataRequired()]) password = PasswordField('Password', [DataRequired()])
method = StringField('Method', [DataRequired()])
open = SubmitField('Open') open = SubmitField('Open')
present = SubmitField('Present') present = SubmitField('Present')
close = SubmitField('Close') close = SubmitField('Close')
@ -63,11 +62,6 @@ class AuthenticationForm(FlaskForm):
elif self.present.data: elif self.present.data:
self.desired_state = DoorState.Present self.desired_state = DoorState.Present
if self.method.data == 'Local':
self.method = AuthMethod.LOCAL_USER_DB
else: # default: use LDAP
self.method = AuthMethod.LDAP_USER_PW
return True return True
@ -98,16 +92,10 @@ def api():
json['status'] = logic.state.value json['status'] = logic.state.value
return jsonify(json) return jsonify(json)
method = request.form.get('method')
user = request.form.get('user') user = request.form.get('user')
password = request.form.get('pass') password = request.form.get('pass')
command = request.form.get('command') command = request.form.get('command')
if method == 'local':
method = AuthMethod.LOCAL_USER_DB
else: # 'ldap' or default
method = AuthMethod.LDAP_USER_PW
if any(v is None for v in [user, password, command]): if any(v is None for v in [user, password, command]):
log.warning('Incomplete API request') log.warning('Incomplete API request')
abort(400) abort(400)
@ -117,7 +105,7 @@ def api():
return json_response(DoorlockResponse.Inval, return json_response(DoorlockResponse.Inval,
'Invalid username or password format') 'Invalid username or password format')
credentials = method, user, password credentials = user, password
if command == 'status': if command == 'status':
return json_response(logic.auth.try_auth(credentials)) return json_response(logic.auth.try_auth(credentials))
@ -143,11 +131,9 @@ def home():
if request.method == 'POST' and authentication_form.validate(): if request.method == 'POST' and authentication_form.validate():
user = authentication_form.username.data user = authentication_form.username.data
password = authentication_form.password.data password = authentication_form.password.data
method = authentication_form.method credentials = user, password
credentials = method, user, password
log.info('Incoming request from %s' % user.encode('utf-8')) log.info('Incoming request from %s' % user.encode('utf-8'))
log.info(' authentication method: %s' % method)
desired_state = authentication_form.desired_state desired_state = authentication_form.desired_state
log.info(' desired state: %s' % desired_state) log.info(' desired state: %s' % desired_state)
log.info(' current state: %s' % logic.state) log.info(' current state: %s' % logic.state)
@ -159,7 +145,6 @@ def home():
return render_template('index.html', return render_template('index.html',
authentication_form=authentication_form, authentication_form=authentication_form,
auth_backends=logic.auth.backends,
response=response, response=response,
state_text=str(logic.state), state_text=str(logic.state),
led=logic.state.to_img(), led=logic.state.to_img(),

View File

@ -23,14 +23,6 @@
<label class="control-label" for="password">Password</label> <label class="control-label" for="password">Password</label>
<input class="form-control" id="password" name="password" required type="password" value=""> <input class="form-control" id="password" name="password" required type="password" value="">
</div> </div>
<div class="form-group">
<label for="method">Authentication method</label>
<select name="method" id="method" class="form-control">
{% for backend in auth_backends %}
<option>{{ backend }}</option>
{% endfor %}
</select>
</div>
<input class="btn btn-success btn-lg btn-block" id="open" name="open" type="submit" value="Open"> <input class="btn btn-success btn-lg btn-block" id="open" name="open" type="submit" value="Open">
<input class="btn btn-warning btn-lg btn-block" id="present" name="present" type="submit" value="Present"> <input class="btn btn-warning btn-lg btn-block" id="present" name="present" type="submit" value="Present">
<input class="btn btn-danger btn-lg btn-block" id="close" name="close" type="submit" value="Close"> <input class="btn btn-danger btn-lg btn-block" id="close" name="close" type="submit" value="Close">