Commit 7e1edd43 by James Tait

Enable restricting acceptable account verification schemes per provider.

parent e035fb2f
......@@ -193,6 +193,12 @@ representing what measures they have taken to validate the e-mail address
included in the response. To change the list of schemes acceptable for your
purposes you can change the setting:
OPENID_VALID_VERIFICATION_SCHEMES = (
'token_via_email',
)
OPENID_VALID_VERIFICATION_SCHEMES = {
None: (),
'http://example.com/': ('token_via_email',),
}
The element with the None key specifies a list of verification schemes that
will be accepted as trusted from OpenID Providers that we haven't explicitly
configured. These are, almost by definition, untrusted, so it is strongly
recommended that this list remain empty.
......@@ -45,6 +45,7 @@ from django_openid_auth.exceptions import (
RequiredAttributeNotReturned,
)
class OpenIDBackend:
"""A django.contrib.auth backend that authenticates the user based on
an OpenID response."""
......@@ -163,8 +164,12 @@ class OpenIDBackend:
first_name = u''
last_name = fullname
verified = verified in getattr(
settings, 'OPENID_VALID_VERIFICATION_SCHEMES', ())
verification_scheme_map = getattr(
settings, 'OPENID_VALID_VERIFICATION_SCHEMES', {})
valid_schemes = verification_scheme_map.get(
openid_response.endpoint.server_url,
verification_scheme_map.get(None, ()))
verified = (verified in valid_schemes)
return dict(email=email, nickname=nickname, account_verified=verified,
first_name=first_name, last_name=last_name)
......@@ -172,8 +177,7 @@ class OpenIDBackend:
def _get_preferred_username(self, nickname, email):
if nickname:
return nickname
if email and getattr(settings, 'OPENID_USE_EMAIL_FOR_USERNAME',
False):
if email and getattr(settings, 'OPENID_USE_EMAIL_FOR_USERNAME', False):
suggestion = ''.join([x for x in email if x.isalnum()])
if suggestion:
return suggestion
......
......@@ -62,6 +62,7 @@ from django_openid_auth.exceptions import (
ET = importElementTree()
class StubOpenIDProvider(HTTPFetcher):
def __init__(self, base_url):
......@@ -175,22 +176,35 @@ class RelyingPartyTests(TestCase):
self.server = Server(DjangoOpenIDStore(), op_endpoint=server_url)
setDefaultFetcher(self.provider, wrap_exceptions=False)
self.old_login_redirect_url = getattr(settings, 'LOGIN_REDIRECT_URL', '/accounts/profile/')
self.old_create_users = getattr(settings, 'OPENID_CREATE_USERS', False)
self.old_strict_usernames = getattr(settings, 'OPENID_STRICT_USERNAMES', False)
self.old_update_details = getattr(settings, 'OPENID_UPDATE_DETAILS_FROM_SREG', False)
self.old_sso_server_url = getattr(settings, 'OPENID_SSO_SERVER_URL', None)
self.old_teams_map = getattr(settings, 'OPENID_LAUNCHPAD_TEAMS_MAPPING', {})
self.old_use_as_admin_login = getattr(settings, 'OPENID_USE_AS_ADMIN_LOGIN', False)
self.old_follow_renames = getattr(settings, 'OPENID_FOLLOW_RENAMES', False)
self.old_physical_multifactor = getattr(settings, 'OPENID_PHYSICAL_MULTIFACTOR_REQUIRED', False)
self.old_login_render_failure = getattr(settings, 'OPENID_RENDER_FAILURE', None)
self.old_consumer_complete = Consumer.complete
self.old_openid_use_email_for_username = getattr(settings,
self.old_login_redirect_url = getattr(
settings, 'LOGIN_REDIRECT_URL', '/accounts/profile/')
self.old_create_users = getattr(
settings, 'OPENID_CREATE_USERS', False)
self.old_strict_usernames = getattr(
settings, 'OPENID_STRICT_USERNAMES', False)
self.old_update_details = getattr(
settings, 'OPENID_UPDATE_DETAILS_FROM_SREG', False)
self.old_sso_server_url = getattr(
settings, 'OPENID_SSO_SERVER_URL', None)
self.old_teams_map = getattr(
settings, 'OPENID_LAUNCHPAD_TEAMS_MAPPING', {})
self.old_use_as_admin_login = getattr(
settings, 'OPENID_USE_AS_ADMIN_LOGIN', False)
self.old_follow_renames = getattr(
settings, 'OPENID_FOLLOW_RENAMES', False)
self.old_physical_multifactor = getattr(
settings, 'OPENID_PHYSICAL_MULTIFACTOR_REQUIRED', False)
self.old_login_render_failure = getattr(
settings, 'OPENID_RENDER_FAILURE', None)
self.old_openid_use_email_for_username = getattr(
settings,
'OPENID_USE_EMAIL_FOR_USERNAME', False)
self.old_required_fields = getattr(
settings, 'OPENID_SREG_REQUIRED_FIELDS', [])
self.old_valid_verification_schemes = getattr(
settings, 'OPENID_VALID_VERIFICATION_SCHEMES', {})
self.old_consumer_complete = Consumer.complete
settings.OPENID_CREATE_USERS = False
settings.OPENID_STRICT_USERNAMES = False
......@@ -202,6 +216,7 @@ class RelyingPartyTests(TestCase):
settings.OPENID_PHYSICAL_MULTIFACTOR_REQUIRED = False
settings.OPENID_SREG_REQUIRED_FIELDS = []
settings.OPENID_USE_EMAIL_FOR_USERNAME = False
settings.OPENID_VALID_VERIFICATION_SCHEMES = {}
def tearDown(self):
settings.LOGIN_REDIRECT_URL = self.old_login_redirect_url
......@@ -212,11 +227,15 @@ class RelyingPartyTests(TestCase):
settings.OPENID_LAUNCHPAD_TEAMS_MAPPING = self.old_teams_map
settings.OPENID_USE_AS_ADMIN_LOGIN = self.old_use_as_admin_login
settings.OPENID_FOLLOW_RENAMES = self.old_follow_renames
settings.OPENID_PHYSICAL_MULTIFACTOR_REQUIRED = self.old_physical_multifactor
settings.OPENID_PHYSICAL_MULTIFACTOR_REQUIRED = (
self.old_physical_multifactor)
settings.OPENID_RENDER_FAILURE = self.old_login_render_failure
Consumer.complete = self.old_consumer_complete
settings.OPENID_SREG_REQUIRED_FIELDS = self.old_required_fields
settings.OPENID_USE_EMAIL_FOR_USERNAME = self.old_openid_use_email_for_username
settings.OPENID_USE_EMAIL_FOR_USERNAME = (
self.old_openid_use_email_for_username)
settings.OPENID_VALID_VERIFICATION_SCHEMES = (
self.old_valid_verification_schemes)
setDefaultFetcher(None)
super(RelyingPartyTests, self).tearDown()
......@@ -231,7 +250,8 @@ class RelyingPartyTests(TestCase):
redirect_to = webresponse.headers['location']
self.assertTrue(redirect_to.startswith(
'http://testserver/openid/complete/'))
return self.client.get('/openid/complete/',
return self.client.get(
'/openid/complete/',
dict(cgi.parse_qsl(redirect_to.split('?', 1)[1])))
def test_login(self):
......@@ -1226,14 +1246,37 @@ class RelyingPartyTests(TestCase):
self.assertEqual(user_openid.account_verified, is_verified)
def test_login_attribute_exchange_with_validation(self):
settings.OPENID_VALID_VERIFICATION_SCHEMES = {
self.provider.endpoint_url: ('token_via_email',),
}
self._test_login_attribute_exchange('token_via_email', True)
def test_login_attribute_exchange_without_validation(self):
settings.OPENID_VALID_VERIFICATION_SCHEMES = {
self.provider.endpoint_url: ('token_via_email',),
}
self._test_login_attribute_exchange(None, False)
def test_login_attribute_exchange_unrecognised_validation(self):
settings.OPENID_VALID_VERIFICATION_SCHEMES = {
self.provider.endpoint_url: ('token_via_email',),
}
self._test_login_attribute_exchange('unrecognised_scheme', False)
def test_login_attribute_exchange_different_default_validation(self):
settings.OPENID_VALID_VERIFICATION_SCHEMES = {
None: ('token_via_email', 'sms'),
'http://otherprovider/': ('unrecognised_scheme',),
}
self._test_login_attribute_exchange('unrecognised_scheme', False)
def test_login_attribute_exchange_matched_default_validation(self):
settings.OPENID_VALID_VERIFICATION_SCHEMES = {
None: ('token_via_email',),
'http://otherprovider/': ('unrecognised_scheme',),
}
self._test_login_attribute_exchange('token_via_email', True)
def test_login_teams(self):
settings.OPENID_LAUNCHPAD_TEAMS_MAPPING_AUTO = False
settings.OPENID_LAUNCHPAD_TEAMS_MAPPING = {'teamname': 'groupname',
......
......@@ -133,11 +133,13 @@ OPENID_CREATE_USERS = True
# data received via Simple Registration?
OPENID_UPDATE_DETAILS_FROM_SREG = True
# List of recognised account verification schemes returned in response to a
# http://ns.login.ubuntu.com/2013/validation/account request
OPENID_VALID_VERIFICATION_SCHEMES = (
'token_via_email',
)
# Map of OpenID Provider base URLs to recognised account verification schemes
# returned in response to a http://ns.login.ubuntu.com/2013/validation/account
# request. Use None as the key in place of a URL to specify verification
# schemes that will be trusted from unknown OpenID Providers (not recommended).
OPENID_VALID_VERIFICATION_SCHEMES = {
None: (),
}
# If set, always use this as the identity URL rather than asking the
# user. This only makes sense if it is a server URL.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment