def auth_complete(self, *args, **kwargs):
        """Completes loging process, must return user instance"""
        try:
            context_id = self.strategy.request.session.get('_krb5', None)

            if context_id not in self._krb5:
                raise AuthException(
                    self.name, 'Authentication failed. context_id not found!')

            if not self._krb5[context_id].complete:
                raise AuthException(self.name, 'Authentication failed')

            kwargs.update({
                'response': {
                    'krb5_initiator':
                    str(self._krb5[context_id].initiator_name),
                },
                'backend': self,
            })
        finally:
            if context_id in self._krb5:
                del self._krb5[context_id]

            if '_krb5' in self.strategy.request.session:
                del self.strategy.request.session['_krb5']

        return self.strategy.authenticate(*args, **kwargs)
Example #2
0
def save_profile(backend, user, response, *args, **kwargs):
    userpic_key, user_about_url = None, None
    if backend.name == 'google-oauth2':
        userpic_key = 'picture'
    elif backend.name == 'vk-oauth2':
        userpic_key = 'user_photo'

        user_about_requested_fields = ('bdate',)
        user_about_url = urlunparse(
            ('https',  # scheme
             'api.vk.com',  # netloc
             '/method/users.get',  # path
             None,  # params
             urlencode({
                 'fields': ','.join(user_about_requested_fields),
                 'access_token': response.get('access_token', None),
                 'version': '5.95',
             }),  # query
             None  # fragment
             )
        )

    if userpic_key and \
            not user.shopuserextended.udpate_userpic(response.get(userpic_key)):
        raise AuthException("Cannot update userpic")

    if user_about_url:
        age_status = user.validate_age(user_about_url)
        if age_status is None:
            logger.error(f"Cannot define age by URL {user_about_url}")
        elif not age_status:
            raise AuthException("Age must be more than 17")
Example #3
0
def verify_open(strategy, backend, user=None, **kwargs):
    """Check whether it is possible to create new user."""
    if not user and not settings.REGISTRATION_OPEN:
        raise AuthException(backend, _('New registrations are disabled!'))

    if user and settings.DEMO_SERVER and user.username == 'demo':
        raise AuthException(backend,
                            _('Can not change authentication for demo!'))
Example #4
0
def verify_open(strategy, backend, user=None, **kwargs):
    """Check whether it is possible to create new user."""
    # Check whether registration is open
    if not user and not settings.REGISTRATION_OPEN:
        raise AuthException(backend, _('New registrations are disabled!'))

    # Avoid adding associations to demo user
    if user and settings.DEMO_SERVER and user.username == 'demo':
        raise AuthException(backend,
                            _('Can not change authentication for demo!'))

    # Ensure it's still same user
    request = strategy.request
    if request.user.pk != request.session.get('social_auth_user'):
        raise AuthStateForbidden(backend, 'user')
Example #5
0
def verify_open(strategy, backend, user=None, **kwargs):
    """Check whether it is possible to create new user."""

    if not user and not settings.REGISTRATION_OPEN:
        raise AuthException(backend, _('New registrations are disabled!'))

    if user and settings.DEMO_SERVER and user.username == 'demo':
        raise AuthException(backend,
                            _('Can not change authentication for demo!'))

    # This is mostly fix for lack of next validation in Python Social Auth
    # see https://github.com/python-social-auth/social-core/issues/62
    url = backend.strategy.session_get('next')
    if url and not is_safe_url(url):
        backend.strategy.session_set('next', None)
Example #6
0
def check_user_allowed(strategy, backend, details, *args, **kwargs):
    """
    Check if a social platform account is being attached to a Django account.
    If it is, the Django account must be active in order to continue.
    """
    user_id = strategy.session_get('user_id')

    if not user_id:
        return None

    user = backend.strategy.storage.user.get_user(pk=user_id)
    if user is None:
        raise AuthException(backend, 'Account not found')
    if not user.is_active:
        raise AuthException(backend, 'Account is not activated')
Example #7
0
def associate_by_email(backend, details, user=None, *args, **kwargs):
    """
    Associate current auth with a user with the same email address in the DB.

    This pipeline entry is not 100% secure unless you know that the providers
    enabled enforce email verification on their side, otherwise a user can
    attempt to take over another user account by using the same (not validated)
    email address on some provider.  This pipeline entry is disabled by
    default.
    """
    if user:
        return None

    email = details.get('email')
    if email:
        # Try to associate accounts registered with the same email address,
        # only if it's a single object. AuthException is raised if multiple
        # objects are returned.
        users = list(backend.strategy.storage.user.get_users_by_email(email))
        if len(users) == 0:
            social = UserSocialAuth.objects.filter(
                uid=email, provider='email'
            ).first()
            if social:
                return {'user': social.user}
            else:
                return None
        elif len(users) > 1:
            raise AuthException(
                backend,
                'The given email address is associated with another account'
            )
        else:
            return {'user': users[0]}
