def _create_suomifi_logout_response(social_user, user, request, redirect_url): """Creates Suomi.fi logout redirect response for given social_user and removes all related OIDC tokens. The user is directed to redirect_url after succesful Suomi.fi logout. """ token = '' saml_backend = load_backend( load_strategy(request), 'suomifi', redirect_uri=getattr(settings, 'LOGIN_URL') ) id_token_hint = request.GET.get('id_token_hint') if id_token_hint: client_id = client_id_from_id_token(id_token_hint) try: client = Client.objects.get(client_id=client_id) if redirect_url in client.post_logout_redirect_uris: token = saml_backend.create_return_token( client_id, client.post_logout_redirect_uris.index(redirect_url)) except Client.DoesNotExist: pass response = saml_backend.create_logout_redirect(social_user, token) for token in Token.objects.filter(user=user): if token.id_token.get('aud') == client_id: token.delete() return response
def suomifi_logout_view(request, uuid=None): saml_backend = load_backend( load_strategy(request), 'suomifi', redirect_uri=getattr(settings, 'LOGIN_URL'), ) return saml_backend.process_logout_message()
def _validate_state(self, value): request = self.context['request'] strategy = load_strategy(request) redirect_uri = strategy.session_get('redirect_uri') backend_name = self.context['view'].kwargs['provider'] backend = load_backend( strategy, backend_name, redirect_uri=redirect_uri ) try: backend.validate_state() except exceptions.AuthMissingParameter: raise serializers.ValidationError( 'State could not be found in request data.' ) except exceptions.AuthStateMissing: raise serializers.ValidationError( 'State could not be found in server-side session data.' ) except exceptions.AuthStateForbidden: raise serializers.ValidationError( 'Invalid state has been provided.' ) return value
def do_authenticate(user=None, next_uri='/api/users/'): facebook_state = 'ABC' client = Client() session = client.session session['facebook_state'] = facebook_state session['next'] = next_uri session.save() request_factory = RequestFactory() request = request_factory.get(path='/social/complete/facebook/', data={ 'redirect_state': 'DEF', 'granted_scopes': 'email,public_profile', 'denied_scopes': '', 'code': 'GHI', 'state': facebook_state, }) request.user = user if user else AnonymousUser() request.session = session request.session = client.session request.social_strategy = load_strategy(request) request.strategy = request.social_strategy backend = load_backend(request.strategy, 'facebook', '/social/complete/facebook/') request.backend = backend args = () kwargs = { 'backend': backend, 'response': {'name': 'Pepa Novák', 'id': '1234', 'expires': 1000, 'granted_scopes': ['email', 'public_profile'], 'access_token': 'A'}, 'user': user, } return backend.strategy.authenticate(*args, **kwargs), request.session.get('next')
def get_user_token(self, request, access_token): backend = load_backend(strategy=load_strategy(request), name='openstreetmap', redirect_uri=None) authed_user = request.user if not request.user.is_anonymous else None user = backend.do_auth(access_token, user=authed_user) token, created = Token.objects.get_or_create(user=user) return {'token': token.key}
def test_reverse_urls(backend_name, expected_url): """Tests that the redirect_uris stay the same as with the django allauth. Can be removed when all of the urls are changed.""" strategy = load_strategy() uri = reverse('social:complete', kwargs={'backend': backend_name}) backend = load_backend(strategy, backend_name, uri) assert backend.get_redirect_uri() == expected_url
def saml_metadata_view(request): complete_url = reverse("social:complete", args=("saml", )) saml_backend = load_backend(load_strategy(request), "saml", redirect_uri=complete_url) metadata, errors = saml_backend.generate_metadata_xml() if not errors: return HttpResponse(content=metadata, content_type="text/xml")
def name(self): from social_django.utils import load_backend, load_strategy saml_backend = load_backend( load_strategy(), "saml", redirect_uri=reverse('social:complete', args=("saml",)) ) return saml_backend.get_idp(self.user_social_auth.uid.split(':')[0]).conf['label']
def setUp(self): super(AccessTokenExchangeFormTest, self).setUp() self.request = RequestFactory().post("dummy_url") redirect_uri = 'dummy_redirect_url' SessionMiddleware().process_request(self.request) self.request.social_strategy = social_utils.load_strategy(self.request) # pylint: disable=no-member self.request.backend = social_utils.load_backend(self.request.social_strategy, self.BACKEND, redirect_uri)
def delete_social(self, user): strategy = load_strategy(self.request) backend = load_backend(strategy, self.provider, '') linked_social = ( backend.strategy.storage.user.get_social_auth_for_user( user, self.provider).first()) if linked_social: linked_social.delete()
def mini_login(request, username, password): """Provide authentication via squarelet via the password grant type""" strategy = load_strategy(request) backend = load_backend(strategy, 'squarelet', redirect_uri=None) backend.password_grant_auth = (username, password) backend.STATE_PARAMETER = False backend.REDIRECT_STATE = False user = backend.complete(request=request) return user
def auth(self, request): backend = load_backend(load_strategy(request), 'amazon', '') user = request.user if request.user.is_authenticated else None res = backend.do_auth(request.data.get('access_token', ''), response=request.data, user=user, request=request) _do_login(backend, res, getattr(res, 'social_user', None)) return res
def test_get_username_user_connected(self): """The user is already connected, its username is fetched and returned.""" backend = load_backend(strategy=self.strategy, name="edx-oauth2", redirect_uri="/") user = UserFactory(username="******") self.assertEqual(get_username(self.strategy, {}, backend, user), {"username": "******"})
def create(self, request, *args, **kwargs): serializer = self.serializer_class(data=request.data) serializer.is_valid(raise_exception=True) provider = request.data['provider'] strategy = load_strategy(request) authenticated_user = request.user if not request.user.is_anonymous else None try: backend = load_backend(strategy=strategy, name=provider, redirect_uri=None) if isinstance(backend, BaseOAuth1): if "access_token_secret" in request.data: token = { 'oauth_token': request.data['access_token'], 'oauth_token_secret': request.data['access_token_secret'] } else: return Response( {'error': 'Please enter your secret token'}, status=status.HTTP_400_BAD_REQUEST) elif isinstance(backend, BaseOAuth2): token = serializer.data.get('access_token') except MissingBackend: return Response({'error': 'Please enter a valid social provider'}, status=status.HTTP_400_BAD_REQUEST) try: user = backend.do_auth(token, user=authenticated_user) except (AuthAlreadyAssociated, IntegrityError): return Response( {"errors": "You are already logged in with another account"}, status=status.HTTP_400_BAD_REQUEST) except BaseException: return Response({"errors": "Invalid token"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) if user: user.is_active = True username = user.username email = user.email date = datetime.now() + timedelta(days=20) payload = { 'email': email, 'username': username, 'exp': int(date.strftime('%s')) } user_token = jwt.encode(payload, settings.SECRET_KEY, algorithm='HS256') serializer = UserSerializer(user) serialized_details = serializer.data serialized_details["token"] = user_token return Response(serialized_details, status.HTTP_200_OK)
def test_get_username_no_user_connected_email_as_username(self): """No user connected and should return the email as username.""" backend = load_backend(strategy=self.strategy, name="edx-oauth2", redirect_uri="/") self.assertEqual( get_username(self.strategy, {"email": "*****@*****.**"}, backend), {"username": "******"}, )
def authenticate_using_social_auth(_, info, accessToken, provider): try: strategy = load_strategy(info.context.request) backend = load_backend(strategy, provider, redirect_uri=None) except MissingBackend: raise AuthError('Auth Provider Not Supported', code='INVALID_PROVIDER') user = backend.do_auth(accessToken, user=None) _do_login(backend, user, user.social_user) return {"success": True, "user": user.__dict__}
def meta_view(request): complete_url = reverse('saml:complete') saml_backend = load_backend( load_strategy(request), "saml", redirect_uri=complete_url, ) metadata, errors = saml_backend.generate_metadata_xml() if not errors: return HttpResponse(content=metadata, content_type='text/xml')
def saml_metadata(request): """ Display SAML configuration metadata as XML """ if not features.is_enabled(features.SAML_AUTH): raise Http404("Page not found") complete_url = reverse("social:complete", args=("saml", )) saml_backend = load_backend(load_strategy(request), "saml", redirect_uri=complete_url) metadata, _ = saml_backend.generate_metadata_xml() return HttpResponse(content=metadata, content_type="text/xml")
def suomifi_metadata_view(request): complete_url = reverse('auth_backends:suomifi_metadata') saml_backend = load_backend( load_strategy(request), 'suomifi', redirect_uri=complete_url, ) metadata, errors = saml_backend.generate_metadata_xml() if not errors: return HttpResponse(content=metadata, content_type='text/xml')
def test_get_username_no_user_and_username_already_saved(self): """No user connected and the username is already saved. Should throw an exception.""" backend = load_backend(strategy=self.strategy, name="edx-oauth2", redirect_uri="/") UserFactory(username="******") with self.assertRaises(AuthAlreadyAssociated): get_username(self.strategy, {"username": "******"}, backend)
def test_get_username_no_user_and_username_available(self): """No user connected, the username is in the details and is available.""" backend = load_backend(strategy=self.strategy, name="edx-oauth2", redirect_uri="/") self.assertEqual( get_username(self.strategy, {"username": "******"}, backend), {"username": "******"}, )
def setUp(self): self.testuser = User.objects.create(username='******', password='******') self.testuser.set_password('hello') self.testuser.email = "*****@*****.**" self.testuser.save() self.backend = load_backend(strategy=load_strategy(), name='dataporten_feide', redirect_uri='/')
def post(self, request): """Authenticate user through the provider and access_token""" serializer = self.serializer_class(data=request.data) serializer.is_valid(raise_exception=True) provider = serializer.data.get('provider', None) strategy = load_strategy(request) try: backend = load_backend(strategy=strategy, name=provider, redirect_uri=None) except MissingBackend: return Response(data=['Please provide a valid provider'], status=status.HTTP_400_BAD_REQUEST) try: if isinstance(backend, BaseOAuth2): access_token = serializer.data.get('access_token') user = backend.do_auth(access_token) except HTTPError as error: return Response(["Invalid token"], status=status.HTTP_400_BAD_REQUEST) except AuthTokenError as error: return Response(["Invalid credentials"], status=status.HTTP_400_BAD_REQUEST) try: authenticated_user = backend.do_auth(access_token, user=user) except HTTPError as error: return Response(["Invalid token"], status=status.HTTP_400_BAD_REQUEST) except AuthForbidden as error: return Response(["Invalid token"], status=status.HTTP_400_BAD_REQUEST) if authenticated_user and authenticated_user.is_active: token, created = Token.objects.get_or_create( user=authenticated_user) if created: # send room rating update to recombee recombee_client = RecombeeIntegrationClient() try: recombee_client.send_user(authenticated_user.id) except ResponseException: print("user with id", authenticated_user.id, "is already exists in recombee") user = UserSerializer(authenticated_user) response = { "user": user.data, "token": token.key, } return Response(status=status.HTTP_200_OK, data=response)
def wrapper(cls, root, info, **kwargs): context = info.context context._jwt_token_auth = True def on_resolve(values): user, payload = values payload.token = get_token(user, context) if jwt_settings.JWT_LONG_RUNNING_REFRESH_TOKEN: payload.refresh_token = refresh_token_lazy(user) return payload token = kwargs.get('access_token') backend = kwargs.get('backend') if conf.settings.SOCIAL_AUTH_GOOGLE_OAUTH2_KEY is None or conf.settings.SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET is None: authorization_key = AuthorizationKey.objects.get(name="google-oauth2") conf.settings.SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = authorization_key.key conf.settings.SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = authorization_key.password if conf.settings.SOCIAL_AUTH_FACEBOOK_KEY is None or conf.settings.SOCIAL_AUTH_FACEBOOK_SECRET is None: authorization_key = AuthorizationKey.objects.get(name="facebook") conf.settings.SOCIAL_AUTH_FACEBOOK_KEY = authorization_key.key conf.settings.SOCIAL_AUTH_FACEBOOK_SECRET = authorization_key.password context.social_strategy = load_strategy(context) # backward compatibility in attribute name, only if not already # defined if not hasattr(context, 'strategy'): context.strategy = context.social_strategy uri = reverse('social:complete', args=(backend,)) context.backend = load_backend(context.social_strategy, backend, uri) user_data = context.backend.user_data(token) if not user_data or not (user_data["email"] and user_data["email"].strip()): LOG.error('Empty email or id from social login received') LOG.error(user_data) raise JSONWebTokenError(_('Please, enter valid credentials')) user = context.backend.do_auth(token) if hasattr(context, 'user'): context.user = user result = f(cls, root, info, **kwargs) values = (user, result) token_issued.send(sender=cls, request=context, user=user) if is_thenable(result): return Promise.resolve(values).then(on_resolve) return on_resolve(values)
def test_get_username_no_user_and_no_username_available(self): """ No user connected and no username available in the details. Should throw an exception. """ backend = load_backend(strategy=self.strategy, name="edx-oauth2", redirect_uri="/") with self.assertRaises(AuthFailed): get_username(self.strategy, {}, backend)
def _link_user_to_third_party_provider( is_third_party_auth_enabled, third_party_auth_credentials_in_api, user, request, params, ): """ If a 3rd party auth provider and credentials were provided in the API, link the account with social auth (If the user is using the normal register page, the social auth pipeline does the linking, not this code) Note: this is orthogonal to the 3rd party authentication pipeline that occurs when the account is created via the browser and redirect URLs. """ third_party_provider, running_pipeline = None, None if is_third_party_auth_enabled and third_party_auth_credentials_in_api: backend_name = params['provider'] request.social_strategy = social_utils.load_strategy(request) redirect_uri = reverse('social:complete', args=(backend_name, )) request.backend = social_utils.load_backend(request.social_strategy, backend_name, redirect_uri) social_access_token = params.get('access_token') if not social_access_token: raise ValidationError({ 'access_token': [ _(u"An access_token is required when passing value ({}) for provider." ).format(params['provider']) ] }) request.session[ pipeline.AUTH_ENTRY_KEY] = pipeline.AUTH_ENTRY_REGISTER_API pipeline_user = None error_message = "" try: pipeline_user = request.backend.do_auth(social_access_token, user=user) except AuthAlreadyAssociated: error_message = _( "The provided access_token is already associated with another user." ) except (HTTPError, AuthException): error_message = _("The provided access_token is not valid.") if not pipeline_user or not isinstance(pipeline_user, User): # Ensure user does not re-enter the pipeline request.social_strategy.clean_partial_pipeline(social_access_token) raise ValidationError({'access_token': [error_message]}) # If the user is registering via 3rd party auth, track which provider they use if is_third_party_auth_enabled and pipeline.running(request): running_pipeline = pipeline.get(request) third_party_provider = provider.Registry.get_from_pipeline( running_pipeline) return third_party_provider, running_pipeline
def get(self, request): from social_django.utils import load_strategy, load_backend complete_url = reverse('social:complete', args=("saml",)) saml_backend = load_backend( load_strategy(request), "saml", redirect_uri=complete_url, ) metadata, errors = saml_backend.generate_metadata_xml() if not errors: return HttpResponse(content=metadata, content_type='text/xml')
def test_auth_allowed_step_disabled(self): """Asserts the authentication is not allowed when waffle switch is disabled.""" strategy = load_strategy() backend = load_backend(strategy, "saml_fer", None) with mock.patch( "marsha.account.social_pipeline.social_auth.social_auth_allowed" ) as social_create_user_mock: details = {"not": "relevant"} self.assertFalse( auth_allowed(backend, details, strategy, 42, some_kwargs=18)) self.assertFalse(social_create_user_mock.called)
def test_authenticate(self): backend = load_backend(strategy=self.strategy, name='facebook', redirect_uri='/') user = mock.Mock() with mock.patch('social_core.backends.base.BaseAuth.pipeline', return_value=user): result = self.strategy.authenticate(backend=backend, response=mock.Mock()) self.assertEqual(result, user) self.assertEqual(result.backend, 'social_core.backends.facebook.FacebookOAuth2')
def saml_metadata_view(request): complete_url = reverse('social:complete', args=("saml", )) saml_backend = load_backend( load_strategy(request), "saml", redirect_uri=complete_url, ) metadata, errors = saml_backend.generate_metadata_xml() print(errors) if not errors: return HttpResponse(content=metadata, content_type='text/xml') else: return HttpResponse(status=500)
def get(self, request, *args, **kwargs): redirect_uri = request.GET.get("redirect_uri") if redirect_uri not in settings.SOCIAL_AUTH_ALLOWED_REDIRECT_URIS: return Response(status=status.HTTP_400_BAD_REQUEST) strategy = load_strategy(request) strategy.session_set("redirect_uri", redirect_uri) backend_name = self.kwargs["provider"] backend = load_backend(strategy, backend_name, redirect_uri=redirect_uri) authorization_url = backend.auth_url() return Response(data={"authorization_url": authorization_url})
def mutate(self, info, accessToken, provider): from social_core.exceptions import MissingBackend from social_django.views import _do_login from social_django.utils import load_backend, load_strategy try: strategy = load_strategy(info.context) backend = load_backend(strategy, provider, redirect_uri=None) except MissingBackend: raise AuthError('Auth Provider Not Supported', code='INVALID_PROVIDER') user = backend.do_auth(accessToken, user=None) _do_login(backend, user, user.social_user) return {"success": True, "user": user.__dict__}
def get(self, request, *args, **kwargs): from social_django.utils import load_backend, load_strategy complete_url = reverse('social:complete', args=('saml',)) try: saml_backend = load_backend(load_strategy(request), 'saml', redirect_uri=complete_url) metadata, errors = saml_backend.generate_metadata_xml() except Exception as e: logger.exception('unable to generate SAML metadata') errors = e if not errors: return HttpResponse(content=metadata, content_type='text/xml') else: return HttpResponse(content=str(errors), content_type='text/plain')
def test_process_exception_non_auth_error(rf, settings): """Tests that a process_exception handles non-auth exceptions correctly""" settings.DEBUG = False request = rf.get(reverse("social:complete", args=("email", ))) # social_django depends on request.sesssion, so use the middleware to set that SessionMiddleware().process_request(request) strategy = load_strategy(request) backend = load_backend(strategy, "email", None) request.social_strategy = strategy request.backend = backend middleware = SocialAuthExceptionRedirectMiddleware() assert (middleware.process_exception( request, Exception("something bad happened")) is None)
def create_logout_response(request, user, backend_name, redirect_uri): backend = load_backend(load_strategy(request), backend_name, redirect_uri=None) # social_auth creates a new user for each (provider, uid) pair so # we don't need to worry about duplicates try: social_user = UserSocialAuth.objects.get(user=user, provider=backend_name) except UserSocialAuth.DoesNotExist: return None if not hasattr(backend, 'create_logout_response'): return None return backend.create_logout_response(social_user, redirect_uri)
def _link_user_to_third_party_provider( is_third_party_auth_enabled, third_party_auth_credentials_in_api, user, request, params, ): """ If a 3rd party auth provider and credentials were provided in the API, link the account with social auth (If the user is using the normal register page, the social auth pipeline does the linking, not this code) Note: this is orthogonal to the 3rd party authentication pipeline that occurs when the account is created via the browser and redirect URLs. """ third_party_provider, running_pipeline = None, None if is_third_party_auth_enabled and third_party_auth_credentials_in_api: backend_name = params['provider'] request.social_strategy = social_utils.load_strategy(request) redirect_uri = reverse('social:complete', args=(backend_name, )) request.backend = social_utils.load_backend(request.social_strategy, backend_name, redirect_uri) social_access_token = params.get('access_token') if not social_access_token: raise ValidationError({ 'access_token': [ _("An access_token is required when passing value ({}) for provider.").format( params['provider'] ) ] }) request.session[pipeline.AUTH_ENTRY_KEY] = pipeline.AUTH_ENTRY_REGISTER_API pipeline_user = None error_message = "" try: pipeline_user = request.backend.do_auth(social_access_token, user=user) except AuthAlreadyAssociated: error_message = _("The provided access_token is already associated with another user.") except (HTTPError, AuthException): error_message = _("The provided access_token is not valid.") if not pipeline_user or not isinstance(pipeline_user, User): # Ensure user does not re-enter the pipeline request.social_strategy.clean_partial_pipeline(social_access_token) raise ValidationError({'access_token': [error_message]}) # If the user is registering via 3rd party auth, track which provider they use if is_third_party_auth_enabled and pipeline.running(request): running_pipeline = pipeline.get(request) third_party_provider = provider.Registry.get_from_pipeline(running_pipeline) return third_party_provider, running_pipeline
def saml_metadata_view(request): """ Get the Service Provider metadata for this edx-platform instance. You must send this XML to any Shibboleth Identity Provider that you wish to use. """ if not SAMLConfiguration.is_enabled(): raise Http404 complete_url = reverse('social:complete', args=("tpa-saml", )) if settings.APPEND_SLASH and not complete_url.endswith('/'): complete_url = complete_url + '/' # Required for consistency saml_backend = load_backend(load_strategy(request), "tpa-saml", redirect_uri=complete_url) metadata, errors = saml_backend.generate_metadata_xml() if not errors: return HttpResponse(content=metadata, content_type='text/xml') return HttpResponseServerError(content=', '.join(errors))
def get(self, request, *args, **kwargs): redirect_uri = request.GET.get('redirect_uri') if redirect_uri not in settings.SOCIAL_AUTH_ALLOWED_REDIRECT_URIS: return Response(status=status.HTTP_400_BAD_REQUEST) strategy = load_strategy(request) strategy.session_set('redirect_uri', redirect_uri) backend_name = self.kwargs['provider'] backend = load_backend( strategy, backend_name, redirect_uri=redirect_uri ) authorization_url = backend.auth_url() return Response(data={ 'authorization_url': authorization_url, })
def validate(self, attrs): request = self.context['request'] if 'state' in request.GET: self._validate_state(request.GET['state']) strategy = load_strategy(request) redirect_uri = strategy.session_get('redirect_uri') backend_name = self.context['view'].kwargs['provider'] backend = load_backend( strategy, backend_name, redirect_uri=redirect_uri ) try: user = backend.auth_complete() except exceptions.AuthException as e: raise serializers.ValidationError(str(e)) return {'user': user}
def get_request_and_strategy(self, auth_entry=None, redirect_uri=None): """Gets a fully-configured request and strategy. These two objects contain circular references, so we create them together. The references themselves are a mixture of normal __init__ stuff and monkey-patching done by python-social-auth. See, for example, social_django.utils.strategy(). """ request = self.request_factory.get( pipeline.get_complete_url(self.backend_name) + '?redirect_state=redirect_state_value&code=code_value&state=state_value') request.site = SiteFactory.create() request.user = auth_models.AnonymousUser() request.session = cache.SessionStore() request.session[self.backend_name + '_state'] = 'state_value' if auth_entry: request.session[pipeline.AUTH_ENTRY_KEY] = auth_entry strategy = social_utils.load_strategy(request=request) request.social_strategy = strategy request.backend = social_utils.load_backend(strategy, self.backend_name, redirect_uri) return request, strategy