Commit f7cabf7f by Bertrand Marron

Fix IONISx social provider

parent e3397cf9
......@@ -7,9 +7,9 @@ import re
import uuid
import time
import json
import requests
from collections import defaultdict
from pytz import UTC
from requests import request, ConnectionError
from django.conf import settings
from django.contrib.auth import logout, authenticate, login
......@@ -372,9 +372,13 @@ def register_user(request, extra_context=None):
"""
This view will display the non-modal registration form
"""
if not settings.FEATURES.get('ENABLE_THIRD_PARTY_AUTH'):
if request.user.is_authenticated():
return redirect(reverse('dashboard'))
if settings.FEATURES.get('ENABLE_THIRD_PARTY_AUTH'):
# Redirect to IONISx, we don't want the registration form.
return external_auth.views.redirect_with_get('/auth/login/portal-oauth2', request.GET, do_reverse=False)
if settings.FEATURES.get('AUTH_USE_CERTIFICATES_IMMEDIATE_SIGNUP'):
# Redirect to branding to process their certificate if SSL is enabled
# and registration is disabled.
......@@ -415,14 +419,6 @@ def register_user(request, extra_context=None):
context.update(overrides)
return render_to_response('register.html', context)
else:
if request.user.is_authenticated():
if 'course_id' in request.GET:
return redirect("/courses/{0}/about".format(request.GET.get('course_id')))
else:
return redirect('/')
else:
return redirect("/auth/login/portal-oauth2/?auth_entry=login&next={0}".format(urlquote(request.get_full_path())))
def complete_course_mode_info(course_id, enrollment):
......@@ -1094,14 +1090,16 @@ def login_user(request, error=""): # pylint: disable-msg=too-many-statements,un
}) # TODO: this should be status code 400 # pylint: disable=fixme
def logout_portal(user_mail):
def logout_portal(request):
if request.user.is_authenticated():
user = request.user
social_data = models.DjangoStorage.user.get_social_auth_for_user(user)[0]
try:
user = models.DjangoStorage.user.objects.get(uid=user_mail)
response = request('POST', settings.IONISX_AUTH['SYNC_LOGOUT_URL'],
params={ 'access_token': user.extra_data['access_token'] })
except ConnectionError as err:
log.warning(err)
except Exception as err:
requests.post(
settings.IONISX_AUTH.get('SYNC_LOGOUT_URL'),
headers={'Authorization': 'Bearer {0}'.format(social_data.extra_data['access_token'])}
)
except requests.ConnectionError as err:
log.warning(err)
......@@ -1119,9 +1117,8 @@ def logout_user(request):
else:
user_mail = request.user.email
logout_portal(request)
logout(request)
if user_mail:
logout_portal(user_mail)
if settings.FEATURES.get('AUTH_USE_CAS'):
target = reverse('cas-logout')
else:
......
......@@ -13,8 +13,9 @@ from social.apps.django_app.default import models
from social.apps.django_app.middleware import SocialAuthExceptionMiddleware
from . import pipeline
from . import portal
log = logging.getLogger('third_party_auth.middleware')
log = logging.getLogger(__file__)
class ExceptionMiddleware(SocialAuthExceptionMiddleware):
"""Custom middleware that handles conditional redirection."""
......@@ -32,32 +33,36 @@ class PortalSynchronizerMiddleware(object):
"""Custom middleware to synchronize user status of LMS with Portal provider."""
def process_request(self, request):
if not isinstance(request.user, AnonymousUser):
try:
email = request.user.email
user = models.DjangoStorage.user.objects.get(uid=email)
response = requests.request('POST', settings.IONISX_AUTH['SYNC_USER_URL'],
params={ 'access_token': user.extra_data['access_token'] })
response = response.json()
if response is None:
logout(request)
response = redirect(request.get_full_path())
response.delete_cookie(
settings.EDXMKTG_COOKIE_NAME,
path='/', domain=settings.SESSION_COOKIE_DOMAIN,
)
return response
if response['updated'] is True:
log.warning('need update !')
if request.user.is_authenticated():
user = request.user
user.email = response['emails'][0]['email']
user.username = response['username']
user.save()
social_auth = models.DjangoStorage.user.get_social_auth_for_user(user)
profile = UserProfile.objects.get(user=request.user)
profile.name = response['name']
profile.save()
if len(social_auth) == 1:
social_data = social_auth[0]
try:
r = requests.get(
settings.IONISX_AUTH.get('USER_DATA_URL'),
headers={'Authorization': 'Bearer {0}'.format(social_data.extra_data['access_token'])}
)
except requests.ConnectionError as err:
log.warning(err)
except Exception as err:
log.warning(err)
return
user_data = r.json()
if user_data:
_id = user_data['_id']
email = portal.get_primary_email(user_data['emails'])
username = user_data['username']
name = user_data['name']
if (user.email != email or user.username != user_data['username']):
log.info('User {} needs to be updated'.format(_id))
user.email = email
user.username = username
user.save()
if user.profile.name != user_data['name']:
log.info('User profile for {} needs to be updated'.format(_id))
user.profile.name = name
user.profile.save()
......@@ -5,35 +5,40 @@ from django.conf import settings
from social.backends.oauth import BaseOAuth2
from social.exceptions import AuthCanceled
def get_primary_email(emails):
for email in emails:
if email['primary'] is True:
return email['email']
return None
class PortalOAuth2(BaseOAuth2):
"""Portal OAuth2 authentication backend"""
name = 'portal-oauth2'
auth_settings = settings.IONISX_AUTH
AUTHORIZATION_URL = auth_settings['AUTHORIZATION_URL']
ACCESS_TOKEN_URL = auth_settings['ACCESS_TOKEN_URL']
name = 'portal-oauth2'
ID_KEY = '_id'
AUTHORIZATION_URL = auth_settings.get('AUTHORIZATION_URL')
ACCESS_TOKEN_URL = auth_settings.get('ACCESS_TOKEN_URL')
ACCESS_TOKEN_METHOD = 'POST'
REDIRECT_STATE = False
USER_DATA_URL = auth_settings['USER_DATA_URL']
def get_user_id(self, details, response):
"""Use portal email as unique id"""
if self.setting('USE_UNIQUE_USER_ID', False):
return response['id']
else:
return details['email']
USER_DATA_URL = auth_settings.get('USER_DATA_URL')
def get_user_details(self, response):
"""Return user details from Portal account"""
return {'username': response.get('username', ''),
'email': response.get('emails', '')[0]['email'],
'fullname': response.get('name')}
"""Return user details from IONISx account"""
return {
'username': response['username'],
'email': get_primary_email(response['emails']),
'fullname': response['name']
}
def user_data(self, access_token, *args, **kwargs):
"""Loads user data from service"""
params = self.setting('PROFILE_EXTRA_PARAMS', {})
params['access_token'] = access_token
return self.get_json(self.USER_DATA_URL, params=params)
return self.get_json(
self.USER_DATA_URL,
headers={'Authorization': 'Bearer {0}'.format(access_token)}
)
def process_error(self, data):
super(PortalOAuth2, self).process_error(data)
......
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