Example #8
0
def verify_open(strategy, backend, user=None, **kwargs):
    '''
    Checks whether it is possible to create new user.
    '''

    if not user and not settings.REGISTRATION_OPEN:
        raise AuthException(backend, _('New registrations are disabled!'))
Example #9
0
    def get_engine(self, request=None):
        """
        Retrieves dataset service engine
        """
        # Get Token for HydroShare interactions
        if self.engine == self.HYDROSHARE:
            # Constants
            HYDROSHARE_OAUTH_PROVIDER_NAME = 'hydroshare'
            user = request.user

            try:
                # social = user.social_auth.get(provider='google-oauth2')
                social = user.social_auth.get(
                    provider=HYDROSHARE_OAUTH_PROVIDER_NAME)
                apikey = social.extra_data['access_token']  # noqa: F841
            except ObjectDoesNotExist:
                # User is not associated with that provider
                # Need to prompt for association
                raise AuthException(
                    "HydroShare authentication required. To automate the authentication prompt "
                    "decorate your controller function with the @ensure_oauth('hydroshare') decorator."
                )

            return HydroShareDatasetEngine(endpoint=self.endpoint,
                                           username=self.username,
                                           password=self.password,
                                           apikey=self.apikey)

        return CkanDatasetEngine(endpoint=self.endpoint,
                                 username=self.username,
                                 password=self.password,
                                 apikey=self.apikey)
    def unauthorized_token(self):
        """
        Return request for unauthorized token (first stage)

        Mediawiki request token is requested from e.g.:
         * https://en.wikipedia.org/w/index.php?title=Special:OAuth/initiate
        """
        params = self.request_token_extra_arguments()
        params.update(self.get_scope_argument())
        params['title'] = 'Special:OAuth/initiate'
        key, secret = self.get_key_and_secret()
        print(key, secret)
        print(self.setting('URL'))
        response = self.request(self.setting('URL'),
                                params=params,
                                auth=OAuth1(
                                    key,
                                    secret,
                                    callback_uri=self.setting('CALLBACK')),
                                method=self.REQUEST_TOKEN_METHOD)

        if response.content.decode().startswith('Error'):
            raise AuthException(self, response.content.decode())

        return response.content.decode()
def check_social_data(backend, details, *args, **kwargs):
    if backend.name != 'deezer' and not (kwargs.get('email')
                                         or details.get('email')):
        raise AuthException(
            backend,
            _('Email address is required in order to complete the registration!'
              ))
    return {}
Example #12
0
    def user_data(self):
        """
        Returns user data from the JWT
        """
        jwt_decode_handler = api_settings.JWT_DECODE_HANDLER

        cookies = self.strategy.request.COOKIES

        if api_settings.JWT_AUTH_COOKIE not in cookies:
            raise AuthException(self, "Authorization header not present")

        auth = cookies.get(api_settings.JWT_AUTH_COOKIE)

        try:
            # this should have the remote username in the ID_KEY field
            return jwt_decode_handler(auth)
        except jwt.InvalidTokenError as exc:
            raise AuthException(self, "Invalid JWT") from exc
Example #13
0
def associate_by_name_id(backend,
                         details,
                         response,
                         request,
                         user=None,
                         *args,
                         **kwargs):
    """ Этот пайплайн занимается поиском пользователя по nameId в зависимости от параметра name_id_type из конфига """
    idp = backend.get_idp(response['idp_name'])
    name_id_type = idp.conf['name_id_type']
    name_id = response['attributes']['name_id']
    request.session['saml:nameid'] = name_id

    # Дополнительные параметры на основе IDP
    saml_superuser_ou = idp.conf.get('verme_superuser_ou', None)
    saml_create_user_employee = idp.conf.get('verme_create_user_employee',
                                             False)
    saml_update_user = idp.conf.get('verme_update_user', False)
    saml_update_employee = idp.conf.get('verme_update_employee', False)

    kwargs = None
    if name_id_type == 'username':
        kwargs = {'username': name_id}
    elif name_id_type == 'number':
        kwargs = {'employee__number': name_id}
    elif name_id_type == 'phone':
        kwargs = {'employee__notify_phone': name_id}
    else:  # email по умолчанию
        kwargs = {'email': name_id}

    users = list(User.objects.filter(**kwargs))
    params = response['attributes']

    # Если не нашли пользователя
    if len(users) == 0:
        # Если включено создание пользователя
        if saml_create_user_employee:
            user = create_or_update_employee(backend, saml_superuser_ou,
                                             **params)
        else:
            return None
    # Если нашли пользователя
    if len(users) == 1:
        # Если включено обновление пользователя
        if saml_update_user:
            user = create_or_update_employee(backend, saml_superuser_ou,
                                             saml_update_user,
                                             saml_update_employee, users[0],
                                             **params)
        else:
            user = users[0]
    # Если нашли несколько пользователей
    if len(users) > 1:
        raise AuthException(
            backend, f'Parameters {kwargs} are associated multiple users')
    return {'user': user, 'is_new': False}
