Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve login form handling errors #93

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ The following configuration values exist for Flask-Multipass:
``MULTIPASS_FAILURE_CATEGORY`` Category of message when flashing after unsuccessful login
``MULTIPASS_ALL_MATCHING_IDENTITIES`` If true, all matching identities are passed after successful authentication
``MULTIPASS_REQUIRE_IDENTITY`` If true, ``IdentityRetrievalFailed`` is raised when no matching identities are found, otherwise empty list is passed
``MULTIPASS_HIDE_NO_SUCH_USER`` If true, ``InvalidCredentials`` instead of ``NoSuchUser`` is raised when no user is found in the system
====================================== =========================================

A configuration example can be found here: :ref:`config_example`
Expand Down
11 changes: 10 additions & 1 deletion flask_multipass/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@
from werkzeug.exceptions import NotFound

from flask_multipass.auth import AuthProvider
from flask_multipass.exceptions import GroupRetrievalFailed, IdentityRetrievalFailed, MultipassException
from flask_multipass.exceptions import (
GroupRetrievalFailed,
IdentityRetrievalFailed,
InvalidCredentials,
MultipassException,
NoSuchUser,
)
from flask_multipass.identity import IdentityProvider
from flask_multipass.util import (
get_canonical_provider_map,
Expand Down Expand Up @@ -72,6 +78,7 @@ def init_app(self, app):
app.config.setdefault('MULTIPASS_FAILURE_CATEGORY', 'error')
app.config.setdefault('MULTIPASS_ALL_MATCHING_IDENTITIES', False)
app.config.setdefault('MULTIPASS_REQUIRE_IDENTITY', True)
app.config.setdefault('MULTIPASS_HIDE_NO_SUCH_USER', False)
with app.app_context():
self._create_login_rule()
state.auth_providers = ImmutableDict(self._create_providers('AUTH', AuthProvider))
Expand Down Expand Up @@ -528,6 +535,8 @@ def handle_login_form(self, provider, data):
try:
response = provider.process_local_login(data)
except MultipassException as e:
if isinstance(e, NoSuchUser) and current_app.config['MULTIPASS_HIDE_NO_SUCH_USER']:
e = InvalidCredentials(e.provider)
ThiefMaster marked this conversation as resolved.
Show resolved Hide resolved
self.handle_auth_error(e)
else:
return response
Expand Down
3 changes: 2 additions & 1 deletion flask_multipass/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ def __init__(self, details=None, provider=None):
class InvalidCredentials(AuthenticationFailed):
"""Indicates a failure to authenticate using the given credentials."""

def __init__(self, details=None, provider=None):
def __init__(self, details=None, provider=None, identifier=None):
AuthenticationFailed.__init__(self, 'Invalid credentials', details=details, provider=provider)
self.identifier = identifier


class IdentityRetrievalFailed(MultipassException):
Expand Down
2 changes: 1 addition & 1 deletion flask_multipass/providers/ldap/providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def process_local_login(self, data):
raise NoSuchUser(provider=self)
current_ldap.connection.simple_bind_s(user_dn, password)
except INVALID_CREDENTIALS:
raise InvalidCredentials(provider=self)
raise InvalidCredentials(provider=self, identifier=data['username'])
auth_info = AuthInfo(self, identifier=user_data[self.ldap_settings['uid']][0])
return self.multipass.handle_auth_success(auth_info)

Expand Down
2 changes: 1 addition & 1 deletion flask_multipass/providers/sqlalchemy.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def process_local_login(self, data):
if not identity:
raise NoSuchUser(provider=self)
if not self.check_password(identity, data['password']):
raise InvalidCredentials(provider=self)
raise InvalidCredentials(provider=self, identifier=data['identifier'])
auth_info = AuthInfo(self, identity=identity)
return self.multipass.handle_auth_success(auth_info)

Expand Down
2 changes: 1 addition & 1 deletion flask_multipass/providers/static.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def process_local_login(self, data):
if password is None:
raise NoSuchUser(provider=self)
if password != data['password']:
raise InvalidCredentials(provider=self)
raise InvalidCredentials(provider=self, identifier=data['username'])
auth_info = AuthInfo(self, username=data['username'])
return self.multipass.handle_auth_success(auth_info)

Expand Down