def do_complete(backend, login, user=None, *args, **kwargs): is_authenticated = user_is_authenticated(user) user = is_authenticated and user or None partial = partial_pipeline_data(backend, user, *args, **kwargs) if partial: user = backend.continue_pipeline(partial) else: user = backend.complete(user=user, *args, **kwargs) # check if the output value is something else than a user and just # return it to the client user_model = backend.strategy.storage.user.user_model() if user and not isinstance(user, user_model): return user elif user: if user_is_active(user): # catch is_new/social_user in case login() resets the instance social_user = user.social_user login(backend, user, social_user) # store last login backend name in session backend.strategy.session_set('social_auth_last_login_backend', social_user.provider) return user
def oauth_complete(request, backend, *args, **kwargs): """ Authentication complete view used for Social Auth """ code = request.GET.get('code', None) if code is None: raise SocialAuthFailed('Authorization code has to be provided.') request.backend.data['code'] = code is_authenticated = user_is_authenticated(request.user) user = request.user if is_authenticated else None partial = partial_pipeline_data(request.backend, user, *args, **kwargs) if partial: user = request.backend.continue_pipeline(partial) # clean partial data after usage request.backend.strategy.clean_partial_pipeline(partial.token) else: # check if social auth is configured properly if backend not in settings.SOCIAL_AUTH_LOGIN_REDIRECT_URLS: raise SocialAuthNotConfigured( f'The backend {backend} is not supported.') elif not settings.SOCIAL_AUTH_LOGIN_REDIRECT_URLS.get(backend): raise SocialAuthNotConfigured( f'A redirect URL for the backend {backend} was not defined.') # prepare request to validate code data = request.backend.strategy.request_data() data['code'] = code redirect_uri = settings.SOCIAL_AUTH_LOGIN_REDIRECT_URLS.get(backend) request.backend.redirect_uri = redirect_uri request.backend.STATE_PARAMETER = False request.backend.REDIRECT_STATE = False try: # validate code / trigger pipeline and return a user user = request.backend.complete(user=user, *args, **kwargs) except AuthFailed as e: raise SocialAuthFailed(e.args[0]) if is_authenticated: # generate JWT/Bearer Token tokens = generate_access_tokens(request, user) return JsonResponse(data=tokens, status=200) elif user: if user_is_active(user): # generate JWT/Bearer Token tokens = generate_access_tokens(request, user) return JsonResponse(data=tokens, status=200) else: url = setting_url(request.backend, 'INACTIVE_USER_URL', 'LOGIN_ERROR_URL', 'LOGIN_URL') else: url = setting_url(request.backend, 'LOGIN_ERROR_URL', 'LOGIN_URL') return request.backend.strategy.redirect(url)
def do_complete(backend, login, user=None, redirect_name='next', *args, **kwargs): data = backend.strategy.request_data() is_authenticated = user_is_authenticated(user) user = user if is_authenticated else None partial = partial_pipeline_data(backend, user, *args, **kwargs) if partial: user = backend.continue_pipeline(partial) # clean partial data after usage backend.strategy.clean_partial_pipeline(partial.token) else: user = backend.complete(user=user, *args, **kwargs) # pop redirect value before the session is trashed on login(), but after # the pipeline so that the pipeline can change the redirect if needed redirect_value = backend.strategy.session_get(redirect_name, '') or \ data.get(redirect_name, '') # check if the output value is something else than a user and just # return it to the client user_model = backend.strategy.storage.user.user_model() if user and not isinstance(user, user_model): return user if is_authenticated: if not user: url = setting_url(backend, redirect_value, 'LOGIN_REDIRECT_URL') else: url = setting_url(backend, redirect_value, 'NEW_ASSOCIATION_REDIRECT_URL', 'LOGIN_REDIRECT_URL') elif user: if user_is_active(user): # catch is_new/social_user in case login() resets the instance is_new = getattr(user, 'is_new', False) social_user = user.social_user login(backend, user, social_user) # store last login backend name in session backend.strategy.session_set('social_auth_last_login_backend', social_user.provider) if is_new: url = setting_url(backend, 'NEW_USER_REDIRECT_URL', redirect_value, 'LOGIN_REDIRECT_URL') else: url = setting_url(backend, redirect_value, 'LOGIN_REDIRECT_URL') else: if backend.setting('INACTIVE_USER_LOGIN', False): social_user = user.social_user login(backend, user, social_user) url = setting_url(backend, 'INACTIVE_USER_URL', 'LOGIN_ERROR_URL', 'LOGIN_URL') else: url = setting_url(backend, 'LOGIN_ERROR_URL', 'LOGIN_URL') if redirect_value and redirect_value != url: redirect_value = quote(redirect_value) url += ('&' if '?' in url else '?') + \ '{0}={1}'.format(redirect_name, redirect_value) if backend.setting('SANITIZE_REDIRECTS', True): allowed_hosts = backend.setting('ALLOWED_REDIRECT_HOSTS', []) + \ [backend.strategy.request_host()] url = sanitize_redirect(allowed_hosts, url) or \ backend.setting('LOGIN_REDIRECT_URL') response = backend.strategy.redirect(url) social_auth = user.social_auth.filter(provider='drycc').\ order_by('-modified').last() response.set_cookie("name", user.username, max_age=social_auth.extra_data.get('expires_in')) response.set_cookie("id_token", social_auth.extra_data.get('id_token'), max_age=social_auth.extra_data.get('expires_in')) from django.core.cache import cache cache.set("oidc_state_" + data.get('state'), {'token': social_auth.extra_data.get('id_token', 'fail'), 'username': user.username}, 60 * 10) return response
def mutate(cls, root, info, provider, **kwargs): backend = get_backend(info.context, provider, **kwargs) backend.REDIRECT_STATE = False backend.STATE_PARAMETER = False backend.redirect_uri = kwargs.get('redirectUri') data = backend.strategy.request_data() user = info.context.user is_authenticated = user_is_authenticated(user) user = user if is_authenticated else None partial = partial_pipeline_data(backend, user) if partial: user = backend.continue_pipeline(partial) # clean partial data after usage backend.strategy.clean_partial_pipeline(partial.token) else: user = backend.complete(user=user) if user is None: raise exceptions.InvalidTokenError(_('Invalid token')) # check if the output value is something else than a user and just # return it to the client user_model = backend.strategy.storage.user.user_model() if isinstance(user, graphene.ObjectType): return user elif not isinstance(user, user_model): msg = _('`{}` is not a user or graphene.ObjectType instance').format(type(user).__name__) raise exceptions.DoAuthError(msg, user) is_inactive_user = False is_new_association = False is_successful_login = False is_new = False if is_authenticated: if user: is_new_association = True elif user: if user_is_active(user): # catch is_new/social_user in case login() resets the instance is_new = getattr(user, 'is_new', False) social_user = user.social_user cls.do_login(backend, user, social_user) # store last login backend name in session backend.strategy.session_set('social_auth_last_login_backend', social_user.provider) is_successful_login = True else: if backend.setting('INACTIVE_USER_LOGIN', False): social_user = user.social_user cls.do_login(backend, user, social_user) is_successful_login = True is_inactive_user = True return cls(result=cls.get_result( backend, user, is_successful_login, is_inactive_user, is_new, is_new_association, **kwargs))
def _authenticate(self, flow): """Authenticate the current request""" request = self.context["request"] strategy = self.context["strategy"] backend = self.context["backend"] user = request.user is_authenticated = user_is_authenticated(user) user = user if is_authenticated else None kwargs = {"request": request, "flow": flow} partial = partial_pipeline_data(backend, user, **kwargs) if partial: try: user = backend.continue_pipeline(partial) except InvalidEmail: authentication_flow = partial.data.get("kwargs").get("flow") if (authentication_flow and authentication_flow == SocialAuthState.FLOW_REGISTER): email = partial.data.get("kwargs").get("details").get( "email") user_exists = User.objects.filter(email=email).exists() if user_exists: return SocialAuthState( SocialAuthState.STATE_EXISTING_ACCOUNT) return SocialAuthState(SocialAuthState.STATE_INVALID_LINK) return SocialAuthState(SocialAuthState.STATE_INVALID_EMAIL) # clean partial data after usage strategy.clean_partial_pipeline(partial.token) else: user = backend.complete(user=user, **kwargs) # pop redirect value before the session is trashed on login(), but after # the pipeline so that the pipeline can change the redirect if needed redirect_url = backend.strategy.session_get("next", None) # check if the output value is something else than a user and just # return it to the client user_model = strategy.storage.user.user_model() if user and not isinstance(user, user_model): # this is where a redirect from the pipeline would get returned return user if is_authenticated: return SocialAuthState(SocialAuthState.STATE_SUCCESS, redirect_url=redirect_url) elif user: if user_is_active(user): social_user = user.social_user login(backend, user, social_user) # store last login backend name in session strategy.session_set("social_auth_last_login_backend", social_user.provider) return SocialAuthState(SocialAuthState.STATE_SUCCESS, redirect_url=redirect_url) else: return SocialAuthState(SocialAuthState.STATE_INACTIVE) else: # pragma: no cover # this follows similar code in PSA itself, but wasn't reachable through normal testing log.error("Unexpected authentication result") return SocialAuthState(SocialAuthState.STATE_ERROR, errors=["Unexpected authentication result"])