Example #14
0
    def test_exception_handling(self):
        """Assert an AuthException results in a 400 error"""
        err = AuthException('openid', 'Auth error')
        exp_msg = (
            "Error: There was an error during authentication 'Auth error', "
            "please check the provided url.")

        msg, errno = app.auth_error_handler(err)

        self.assertEqual(400, errno)
        self.assertEqual(exp_msg, msg)
Example #15
0
def forbid_hijack(strategy, backend, **kwargs):  # pylint: disable=unused-argument
    """
    Forbid an admin user from trying to login/register while hijacking another user

    Args:
        strategy (social_django.strategy.DjangoStrategy): the strategy used to authenticate
        backend (social_core.backends.base.BaseAuth): the backend being used to authenticate
    """
    # As first step in pipeline, stop a hijacking admin from going any further
    if strategy.session_get("is_hijacked_user"):
        raise AuthException("You are hijacking another user, don't try to login again")
    return {}
Example #16
0
    def test_post_facebook_provider_code_validation_fails(self):
        data = {'code': 'XYZ', 'state': 'ABC'}

        mock.patch(
            'social_core.backends.facebook.FacebookOAuth2.auth_complete',
            side_effect=AuthException(backend=None)).start()
        mock.patch('social_core.backends.oauth.OAuthAuth.get_session_state',
                   return_value=data['state']).start()

        request = self.factory.post(data=data)
        response = self.view(request, provider='facebook')
        self.assert_status_equal(response, status.HTTP_400_BAD_REQUEST)
Example #17
0
    def get_user_details(self, response):
        """
        Returns detail about the user account from the service
        """

        current_req = get_current_request()
        site = getattr(current_req, "site", None)
        domain = getattr(site, "domain", None)
        try:
            user_site_domain = response["companyInfo"]["url"]

            if not domain:
                LOGGER.exception("Domain not found in request attributes")
                raise AuthException("Colaraz", "Error while authentication")
            elif user_site_domain.lower() not in domain:
                LOGGER.exception("User can only login through {} site".format(
                    user_site_domain))
                raise AuthException(
                    "Colaraz",
                    "Your account belongs to {}".format(user_site_domain))

            details = {
                "fullname":
                u"{} {}".format(response["firstName"],
                                response["lastName"]).encode(
                                    "ascii", "ignore"),
                "email":
                response["email"],
                "first_name":
                response["firstName"],
                "last_name":
                response["lastName"],
                "username":
                response["email"]
            }
            return details
        except KeyError:
            LOGGER.exception("User profile data is unappropriate or not given")
            raise AuthException(
                "Colaraz", "User profile data is unappropriate or not given")
Example #18
0
def check_email_exists(backend, details, uid, user=None, *args, **kwargs):
    email = details.get('email', '')
    provider = backend.name

    # check if social user exists to allow logging in (not sure if this is necessary)
    social = backend.strategy.storage.user.get_social_auth(provider, uid)
    # check if given email is in use
    exists = Account.objects.filter(email=email).exists()

    # user is not logged in, social profile with given uid doesn't exist
    # and email is in use
    if not user and not social and exists:
        raise AuthException(backend)
