Commit c8adbe38 by brianhw

Merge pull request #1182 from carsongee/add_mitx_ssl_bypass_signup

Add feature to do auto signup with external auth
parents 62a25824 3ad705cd
......@@ -98,3 +98,4 @@ Olivier Marquez <oliviermarquez@gmail.com>
Florian Dufour <neurolit@gmail.com>
Manuel Freire <manuel.freire@fdi.ucm.es>
Daniel Cebrián Robles <danielcebrianr@gmail.com>
Carson Gee <cgee@mit.edu>
"""
Provides unit tests for SSL based authentication portions
of the external_auth app.
"""
import unittest
from django.conf import settings
from django.contrib.auth.models import AnonymousUser, User
from django.contrib.sessions.middleware import SessionMiddleware
from django.core.urlresolvers import reverse
from django.test import TestCase
from django.test.client import Client
from django.test.client import RequestFactory
from django.test.utils import override_settings
from external_auth.models import ExternalAuthMap
import external_auth.views
MITX_FEATURES_WITH_SSL_AUTH = settings.MITX_FEATURES.copy()
MITX_FEATURES_WITH_SSL_AUTH['AUTH_USE_MIT_CERTIFICATES'] = True
MITX_FEATURES_WITH_SSL_AUTH_IMMEDIATE_SIGNUP = MITX_FEATURES_WITH_SSL_AUTH.copy()
MITX_FEATURES_WITH_SSL_AUTH_IMMEDIATE_SIGNUP['AUTH_USE_MIT_CERTIFICATES_IMMEDIATE_SIGNUP'] = True
@override_settings(MITX_FEATURES=MITX_FEATURES_WITH_SSL_AUTH)
class SSLClientTest(TestCase):
"""
Tests SSL Authentication code sections of external_auth
"""
AUTH_DN = '/C=US/ST=Massachusetts/O=Massachusetts Institute of Technology/OU=Client CA v1/CN={0}/emailAddress={1}'
USER_NAME = 'test_user_ssl'
USER_EMAIL = 'test_user_ssl@EDX.ORG'
def _create_ssl_request(self, url):
"""Creates a basic request for SSL use."""
request = self.factory.get(url)
request.META['SSL_CLIENT_S_DN'] = self.AUTH_DN.format(self.USER_NAME, self.USER_EMAIL)
request.user = AnonymousUser()
middleware = SessionMiddleware()
middleware.process_request(request)
request.session.save()
return request
def setUp(self):
"""Setup test case by adding primary user."""
super(SSLClientTest, self).setUp()
self.client = Client()
self.factory = RequestFactory()
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
def test_ssl_login_with_signup_lms(self):
"""
Validate that an SSL login creates an eamap user and
redirects them to the signup page.
"""
response = external_auth.views.ssl_login(self._create_ssl_request('/'))
# Response should contain template for signup form, eamap should have user, and internal
# auth should not have a user
self.assertIn('<form role="form" id="register-form" method="post"', response.content)
try:
ExternalAuthMap.objects.get(external_id=self.USER_EMAIL)
except ExternalAuthMap.DoesNotExist, ex:
self.fail('User did not get properly added to external auth map, exception was {0}'.format(str(ex)))
with self.assertRaises(User.DoesNotExist):
User.objects.get(email=self.USER_EMAIL)
@unittest.skipUnless(settings.ROOT_URLCONF == 'cms.urls', 'Test only valid in cms')
@unittest.skip
def test_ssl_login_with_signup_cms(self):
"""
Validate that an SSL login creates an eamap user and
redirects them to the signup page on CMS.
This currently is failing and should be resolved to passing at
some point. using skip here instead of expectFailure because
of an issue with nose.
"""
self.client.get(
reverse('contentstore.views.login_page'),
SSL_CLIENT_S_DN=self.AUTH_DN.format(self.USER_NAME, self.USER_EMAIL)
)
try:
ExternalAuthMap.objects.get(external_id=self.USER_EMAIL)
except ExternalAuthMap.DoesNotExist, ex:
self.fail('User did not get properly added to external auth map, exception was {0}'.format(str(ex)))
with self.assertRaises(User.DoesNotExist):
User.objects.get(email=self.USER_EMAIL)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
@override_settings(MITX_FEATURES=MITX_FEATURES_WITH_SSL_AUTH_IMMEDIATE_SIGNUP)
def test_ssl_login_without_signup_lms(self):
"""
Test IMMEDIATE_SIGNUP feature flag and ensure the user account is automatically created
and the user is redirected to slash.
"""
external_auth.views.ssl_login(self._create_ssl_request('/'))
# Assert our user exists in both eamap and Users, and that we are logged in
try:
ExternalAuthMap.objects.get(external_id=self.USER_EMAIL)
except ExternalAuthMap.DoesNotExist, ex:
self.fail('User did not get properly added to external auth map, exception was {0}'.format(str(ex)))
try:
User.objects.get(email=self.USER_EMAIL)
except ExternalAuthMap.DoesNotExist, ex:
self.fail('User did not get properly added to internal users, exception was {0}'.format(str(ex)))
@unittest.skipUnless(settings.ROOT_URLCONF == 'cms.urls', 'Test only valid in cms')
@override_settings(MITX_FEATURES=MITX_FEATURES_WITH_SSL_AUTH_IMMEDIATE_SIGNUP)
@unittest.skip
def test_ssl_login_without_signup_cms(self):
"""
Test IMMEDIATE_SIGNUP feature flag and ensure the user account is
automatically created on CMS.
This currently is failing and should be resolved to passing at
some point. using skip here instead of expectFailure because
of an issue with nose.
"""
self.client.get(
reverse('contentstore.views.login_page'),
SSL_CLIENT_S_DN=self.AUTH_DN.format(self.USER_NAME, self.USER_EMAIL)
)
# Assert our user exists in both eamap and Users, and that we are logged in
try:
ExternalAuthMap.objects.get(external_id=self.USER_EMAIL)
except ExternalAuthMap.DoesNotExist, ex:
self.fail('User did not get properly added to external auth map, exception was {0}'.format(str(ex)))
try:
User.objects.get(email=self.USER_EMAIL)
except ExternalAuthMap.DoesNotExist, ex:
self.fail('User did not get properly added to internal users, exception was {0}'.format(str(ex)))
......@@ -250,6 +250,18 @@ def _signup(request, eamap):
# save this for use by student.views.create_account
request.session['ExternalAuthMap'] = eamap
if settings.MITX_FEATURES.get('AUTH_USE_MIT_CERTIFICATES_IMMEDIATE_SIGNUP', ''):
# do signin immediately, by calling create_account, instead of asking
# student to fill in form. MIT students already have information filed.
username = eamap.external_email.split('@', 1)[0]
username = username.replace('.', '_')
post_vars = dict(username=username,
honor_code=u'true',
terms_of_service=u'true')
log.info('doing immediate signup for %s, params=%s', username, post_vars)
student.views.create_account(request, post_vars)
return redirect('/')
# default conjoin name, no spaces, flattened to ascii b/c django can't handle unicode usernames, sadly
# but this only affects username, not fullname
username = re.sub(r'\s', '', _flatten_to_ascii(eamap.external_name), flags=re.UNICODE)
......
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