diff --git a/cms/djangoapps/contentstore/views.py b/cms/djangoapps/contentstore/views.py index 93f867549c..dd85c207e6 100644 --- a/cms/djangoapps/contentstore/views.py +++ b/cms/djangoapps/contentstore/views.py @@ -37,6 +37,7 @@ from xmodule.error_module import ErrorDescriptor from xmodule.errortracker import exc_info_to_str from github_sync import export_to_github from static_replace import replace_urls +from external_auth.views import ssl_login_shortcut from mitxmako.shortcuts import render_to_response, render_to_string from xmodule.modulestore.django import modulestore @@ -88,7 +89,7 @@ def signup(request): csrf_token = csrf(request)['csrf_token'] return render_to_response('signup.html', {'csrf': csrf_token}) - +@ssl_login_shortcut @ensure_csrf_cookie def login_page(request): """ diff --git a/cms/envs/common.py b/cms/envs/common.py index 6f7a462da2..8b5e6c7655 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -32,7 +32,8 @@ from xmodule.static_content import write_descriptor_styles, write_descriptor_js, MITX_FEATURES = { 'USE_DJANGO_PIPELINE': True, 'GITHUB_PUSH': False, - 'ENABLE_DISCUSSION_SERVICE': False + 'ENABLE_DISCUSSION_SERVICE': False, + 'AUTH_USE_MIT_CERTIFICATES' : False, } # needed to use lms student app diff --git a/cms/envs/dev_ike.py b/cms/envs/dev_ike.py index ec769ff6ab..0fdca9113d 100644 --- a/cms/envs/dev_ike.py +++ b/cms/envs/dev_ike.py @@ -1,8 +1,21 @@ # dev environment for ichuang/mit +# FORCE_SCRIPT_NAME = '/cms' + from .common import * from logsettings import get_logger_config from .dev import * import socket -#MITX_FEATURES['USE_DJANGO_PIPELINE']=False # don't recompile scss +MITX_FEATURES['AUTH_USE_MIT_CERTIFICATES'] = True + +MITX_FEATURES['USE_DJANGO_PIPELINE']=False # don't recompile scss + +SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL', 'https') # django 1.4 for nginx ssl proxy + +MITX_ROOT_URL = 'https://qisx.mit.edu:442' +#MITX_ROOT_URL = 'cms' + +LOGIN_REDIRECT_URL = MITX_ROOT_URL + '/login' +LOGIN_URL = MITX_ROOT_URL + '/login' + diff --git a/common/djangoapps/external_auth/views.py b/common/djangoapps/external_auth/views.py index 5cf21ca68d..520cd95c0b 100644 --- a/common/djangoapps/external_auth/views.py +++ b/common/djangoapps/external_auth/views.py @@ -215,6 +215,52 @@ def ssl_dn_extract_info(dn): else: return None return (user, email, fullname) + + +def ssl_get_cert_from_request(request): + """ + Extract user information from certificate, if it exists, returning (user, email, fullname). + Else return None. + """ + certkey = "SSL_CLIENT_S_DN" # specify the request.META field to use + + cert = request.META.get(certkey, '') + if not cert: + cert = request.META.get('HTTP_' + certkey, '') + if not cert: + try: + # try the direct apache2 SSL key + cert = request._req.subprocess_env.get(certkey, '') + except Exception: + return '' + + return cert + + (user, email, fullname) = ssl_dn_extract_info(cert) + return (user, email, fullname) + + +def ssl_login_shortcut(fn): + """ + Python function decorator for login procedures, to allow direct login + based on existing ExternalAuth record and MIT ssl certificate. + """ + def wrapped(*args, **kwargs): + if not settings.MITX_FEATURES['AUTH_USE_MIT_CERTIFICATES']: + return fn(*args, **kwargs) + request = args[0] + cert = ssl_get_cert_from_request(request) + if not cert: # no certificate information - show normal login window + 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) + return wrapped @csrf_exempt @@ -234,17 +280,7 @@ def ssl_login(request): Else continues on with student.views.index, and no authentication. """ - certkey = "SSL_CLIENT_S_DN" # specify the request.META field to use - - cert = request.META.get(certkey, '') - if not cert: - cert = request.META.get('HTTP_' + certkey, '') - if not cert: - try: - # try the direct apache2 SSL key - cert = request._req.subprocess_env.get(certkey, '') - except Exception: - cert = None + cert = ssl_get_cert_from_request(request) if not cert: # no certificate information - go onward to main index