diff --git a/common/djangoapps/external_auth/tests/test_openid_provider.py b/common/djangoapps/external_auth/tests/test_openid_provider.py
index 570dfbf9ee..1f093c93be 100644
--- a/common/djangoapps/external_auth/tests/test_openid_provider.py
+++ b/common/djangoapps/external_auth/tests/test_openid_provider.py
@@ -59,18 +59,15 @@ class MyFetcher(HTTPFetcher):
final_url=final_url,
headers=response_headers,
status=status,
- )
+ )
class OpenIdProviderTest(TestCase):
+ """
+ Tests of the OpenId login
+ """
-# def setUp(self):
-# username = 'viewtest'
-# email = 'view@test.com'
-# password = 'foo'
-# user = User.objects.create_user(username, email, password)
-
- def testBeginLoginWithXrdsUrl(self):
+ def test_begin_login_with_xrds_url(self):
# skip the test if openid is not enabled (as in cms.envs.test):
if not settings.MITX_FEATURES.get('AUTH_USE_OPENID') or not settings.MITX_FEATURES.get('AUTH_USE_OPENID_PROVIDER'):
return
@@ -99,7 +96,7 @@ class OpenIdProviderTest(TestCase):
"got code {0} for url '{1}'. Expected code {2}"
.format(resp.status_code, url, code))
- def testBeginLoginWithLoginUrl(self):
+ def test_begin_login_with_login_url(self):
# skip the test if openid is not enabled (as in cms.envs.test):
if not settings.MITX_FEATURES.get('AUTH_USE_OPENID') or not settings.MITX_FEATURES.get('AUTH_USE_OPENID_PROVIDER'):
return
@@ -150,45 +147,77 @@ class OpenIdProviderTest(TestCase):
#
#
-
- def testOpenIdSetup(self):
+ def test_open_id_setup(self):
if not settings.MITX_FEATURES.get('AUTH_USE_OPENID_PROVIDER'):
return
url = reverse('openid-provider-login')
post_args = {
- "openid.mode": "checkid_setup",
- "openid.return_to": "http://testserver/openid/complete/?janrain_nonce=2013-01-23T06%3A20%3A17ZaN7j6H",
- "openid.assoc_handle": "{HMAC-SHA1}{50ff8120}{rh87+Q==}",
- "openid.claimed_id": "http://specs.openid.net/auth/2.0/identifier_select",
- "openid.ns": "http://specs.openid.net/auth/2.0",
- "openid.realm": "http://testserver/",
- "openid.identity": "http://specs.openid.net/auth/2.0/identifier_select",
- "openid.ns.ax": "http://openid.net/srv/ax/1.0",
- "openid.ax.mode": "fetch_request",
- "openid.ax.required": "email,fullname,old_email,firstname,old_nickname,lastname,old_fullname,nickname",
- "openid.ax.type.fullname": "http://axschema.org/namePerson",
- "openid.ax.type.lastname": "http://axschema.org/namePerson/last",
- "openid.ax.type.firstname": "http://axschema.org/namePerson/first",
- "openid.ax.type.nickname": "http://axschema.org/namePerson/friendly",
- "openid.ax.type.email": "http://axschema.org/contact/email",
- "openid.ax.type.old_email": "http://schema.openid.net/contact/email",
- "openid.ax.type.old_nickname": "http://schema.openid.net/namePerson/friendly",
- "openid.ax.type.old_fullname": "http://schema.openid.net/namePerson",
- }
+ "openid.mode": "checkid_setup",
+ "openid.return_to": "http://testserver/openid/complete/?janrain_nonce=2013-01-23T06%3A20%3A17ZaN7j6H",
+ "openid.assoc_handle": "{HMAC-SHA1}{50ff8120}{rh87+Q==}",
+ "openid.claimed_id": "http://specs.openid.net/auth/2.0/identifier_select",
+ "openid.ns": "http://specs.openid.net/auth/2.0",
+ "openid.realm": "http://testserver/",
+ "openid.identity": "http://specs.openid.net/auth/2.0/identifier_select",
+ "openid.ns.ax": "http://openid.net/srv/ax/1.0",
+ "openid.ax.mode": "fetch_request",
+ "openid.ax.required": "email,fullname,old_email,firstname,old_nickname,lastname,old_fullname,nickname",
+ "openid.ax.type.fullname": "http://axschema.org/namePerson",
+ "openid.ax.type.lastname": "http://axschema.org/namePerson/last",
+ "openid.ax.type.firstname": "http://axschema.org/namePerson/first",
+ "openid.ax.type.nickname": "http://axschema.org/namePerson/friendly",
+ "openid.ax.type.email": "http://axschema.org/contact/email",
+ "openid.ax.type.old_email": "http://schema.openid.net/contact/email",
+ "openid.ax.type.old_nickname": "http://schema.openid.net/namePerson/friendly",
+ "openid.ax.type.old_fullname": "http://schema.openid.net/namePerson",
+ }
resp = self.client.post(url, post_args)
code = 200
self.assertEqual(resp.status_code, code,
"got code {0} for url '{1}'. Expected code {2}"
.format(resp.status_code, url, code))
+ def test_invalid_namespace(self):
+ """ Test for 403 error code when the namespace of the request is invalid"""
+ if not settings.MITX_FEATURES.get('AUTH_USE_OPENID_PROVIDER'):
+ return
+ url = reverse('openid-provider-login')
+ post_args = {
+ "openid.mode": "checkid_setup",
+ "openid.return_to": "http://testserver/openid/complete/?janrain_nonce=2013-01-23T06%3A20%3A17ZaN7j6H",
+ "openid.assoc_handle": "{HMAC-SHA1}{50ff8120}{rh87+Q==}",
+ "openid.claimed_id": "http://specs.openid.net/auth/2.0/identifier_select",
+ "openid.ns": "http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0",
+ "openid.realm": "http://testserver/",
+ "openid.identity": "http://specs.openid.net/auth/2.0/identifier_select",
+ "openid.ns.ax": "http://openid.net/srv/ax/1.0",
+ "openid.ax.mode": "fetch_request",
+ "openid.ax.required": "email,fullname,old_email,firstname,old_nickname,lastname,old_fullname,nickname",
+ "openid.ax.type.fullname": "http://axschema.org/namePerson",
+ "openid.ax.type.lastname": "http://axschema.org/namePerson/last",
+ "openid.ax.type.firstname": "http://axschema.org/namePerson/first",
+ "openid.ax.type.nickname": "http://axschema.org/namePerson/friendly",
+ "openid.ax.type.email": "http://axschema.org/contact/email",
+ "openid.ax.type.old_email": "http://schema.openid.net/contact/email",
+ "openid.ax.type.old_nickname": "http://schema.openid.net/namePerson/friendly",
+ "openid.ax.type.old_fullname": "http://schema.openid.net/namePerson",
+ }
+ resp = self.client.post(url, post_args)
+ code = 403
+ self.assertEqual(resp.status_code, code,
+ "got code {0} for url '{1}'. Expected code {2}"
+ .format(resp.status_code, url, code))
+
-# In order for this absolute URL to work (i.e. to get xrds, then authentication)
-# in the test environment, we either need a live server that works with the default
-# fetcher (i.e. urlopen2), or a test server that is reached through a custom fetcher.
-# Here we do the former.
class OpenIdProviderLiveServerTest(LiveServerTestCase):
+ """
+ In order for this absolute URL to work (i.e. to get xrds, then authentication)
+ in the test environment, we either need a live server that works with the default
+ fetcher (i.e. urlopen2), or a test server that is reached through a custom fetcher.
+ Here we do the former.
+ """
- def testBeginLogin(self):
+ def test_begin_login(self):
# skip the test if openid is not enabled (as in cms.envs.test):
if not settings.MITX_FEATURES.get('AUTH_USE_OPENID') or not settings.MITX_FEATURES.get('AUTH_USE_OPENID_PROVIDER'):
return
diff --git a/common/djangoapps/external_auth/views.py b/common/djangoapps/external_auth/views.py
index 06709eff9e..50deb5c449 100644
--- a/common/djangoapps/external_auth/views.py
+++ b/common/djangoapps/external_auth/views.py
@@ -36,7 +36,7 @@ import django_openid_auth.views as openid_views
from django_openid_auth import auth as openid_auth
from openid.consumer.consumer import SUCCESS
-from openid.server.server import Server
+from openid.server.server import Server, ProtocolError
from openid.server.trustroot import TrustRoot
from openid.extensions import ax, sreg
@@ -102,7 +102,7 @@ def openid_login_complete(request,
oid_backend = openid_auth.OpenIDBackend()
details = oid_backend._extract_user_details(openid_response)
- log.debug('openid success, details=%s' % details)
+ log.debug('openid success, details={0}'.format(details))
url = getattr(settings, 'OPENID_SSO_SERVER_URL', None)
external_domain = "openid:%s" % url
@@ -132,7 +132,7 @@ def external_login_or_signup(request,
try:
eamap = ExternalAuthMap.objects.get(external_id=external_id,
external_domain=external_domain)
- log.debug('Found eamap=%s' % eamap)
+ log.debug('Found eamap={0}'.format(eamap))
except ExternalAuthMap.DoesNotExist:
# go render form for creating edX user
eamap = ExternalAuthMap(external_id=external_id,
@@ -141,11 +141,11 @@ def external_login_or_signup(request,
eamap.external_email = email
eamap.external_name = fullname
eamap.internal_password = generate_password()
- log.debug('Created eamap=%s' % eamap)
+ log.debug('Created eamap={0}'.format(eamap))
eamap.save()
- log.info("External_Auth login_or_signup for %s : %s : %s : %s" % (external_domain, external_id, email, fullname))
+ log.info(u"External_Auth login_or_signup for {0} : {1} : {2} : {3}".format(external_domain, external_id, email, fullname))
internal_user = eamap.user
if internal_user is None:
if settings.MITX_FEATURES.get('AUTH_USE_SHIB'):
@@ -157,7 +157,7 @@ def external_login_or_signup(request,
eamap.user = link_user
eamap.save()
internal_user = link_user
- log.info('SHIB: Linking existing account for %s' % eamap.external_email)
+ log.info('SHIB: Linking existing account for {0}'.format(eamap.external_email))
# now pass through to log in
else:
# otherwise, there must have been an error, b/c we've already linked a user with these external
@@ -168,10 +168,10 @@ def external_login_or_signup(request,
% getattr(settings, 'TECH_SUPPORT_EMAIL', 'techsupport@class.stanford.edu')))
return default_render_failure(request, failure_msg)
except User.DoesNotExist:
- log.info('SHIB: No user for %s yet, doing signup' % eamap.external_email)
+ log.info('SHIB: No user for {0} yet, doing signup'.format(eamap.external_email))
return signup(request, eamap)
else:
- log.info('No user for %s yet, doing signup' % eamap.external_email)
+ log.info('No user for {0} yet.formatdoing signup'.format(eamap.external_email))
return signup(request, eamap)
# We trust shib's authentication, so no need to authenticate using the password again
@@ -183,17 +183,17 @@ def external_login_or_signup(request,
else:
auth_backend = 'django.contrib.auth.backends.ModelBackend'
user.backend = auth_backend
- log.info('SHIB: Logging in linked user %s' % user.email)
+ log.info('SHIB: Logging in linked user {0}'.format(user.email))
else:
uname = internal_user.username
user = authenticate(username=uname, password=eamap.internal_password)
if user is None:
- log.warning("External Auth Login failed for %s / %s" %
- (uname, eamap.internal_password))
+ log.warning("External Auth Login failed for {0} / {1}".format(
+ uname, eamap.internal_password))
return signup(request, eamap)
if not user.is_active:
- log.warning("User %s is not active" % (uname))
+ log.warning("User {0} is not active".format(uname))
# TODO: improve error page
msg = 'Account not yet activated: please look for link in your email'
return default_render_failure(request, msg)
@@ -261,7 +261,7 @@ def signup(request, eamap=None):
except ValidationError:
context['ask_for_email'] = True
- log.info('EXTAUTH: Doing signup for %s' % eamap.external_id)
+ log.info('EXTAUTH: Doing signup for {0}'.format(eamap.external_id))
return student_views.register_user(request, extra_context=context)
@@ -405,7 +405,7 @@ def shib_login(request):
shib['sn'] = shib['sn'].split(";")[0].strip().capitalize().decode('utf-8')
shib['givenName'] = shib['givenName'].split(";")[0].strip().capitalize().decode('utf-8')
- log.info("SHIB creds returned: %r" % shib)
+ log.info("SHIB creds returned: {0}".format(shib))
return external_login_or_signup(request,
external_id=shib['REMOTE_USER'],
@@ -640,7 +640,10 @@ def provider_login(request):
error = False
if 'openid.mode' in request.GET or 'openid.mode' in request.POST:
# decode request
- openid_request = server.decodeRequest(querydict)
+ try:
+ openid_request = server.decodeRequest(querydict)
+ except ProtocolError:
+ return default_render_failure(request, "Invalid OpenID request")
if not openid_request:
return default_render_failure(request, "Invalid OpenID request")
@@ -720,8 +723,6 @@ def provider_login(request):
if 'openid_error' in request.session:
del request.session['openid_error']
- # fullname field comes from user profile
- profile = UserProfile.objects.get(user=user)
log.info("OpenID login success - {0} ({1})".format(user.username,
user.email))