def get_api_user(request): import json import urllib2 from django.conf import settings from wstore.oauth2provider.models import Token from django.contrib.auth.models import User, AnonymousUser from wstore.social_auth_backend import FIWARE_USER_DATA_URL, fill_internal_user_info, FiwareBackend from wstore.store_commons.utils.method_request import MethodRequest # Get access_token from the request try: auth_info = request.META['HTTP_AUTHORIZATION'].split(' ', 1) auth_type = auth_info[0] token = auth_info[1] except: return AnonymousUser() # If using the idM to authenticate users, validate the token if settings.OILAUTH: opener = urllib2.build_opener() url = FIWARE_USER_DATA_URL + '?access_token=' + token request = MethodRequest('GET', url) try: new_user = False response = opener.open(request) user_info = json.loads(response.read()) # Try to get an internal user try: user_id = None if settings.FIWARE_IDM_API_VERSION == 1: user_id = user_info['nickName'] else: user_id = user_info['id'] user = User.objects.get(username=user_id) except: # The user is valid but she has never accessed wstore so # internal models should be created from social_auth.backends.pipeline.user import get_username from social_auth.backends.pipeline.user import create_user from social_auth.backends.pipeline.social import associate_user from social_auth.backends.pipeline.social import load_extra_data # The request is from a new user new_user = True # Get the internal username to be used details = { 'username': user_info['nickName'], 'email': user_info['email'], 'fullname': user_info['displayName'] } username = get_username(details) # Create user structure auth_user = create_user('', details, '', user_info['actorId'], username['username']) # associate user with social user social_user = associate_user(FiwareBackend, auth_user['user'], user_info['actorId']) # Load user extra data request = { 'access_token': token } load_extra_data(FiwareBackend, details, request, user_info['actorId'], social_user['user'], social_user=social_user['social_user']) # Refresh user info user = User.objects.get(username=user_info['nickName']) # If it is a new user the auth info contained in the userprofile is not valid if not new_user: # The user has been validated but the user info is not valid since the # used token belongs to an external application # Get FiPay token for the user token = user.userprofile.access_token # Get valid user info for Fipay url = FIWARE_USER_DATA_URL + '?access_token=' + token request = MethodRequest('GET', url) try: response = opener.open(request) user_info = json.loads(response.read()) except Exception, e: if e.code == 401: # The access token may expired, try to refresh it social = user.social_auth.filter(provider='fiware')[0] social.refresh_token() # Try to get user info with the new access token social = user.social_auth.filter(provider='fiware')[0] new_credentials = social.extra_data user.userprofile.access_token = new_credentials['access_token'] user.userprofile.refresh_token = new_credentials['refresh_token'] user.userprofile.save() token = user.userprofile.access_token url = FIWARE_USER_DATA_URL + '?access_token=' + token request = MethodRequest('GET', url) response = opener.open(request) user_info = json.loads(response.read()) else: raise(e) user_info['access_token'] = token user_info['refresh_token'] = user.userprofile.refresh_token fill_internal_user_info((), response=user_info, user=user) except Exception, e: user = AnonymousUser()
def get_api_user(request): import json import urllib2 from django.conf import settings from wstore.oauth2provider.models import Token from django.contrib.auth.models import User, AnonymousUser from wstore.social_auth_backend import FIWARE_USER_DATA_URL, fill_internal_user_info, FiwareBackend from wstore.store_commons.utils.method_request import MethodRequest # Get access_token from the request try: token = request.META['HTTP_AUTHORIZATION'].split(' ', 1)[1] except: return AnonymousUser() # If using the idM to authenticate users, validate the token if settings.OILAUTH: opener = urllib2.build_opener() url = FIWARE_USER_DATA_URL + '?access_token=' + token request = MethodRequest('GET', url) try: new_user = False response = opener.open(request) user_info = json.loads(response.read()) # Try to get an internal user try: user = User.objects.get(username=user_info['nickName']) except: # The user is valid but she has never accessed wstore so # internal models should be created from social_auth.backends.pipeline.user import get_username from social_auth.backends.pipeline.user import create_user from social_auth.backends.pipeline.social import associate_user from social_auth.backends.pipeline.social import load_extra_data # The request is from a new user new_user = True # Get the internal username to be used details = { 'username': user_info['nickName'], 'email': user_info['email'], 'fullname': user_info['displayName'] } username = get_username(details) # Create user structure auth_user = create_user('', details, '', user_info['actorId'], username['username']) # associate user with social user social_user = associate_user(FiwareBackend, auth_user['user'], user_info['actorId']) # Load user extra data request = { 'access_token': token } load_extra_data(FiwareBackend, details, request, user_info['actorId'], social_user['user'], social_user=social_user['social_user']) # Refresh user info user = User.objects.get(username=user_info['nickName']) # If it is a new user the auth info contained in the userprofile is not valid if not new_user: # The user has been validated but the user info is not valid since the # used token belongs to an external application # Get FiPay token for the user # TeroV: this token might be empty if auth via store web UI has failed token = user.userprofile.access_token def refreshToken(user): # The access token may expired, try to refresh it social = user.social_auth.filter(provider='fiware')[0] result = social.refresh_token() # Try to get user info with the new access token social = user.social_auth.filter(provider='fiware')[0] new_credentials = social.extra_data user.userprofile.access_token = new_credentials['access_token'] user.userprofile.refresh_token = new_credentials['refresh_token'] user.userprofile.save() token = user.userprofile.access_token url = FIWARE_USER_DATA_URL + '?access_token=' + token request = MethodRequest('GET', url) response = opener.open(request) user_info = json.loads(response.read()) user_info['access_token'] = token user_info['refresh_token'] = user.userprofile.refresh_token fill_internal_user_info((), response=user_info, user=user) # To get clear reason for unclear situation if token is None: logger.debug("Token is empty") # TODO: this is not correct action, because if no original login then we don't have refresh_token either refreshToken(user) else: # try to use found token try: # Get valid user info for Fipay url = FIWARE_USER_DATA_URL + '?access_token=' + token request = MethodRequest('GET', url) response = opener.open(request) user_info = json.loads(response.read()) except Exception, e: logger.debug("Exception when calling IdM: %s" % str(e)) if e.code == 401: # server responded that code is not valid logger.debug("Token was not valid -> refresh") refreshToken(user) else: raise(e) except Exception, e: io = StringIO() traceback.print_exc(io) logger.error("User authentication failed. Returning AnonymousUser: %s" % io.getvalue()) user = AnonymousUser()