Example #19
0
def initialize_engine_object(engine,
                             endpoint,
                             apikey=None,
                             username=None,
                             password=None,
                             request=None):
    """
    Initialize a DatasetEngine object from a string that points at the engine class.
    """
    # Constants
    HYDROSHARE_OAUTH_PROVIDER_NAME = 'hydroshare'

    # Derive import parts from engine string
    engine_split = engine.split('.')
    module_string = '.'.join(engine_split[:-1])
    engine_class_string = engine_split[-1]

    # Import
    module = __import__(module_string, fromlist=[engine_class_string])
    EngineClass = getattr(module, engine_class_string)

    # Get Token for HydroShare interactions
    if EngineClass is HydroShareDatasetEngine:
        user = request.user

        try:
            # social = user.social_auth.get(provider='google-oauth2')
            social = user.social_auth.get(
                provider=HYDROSHARE_OAUTH_PROVIDER_NAME)
            apikey = social.extra_data['access_token']
        except ObjectDoesNotExist:
            # User is not associated with that provider
            # Need to prompt for association
            raise AuthException(
                "HydroShare authentication required. To automate the authentication prompt decorate "
                "your controller function with the @ensure_oauth('hydroshare') decorator."
            )
        except AttributeError:
            # Anonymous User...
            raise
        except AuthAlreadyAssociated:
            raise
        except:
            raise

    # Create Engine Object
    engine_instance = EngineClass(endpoint=endpoint,
                                  apikey=apikey,
                                  username=username,
                                  password=password)
    return engine_instance
Example #20
0
def check_email_exists(backend, user, response, *args, **kwargs):
    # TODO twitter, google, facebook, github
    email = response.get('email')
    print(email)
    if not email:
        return
    # check if given email is in use
    count = User.objects.filter(username=email).count()

    # user is not logged in, social profile with given uid doesn't exist
    # and email is in use
    if not user and count:
        # TODO messages
        raise AuthException(backend, 'This email is already in use.')
Example #21
0
    def auth_complete(self, request, *args, **kwargs):
        print "Auth complete!", args, kwargs
        ssoParams = request.GET.get('sso')
        ssoSignature = request.GET.get('sig')
        paramSignature = hmac.new(settings.DISCOURSE_SSO_SECRET, ssoParams, sha256).hexdigest()

        if ssoSignature != paramSignature:
            raise AuthException('Could not verify discourse login')

        decodedParams = b64decode(ssoParams)
        kwargs.update({'sso':'', 'sig': '', 'backend': self, 'response':
            urlparse.parse_qs(decodedParams)})

        return self.strategy.authenticate(*args, **kwargs)
Example #22
0
def check_user_backend(is_new, user, *args, **kwargs):
    backend = kwargs['backend'].name
    user_email = kwargs['details']['email']
    if backend == GOOGLE_OAUTH2_SOCIAL_DJANGO_BACKEND and not User.objects.filter(
            email=user_email).exists():
        user_email_domain = user_email.split("@")[1]
        if user_email_domain == 'eventbrite.com':
            language = kwargs['request'].LANGUAGE_CODE
            user = User.objects.create_user(user_email,
                                            None,
                                            preferred_language=language)
        else:
            raise AuthException(backend, 'Invalid Login')
    return {'is_new': is_new, 'user': user}
Example #23
0
def unique_by_email(backend, details, user=None, *args, **kwargs):

    if user:
        return None

    email = details.get('email')
    if email:
        users = list(backend.strategy.storage.user.get_users_by_email(email))
        if len(users) == 0:
            return None
        else:
            raise AuthException(
                backend,
                'The given email address already exists'
            )
Example #24
0
    def test_post_facebook_provider_code_validation_fails(self):
        data = {"code": "XYZ", "state": "ABC"}

        mock.patch(
            "social_core.backends.facebook.FacebookOAuth2.auth_complete",
            side_effect=AuthException(backend=None),
        ).start()
        mock.patch(
            "social_core.backends.oauth.OAuthAuth.get_session_state",
            return_value=data["state"],
        ).start()

        request = self.factory.post()
        request.GET = {k: v for k, v in six.iteritems(data)}
        response = self.view(request, provider="facebook")
        self.assert_status_equal(response, status.HTTP_400_BAD_REQUEST)
