Skip to content
Closed
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
41 changes: 36 additions & 5 deletions common/djangoapps/external_auth/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,10 +177,10 @@ def _external_login_or_signup(request,
return default_render_failure(request, failure_msg)
except User.DoesNotExist:
log.info('SHIB: No user for %s yet, doing signup', eamap.external_email)
return _signup(request, eamap)
return _signup(request, eamap, retfun)
else:
log.info('No user for %s yet. doing signup', eamap.external_email)
return _signup(request, eamap)
return _signup(request, eamap, retfun)

# We trust shib's authentication, so no need to authenticate using the password again
uname = internal_user.username
Expand All @@ -198,7 +198,7 @@ def _external_login_or_signup(request,
if user is None:
# we want to log the failure, but don't want to log the password attempted:
AUDIT_LOG.warning('External Auth Login failed for "%s"', uname)
return _signup(request, eamap)
return _signup(request, eamap, retfun)

if not user.is_active:
AUDIT_LOG.warning('User "%s" is not active after external login', uname)
Expand Down Expand Up @@ -237,7 +237,7 @@ def _flatten_to_ascii(txt):


@ensure_csrf_cookie
def _signup(request, eamap):
def _signup(request, eamap, retfun=None):
"""
Present form to complete for signup via external authentication.
Even though the user has external credentials, he/she still needs
Expand All @@ -246,10 +246,30 @@ def _signup(request, eamap):

eamap is an ExternalAuthMap object, specifying the external user
for which to complete the signup.

retfun is a function to execute for the return value, if immediate
signup is used. That allows @ssl_login_shortcut() to work.
"""
# save this for use by student.views.create_account
request.session['ExternalAuthMap'] = eamap

if settings.MITX_FEATURES.get('AUTH_USE_MIT_CERTIFICATES_IMMEDIATE_SIGNUP', False):
# 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',
)
ret = student.views.create_account(request, post_vars)
log.debug('doing immediate signup for %s, ret=%s' % (username, ret))
# should check return content for successful completion before continuing
if retfun is not None:
return retfun()
else:
return ret

# 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)
Expand Down Expand Up @@ -340,18 +360,26 @@ def wrapped(*args, **kwargs):
if not settings.MITX_FEATURES['AUTH_USE_MIT_CERTIFICATES']:
return fn(*args, **kwargs)
request = args[0]

if request.user and request.user.is_authenticated(): # don't re-authenticate
return fn(*args, **kwargs)

cert = _ssl_get_cert_from_request(request)
if not cert: # no certificate information - show normal login window
return fn(*args, **kwargs)

def retfun():
return fn(*args, **kwargs)

(_user, email, fullname) = _ssl_dn_extract_info(cert)
return _external_login_or_signup(
request,
external_id=email,
external_domain="ssl:MIT",
credentials=cert,
email=email,
fullname=fullname
fullname=fullname,
retfun=retfun,
)
return wrapped

Expand Down Expand Up @@ -902,6 +930,9 @@ def test_center_login(request):
'''
# Imports from lms/djangoapps/courseware -- these should not be
# in a common djangoapps.
# Required for Pearson
# this import must be here because the test center code imports this file (can't have import loops)
# also, the test center code really needs refactoring - it is a huge kludge
from courseware.views import get_module_for_descriptor, jump_to
from courseware.model_data import FieldDataCache

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to add a comment here explaining why the import is moved down here. (Because it's a dependency on LMS? Some other reason?)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And why only this, and not also ModelDataCache?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done - see comment for reason

Expand Down