예제 #1
0
파일: views.py 프로젝트: slonidet/volunteer
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
예제 #2
0
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)
예제 #3
0
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
예제 #4
0
    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))
예제 #5
0
    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"])