def external_login_or_signup(request, external_id, external_domain, credentials, email, fullname, retfun=None): """Generic external auth login or signup""" # see if we have a map from this external_id to an edX username try: eamap = ExternalAuthMap.objects.get(external_id=external_id, external_domain=external_domain) log.debug('Found eamap=%s' % eamap) except ExternalAuthMap.DoesNotExist: # go render form for creating edX user eamap = ExternalAuthMap(external_id=external_id, external_domain=external_domain, external_credentials=json.dumps(credentials)) eamap.external_email = email eamap.external_name = fullname eamap.internal_password = generate_password() log.debug('Created eamap=%s' % eamap) eamap.save() internal_user = eamap.user if internal_user is None: log.debug('No user for %s yet, doing signup' % eamap.external_email) return signup(request, eamap) 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)) return signup(request, eamap) if not user.is_active: log.warning("User %s is not active" % (uname)) # TODO: improve error page msg = 'Account not yet activated: please look for link in your email' return default_render_failure(request, msg) login(request, user) request.session.set_expiry(0) student_views.try_change_enrollment(request) log.info("Login success - {0} ({1})".format(user.username, user.email)) if retfun is None: return redirect('/') return retfun()
def external_login_or_signup(request, external_id, external_domain, credentials, email, fullname, retfun=None): """Generic external auth login or signup""" # see if we have a map from this external_id to an edX username try: eamap = ExternalAuthMap.objects.get(external_id=external_id, external_domain=external_domain) log.debug('Found eamap=%s' % eamap) except ExternalAuthMap.DoesNotExist: # go render form for creating edX user eamap = ExternalAuthMap(external_id=external_id, external_domain=external_domain, external_credentials=json.dumps(credentials)) eamap.external_email = email eamap.external_name = fullname eamap.internal_password = generate_password() log.debug('Created eamap=%s' % eamap) eamap.save() internal_user = eamap.user if internal_user is None: log.debug('No user for %s yet, doing signup' % eamap.external_email) return signup(request, eamap) 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)) return signup(request, eamap) if not user.is_active: log.warning("User %s is not active" % (uname)) # TODO: improve error page msg = 'Account not yet activated: please look for link in your email' return default_render_failure(request, msg) login(request, user) request.session.set_expiry(0) student_views.try_change_enrollment(request) log.info("Login success - {0} ({1})".format(user.username, user.email)) if retfun is None: return redirect('/') return retfun()
def authentication_success(request): ''' 新用户注册时 用户直接走oauth后通过python-social-auth的auth后,成功会回调到此处, 此时django的用户应该是未登录状态 request.user.is_authenticated() is False ''' detail = request.session.get('authentication_user_detail') inviter_id = request.session.get('inviter_id') provider = detail['social_provider'] strategy = get_strategy(provider) enrollment_action = request.session.get('enrollment_action') course_id = request.session.get('course_id') user, _created = _get_or_create_oauth_user(strategy, detail, request) # 如果有邀请 if inviter_id: _create_user_invite(inviter_id, user) login(request, user) user_profile = user.profile user_profile.last_login_ip = request.META.get('REMOTE_ADDR', None) user_profile.save() # 如果用户没有登录就选课,并且这时候选择的是oauth,尝试enroll课程 if enrollment_action: request.method = 'POST' request.POST = request.POST.copy() request.POST['enrollment_action'] = enrollment_action request.POST['course_id'] = course_id try_change_enrollment(request) next_url = request.session.get('next', '') context = {'next': next_url} track_log(request, 'oauth.user.login_success', { 'success': True, 'uid': user.id, 'provider': strategy.backend.name, }) return render_to_response('xuetangx/oauth/oauth_login_success.html', context)
def authentication_success(request): ''' 新用户注册时 用户直接走oauth后通过python-social-auth的auth后,成功会回调到此处, 此时django的用户应该是未登录状态 request.user.is_authenticated() is False ''' detail = request.session.get('authentication_user_detail') inviter_id = request.session.get('inviter_id') provider = detail['social_provider'] strategy = get_strategy(provider) enrollment_action = request.session.get('enrollment_action') course_id = request.session.get('course_id') user, _created = _get_or_create_oauth_user(strategy, detail, request) # 如果有邀请 if inviter_id: _create_user_invite(inviter_id, user) login(request, user) user_profile = user.profile user_profile.last_login_ip = request.META.get('REMOTE_ADDR', None) user_profile.save() # 如果用户没有登录就选课,并且这时候选择的是oauth,尝试enroll课程 if enrollment_action: request.method = 'POST' request.POST = request.POST.copy() request.POST['enrollment_action'] = enrollment_action request.POST['course_id'] = course_id try_change_enrollment(request) next_url = request.session.get('next', '') context = {'next': next_url} track_log(request, 'oauth.user.login_success', { 'success': True, 'uid': user.id, 'provider': strategy.backend.name, }) return render_to_response('xuetangx/oauth/oauth_login_success.html', context)
eamap.save() AUDIT_LOG.info("User registered with external_auth %s", post_vars['username']) AUDIT_LOG.info('Updated ExternalAuthMap for %s to be %s', post_vars['username'], eamap) if settings.FEATURES.get('BYPASS_ACTIVATION_EMAIL_FOR_EXTAUTH'): log.info('bypassing activation email') login_user.is_active = True login_user.save() AUDIT_LOG.info( u"Login activated on extauth account - {0} ({1})".format( login_user.username, login_user.email)) dog_stats_api.increment("common.student.account_created") redirect_url = try_change_enrollment(request) # Resume the third-party-auth pipeline if necessary. if settings.FEATURES.get('ENABLE_THIRD_PARTY_AUTH') and pipeline.running( request): running_pipeline = pipeline.get(request) redirect_url = pipeline.get_complete_url(running_pipeline['backend']) response = JsonResponse({ 'success': True, 'redirect_url': redirect_url, }) # set the login cookie for the edx marketing site # we want this cookie to be accessed via javascript # so httponly is set to None
def _external_login_or_signup(request, external_id, external_domain, credentials, email, fullname, retfun=None): """Generic external auth login or signup""" # see if we have a map from this external_id to an edX username try: eamap = ExternalAuthMap.objects.get(external_id=external_id, external_domain=external_domain) log.debug('Found eamap=%s', eamap) except ExternalAuthMap.DoesNotExist: # go render form for creating edX user eamap = ExternalAuthMap(external_id=external_id, external_domain=external_domain, external_credentials=json.dumps(credentials)) eamap.external_email = email eamap.external_name = fullname eamap.internal_password = generate_password() log.debug('Created eamap=%s', eamap) eamap.save() log.info(u"External_Auth login_or_signup for %s : %s : %s : %s", external_domain, external_id, email, fullname) uses_shibboleth = settings.MITX_FEATURES.get( 'AUTH_USE_SHIB') and external_domain.startswith( SHIBBOLETH_DOMAIN_PREFIX) internal_user = eamap.user if internal_user is None: if uses_shibboleth: # if we are using shib, try to link accounts using email try: link_user = User.objects.get(email=eamap.external_email) if not ExternalAuthMap.objects.filter(user=link_user).exists(): # if there's no pre-existing linked eamap, we link the user eamap.user = link_user eamap.save() internal_user = link_user log.info('SHIB: Linking existing account for %s', 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 # creds failure_msg = _( dedent(""" You have already created an account using an external login like WebAuth or Shibboleth. Please contact %s for support """ % getattr(settings, 'TECH_SUPPORT_EMAIL', '*****@*****.**'))) 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) else: log.info('No user for %s yet. doing signup', eamap.external_email) return _signup(request, eamap) # We trust shib's authentication, so no need to authenticate using the password again uname = internal_user.username if uses_shibboleth: user = internal_user # Assuming this 'AUTHENTICATION_BACKENDS' is set in settings, which I think is safe if settings.AUTHENTICATION_BACKENDS: auth_backend = settings.AUTHENTICATION_BACKENDS[0] else: auth_backend = 'django.contrib.auth.backends.ModelBackend' user.backend = auth_backend AUDIT_LOG.info('Linked user "%s" logged in via Shibboleth', user.email) else: user = authenticate(username=uname, password=eamap.internal_password, request=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) if not user.is_active: AUDIT_LOG.warning('User "%s" is not active after external login', uname) # TODO: improve error page msg = 'Account not yet activated: please look for link in your email' return default_render_failure(request, msg) login(request, user) request.session.set_expiry(0) # Now to try enrollment # Need to special case Shibboleth here because it logs in via a GET. # testing request.method for extra paranoia if uses_shibboleth and request.method == 'GET': enroll_request = _make_shib_enrollment_request(request) student_views.try_change_enrollment(enroll_request) else: student_views.try_change_enrollment(request) AUDIT_LOG.info("Login success - %s (%s)", user.username, user.email) if retfun is None: return redirect('/') return retfun()
def _external_login_or_signup(request, external_id, external_domain, credentials, email, fullname, retfun=None): """Generic external auth login or signup""" # see if we have a map from this external_id to an edX username try: eamap = ExternalAuthMap.objects.get(external_id=external_id, external_domain=external_domain) log.debug('Found eamap=%s', eamap) except ExternalAuthMap.DoesNotExist: # go render form for creating edX user eamap = ExternalAuthMap(external_id=external_id, external_domain=external_domain, external_credentials=json.dumps(credentials)) eamap.external_email = email eamap.external_name = fullname eamap.internal_password = generate_password() log.debug('Created eamap=%s', eamap) eamap.save() log.info(u"External_Auth login_or_signup for %s : %s : %s : %s", external_domain, external_id, email, fullname) uses_shibboleth = settings.MITX_FEATURES.get('AUTH_USE_SHIB') and external_domain.startswith(SHIBBOLETH_DOMAIN_PREFIX) internal_user = eamap.user if internal_user is None: if uses_shibboleth: # if we are using shib, try to link accounts using email try: link_user = User.objects.get(email=eamap.external_email) if not ExternalAuthMap.objects.filter(user=link_user).exists(): # if there's no pre-existing linked eamap, we link the user eamap.user = link_user eamap.save() internal_user = link_user log.info('SHIB: Linking existing account for %s', 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 # creds failure_msg = _(dedent(""" You have already created an account using an external login like WebAuth or Shibboleth. Please contact %s for support """ % getattr(settings, 'TECH_SUPPORT_EMAIL', '*****@*****.**'))) 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) else: log.info('No user for %s yet. doing signup', eamap.external_email) return _signup(request, eamap) # We trust shib's authentication, so no need to authenticate using the password again uname = internal_user.username if uses_shibboleth: user = internal_user # Assuming this 'AUTHENTICATION_BACKENDS' is set in settings, which I think is safe if settings.AUTHENTICATION_BACKENDS: auth_backend = settings.AUTHENTICATION_BACKENDS[0] else: auth_backend = 'django.contrib.auth.backends.ModelBackend' user.backend = auth_backend AUDIT_LOG.info('Linked user "%s" logged in via Shibboleth', user.email) else: user = authenticate(username=uname, password=eamap.internal_password, request=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) if not user.is_active: AUDIT_LOG.warning('User "%s" is not active after external login', uname) # TODO: improve error page msg = 'Account not yet activated: please look for link in your email' return default_render_failure(request, msg) login(request, user) request.session.set_expiry(0) # Now to try enrollment # Need to special case Shibboleth here because it logs in via a GET. # testing request.method for extra paranoia if uses_shibboleth and request.method == 'GET': enroll_request = _make_shib_enrollment_request(request) student_views.try_change_enrollment(enroll_request) else: student_views.try_change_enrollment(request) AUDIT_LOG.info("Login success - %s (%s)", user.username, user.email) if retfun is None: return redirect('/') return retfun()