Example #25
0
    def policy(self):
        request = self.strategy.request
        if request and hasattr(request, "policy"):
            #if request has a property policy, use that policy directly,
            #The features(mfa set, mfa reset, and password reset) use this proerty 'policy' to specific the customized policy
            policy = request.policy
        else:
            domain = (utils.get_domain(
                request.session.get(utils.REDIRECT_FIELD_NAME))
                      or utils.get_host(request)) if request else None
            if not domain or domain == settings.AUTH2_DOMAIN:
                #Domain is None or dmain is auth2, use the user flow's default policy
                userflow = CustomizableUserflow.get_userflow(None)
                logger.debug(
                    "Use the default userflow({1}.{2}) for domain({0})".format(
                        domain, userflow.domain, userflow.default))
                policy = userflow.default
            else:
                userflow = CustomizableUserflow.get_userflow(domain)
                if userflow.fixed:
                    #A fixed policy is configured for the domain related userflow, use it directly
                    logger.debug(
                        "Use the fixed userflow({1}.{2}) for domain({0})".
                        format(domain, userflow.domain, userflow.fixed))
                    policy = userflow.fixed
                else:
                    #if the cookie 'PREFERED_IDP_COOKIE' exists, and try to get the policy from the latest used idp
                    idpid = request.COOKIES.get(
                        settings.PREFERED_IDP_COOKIE_NAME,
                        None) if request else None
                    idp = IdentityProvider.get_idp(idpid) if idpid else None
                    if idp and idp.userflow:
                        #Found the latest used idp, and that idp has a configued user flow, use the user flow directly
                        policy = idp.userflow
                    else:
                        #Can't find the latest used idp, user the domain related userflow's default policy
                        policy = userflow.default

                    logger.debug(
                        "Prefered idp is '{}', Choosed userflow is '{}', request domain is '{}' "
                        .format(idp, policy, domain))

        if not policy or not policy.lower().startswith('b2c_'):
            raise AuthException('SOCIAL_AUTH_AZUREAD_B2C_OAUTH2_POLICY is '
                                'required and should start with `b2c_`')

        return policy
Example #26
0
    def get_redirect_uri(self, state=None):
        """
        Returns redirect uri for oauth redirection
        """
        current_req = get_current_request()

        environ = getattr(current_req, "environ", {})
        schema = environ.get("wsgi.url_scheme", "http")

        site = getattr(current_req, "site", None)
        domain = getattr(site, "domain", None)

        if not domain:
            LOGGER.exception("Domain not found in request attributes")
            raise AuthException("Colaraz", "Error while authentication")

        return "{}://{}/auth/complete/{}".format(schema, domain, self.name)
Example #27
0
def registrate_user(*args, **kwargs):
    print("===========================")
    pprint(kwargs)

    email = kwargs.get('details', {}).get('email', None)
    user = kwargs.get('user', None)
    is_new = kwargs.get('is_new', None)
    if not user:
        if email:
            user, is_new = User.objects.get_or_create(username=email,
                                                      email=email)
            return {"username": email, "user": user, "is_new": is_new}
        else:
            raise AuthException(kwargs['backend'])
    else:
        pass
    print("===========================")
def link_to_existing_user_by_email_if_backend_is_trusted(
        backend, details, user=None, *args, **kwargs):
    """Return user entry with same email address as one returned on details."""
    if user or not _is_trusted_email_backend(backend):
        return

    email = details.get('email')

    if email:
        # try to link accounts registered with the same email address,
        # only if it's a single object. AuthException is raised if multiple
        # objects are returned
        try:
            return {'user': EmailAddress.objects.get(email=email).user}
        except MultipleObjectsReturned:
            raise AuthException(kwargs['backend'], 'Not unique email address.')
        except ObjectDoesNotExist:
            pass
def associate_by_username(backend, details, user=None, *args, **kwargs):
    if user:
        return None

    username = details.get('username')
    if username:
        # Try to associate accounts registered with the same username,
        # only if it's a single object. AuthException is raised if multiple
        # objects are returned.
        users = list(User.objects.filter(agol_info__agol_username=username))
        if len(users) == 0:
            return None
        elif len(users) > 1:
            raise AuthException(
                backend,
                'The given username is associated with another account')
        else:
            return {'user': users[0], 'is_new': False}
Example #30
0
def associate_by_email_or_pause(strategy,
                                details,
                                user=None,
                                backend=None,
                                is_new=False,
                                *args,
                                **kwargs):
    """
    Associate current auth with a user with the same email address in the DB.

    This pipeline entry is not 100% secure unless you know that the providers
    enabled enforce email verification on their side, otherwise a user can
    attempt to take over another user account by using the same (not validated)
    email address on some provider.  This pipeline entry is disabled by
    default.

    We redirect the user to a access denied page where they can resume the
    login in the case an admin grants them access.
    """
    if user:
        return None

    email = details.get('email')
    if email:
        # Try to associate accounts registered with the same email address,
        # only if it's a single object. AuthException is raised if multiple
        # objects are returned.
        users = list(strategy.storage.user.get_users_by_email(email))
        if len(users) == 0:
            # Redirect to an error page notifying user their email hasn't
            # been added by the admins. This page can be re-visited once the
            # user account has been added to the system.
            current_partial = kwargs.get('current_partial')
            return strategy.redirect(
                '/request-access?partial_token={0}&backend={1}'.format(
                    current_partial.token, backend.name))
        elif len(users) > 1:
            raise AuthException(
                backend,
                'The given email address is associated with another account')
        else:
            return {'user': users[0], 'is_new': False}