From 9653631e9aa37c19abb06c2a7459df77538093e3 Mon Sep 17 00:00:00 2001 From: Brian Wilson Date: Tue, 22 Jan 2013 11:15:30 -0500 Subject: [PATCH] Add initial openid_provider tests (covers xrds and authentication requests) --- .../external_auth/tests/__init__.py | 0 .../tests/test_openid_provider.py | 155 ++++++++++++++++++ lms/envs/test.py | 7 + 3 files changed, 162 insertions(+) create mode 100644 common/djangoapps/external_auth/tests/__init__.py create mode 100644 common/djangoapps/external_auth/tests/test_openid_provider.py diff --git a/common/djangoapps/external_auth/tests/__init__.py b/common/djangoapps/external_auth/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/common/djangoapps/external_auth/tests/test_openid_provider.py b/common/djangoapps/external_auth/tests/test_openid_provider.py new file mode 100644 index 0000000000..dce956095b --- /dev/null +++ b/common/djangoapps/external_auth/tests/test_openid_provider.py @@ -0,0 +1,155 @@ +''' +Created on Jan 18, 2013 + +@author: brian +''' +import openid +from openid.fetchers import HTTPFetcher, HTTPResponse +from urlparse import parse_qs + +from django.conf import settings +from django.test import TestCase, LiveServerTestCase +# from django.contrib.auth.models import User +from django.core.urlresolvers import reverse +from django.test.client import RequestFactory + +class MyFetcher(HTTPFetcher): + """A fetcher that uses server-internal calls for performing HTTP + requests. + """ + + def __init__(self, client): + """@param client: A test client object""" + + super(MyFetcher, self).__init__() + self.client = client + + def fetch(self, url, body=None, headers=None): + """Perform an HTTP request + + @raises Exception: Any exception that can be raised by Django + + @see: C{L{HTTPFetcher.fetch}} + """ + if body: + # method = 'POST' + # undo the URL encoding of the POST arguments + data = parse_qs(body) + response = self.client.post(url, data) + else: + # method = 'GET' + data = {} + if headers and 'Accept' in headers: + data['CONTENT_TYPE'] = headers['Accept'] + response = self.client.get(url, data) + + # Translate the test client response to the fetcher's HTTP response abstraction + content = response.content + final_url = url + response_headers = {} + if 'Content-Type' in response: + response_headers['content-type'] = response['Content-Type'] + if 'X-XRDS-Location' in response: + response_headers['x-xrds-location'] = response['X-XRDS-Location'] + status = response.status_code + + return HTTPResponse( + body=content, + final_url=final_url, + headers=response_headers, + status=status, + ) + +class OpenIdProviderTest(TestCase): + +# def setUp(self): +# username = 'viewtest' +# email = 'view@test.com' +# password = 'foo' +# user = User.objects.create_user(username, email, password) + + def testBeginLoginWithXrdsUrl(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 + + # the provider URL must be converted to an absolute URL in order to be + # used as an openid provider. + provider_url = reverse('openid-provider-xrds') + factory = RequestFactory() + request = factory.request() + abs_provider_url = request.build_absolute_uri(location = provider_url) + + # 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 latter: + fetcher = MyFetcher(self.client) + openid.fetchers.setDefaultFetcher(fetcher, wrap_exceptions=False) + + # now we can begin the login process by invoking a local openid client, + # with a pointer to the (also-local) openid provider: + with self.settings(OPENID_SSO_SERVER_URL = abs_provider_url): + url = reverse('openid-login') + resp = self.client.post(url) + code = 200 + self.assertEqual(resp.status_code, code, + "got code {0} for url '{1}'. Expected code {2}" + .format(resp.status_code, url, code)) + + def testBeginLoginWithLoginUrl(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 + + # the provider URL must be converted to an absolute URL in order to be + # used as an openid provider. + provider_url = reverse('openid-provider-login') + factory = RequestFactory() + request = factory.request() + abs_provider_url = request.build_absolute_uri(location = provider_url) + + # 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 latter: + fetcher = MyFetcher(self.client) + openid.fetchers.setDefaultFetcher(fetcher, wrap_exceptions=False) + + # now we can begin the login process by invoking a local openid client, + # with a pointer to the (also-local) openid provider: + with self.settings(OPENID_SSO_SERVER_URL = abs_provider_url): + url = reverse('openid-login') + resp = self.client.post(url) + code = 200 + 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): + + def testBeginLogin(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 + + # the provider URL must be converted to an absolute URL in order to be + # used as an openid provider. + provider_url = reverse('openid-provider-xrds') + factory = RequestFactory() + request = factory.request() + abs_provider_url = request.build_absolute_uri(location = provider_url) + + # now we can begin the login process by invoking a local openid client, + # with a pointer to the (also-local) openid provider: + with self.settings(OPENID_SSO_SERVER_URL = abs_provider_url): + url = reverse('openid-login') + resp = self.client.post(url) + code = 200 + self.assertEqual(resp.status_code, code, + "got code {0} for url '{1}'. Expected code {2}" + .format(resp.status_code, url, code)) diff --git a/lms/envs/test.py b/lms/envs/test.py index e9e4a43c6f..c77effbead 100644 --- a/lms/envs/test.py +++ b/lms/envs/test.py @@ -125,8 +125,15 @@ SECRET_KEY = '85920908f28904ed733fe576320db18cabd7b6cd' ################################## OPENID ###################################### MITX_FEATURES['AUTH_USE_OPENID'] = True MITX_FEATURES['AUTH_USE_OPENID_PROVIDER'] = True + +OPENID_CREATE_USERS = False +OPENID_UPDATE_DETAILS_FROM_SREG = True +OPENID_USE_AS_ADMIN_LOGIN = False OPENID_PROVIDER_TRUSTED_ROOTS = ['*'] +INSTALLED_APPS += ('external_auth',) +INSTALLED_APPS += ('django_openid_auth',) + ############################ STATIC FILES ############################# DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage' MEDIA_ROOT = TEST_ROOT / "uploads"