Esempio n. 1
0
def get_login_providers(request, short=False):
    """
    Returns a list of available login providers based on the
    AUTHENTICATION_BACKENDS setting. Each provider is represented as a
    dictionary containing the backend name, name of required parameter if
    required and its verbose name.
    """
    def extract_backend_data(klass):
        """
        Helper function which extracts information useful for use in
        templates from SocialAuth subclasses and returns it as a
        dictionary.
        """
        return {
            'name': klass.name,
            'required_field': klass.REQUIRED_FIELD_NAME,
            'required_field_verbose': klass.REQUIRED_FIELD_VERBOSE_NAME,
        }

    backends = (module_member(auth_backend)
                for auth_backend in setting('AUTHENTICATION_BACKENDS'))
    providers = [
        extract_backend_data(backend) for backend in backends
        if issubclass(backend, BaseAuth)
    ]
    if short:
        return providers[:setting('AUTHENTICATION_PROVIDERS_BRIEF',
                                  DEFAULT_AUTHENTICATION_PROVIDERS_BRIEF)]
    return providers
Esempio n. 2
0
def get_login_providers(request, short=False):
    """
    Returns a list of available login providers based on the
    AUTHENTICATION_BACKENDS setting. Each provider is represented as a
    dictionary containing the backend name, name of required parameter if
    required and its verbose name.
    """
    def extract_backend_data(klass):
        """
        Helper function which extracts information useful for use in
        templates from SocialAuth subclasses and returns it as a
        dictionary.
        """
        return {
            'name': klass.name,
            'required_field': klass.REQUIRED_FIELD_NAME,
            'required_field_verbose': klass.REQUIRED_FIELD_VERBOSE_NAME,
        }

    backends = (module_member(auth_backend) for auth_backend in setting('AUTHENTICATION_BACKENDS'))
    providers = [extract_backend_data(backend) for backend in backends if issubclass(backend, BaseAuth)]
    if short:
        return providers[:setting('AUTHENTICATION_PROVIDERS_BRIEF',
                                  DEFAULT_AUTHENTICATION_PROVIDERS_BRIEF)]
    return providers
Esempio n. 3
0
def login(request):
    # TODO: Remove this in favor of redirect_authenticated_user once we
    # drop support for Django<1.10.
    if request.user.is_authenticated():
        next_page = request.GET.get('next', request.POST.get('next', ''))
        if not is_safe_url(url=next_page, host=request.get_host()):
            next_page = resolve_url(setting('LOGIN_REDIRECT_URL'))
        return HttpResponseRedirect(next_page)
    return auth_login(request, template_name='ksp_login/login.html',
                      extra_context=login_providers(request))
Esempio n. 4
0
def auth(request, backend):
    # Save any defined next value into session
    data = request.POST if request.method == 'POST' else request.GET

    # Save extra data into session.
    for field_name in request.strategy.setting('FIELDS_STORED_IN_SESSION', []):
        if field_name in data:
            request.session[field_name] = data[field_name]

    if REDIRECT_FIELD_NAME in data:
        # Check and sanitize a user-defined GET/POST next field value
        redirect = data[REDIRECT_FIELD_NAME]
        if setting('SANITIZE_REDIRECTS', True):
            redirect = sanitize_redirect(request.get_host(), redirect)
        request.session[REDIRECT_FIELD_NAME] = redirect or DEFAULT_REDIRECT
    return request.strategy.start()
Esempio n. 5
0
def register(request, creation_form=KspUserCreationForm):
    """
    As the name suggests, registers a new user.

    Can replace the create_user function in the SOCIAL_AUTH pipeline
    (through ksp_login.pipeline.register_user, with the corresponding
    save_status_to_session, of course) to make it possible for the user to
    pick a username.

    Also presents additional app-specific forms listed in the
    KSP_LOGIN_PROFILE_FORMS setting to the user.
    """
    if request.user.is_authenticated():
        return redirect('account_settings')
    try:
        pipeline_state = request.session[setting('SOCIAL_AUTH_PARTIAL_PIPELINE_KEY',
                                                 SOCIAL_AUTH_PARTIAL_PIPELINE_KEY)]
        backend = pipeline_state['backend']
        pipeline_state = pipeline_state['kwargs']
        standalone = False
    except KeyError:
        standalone = True

    form_classes = [creation_form] + get_profile_forms()

    if request.method == "POST":
        forms = [form(request.POST, request=request)
                 for form in form_classes]
        if all(form.is_valid() for form in forms):
            user = forms[0].save()
            for form in forms[1:]:
                form.set_user(user)
                form.save()
            if standalone:
                return redirect('account_login')
            pipeline_state['user'] = user.id
            # This ensures the top-level session dict changes, otherwise
            # our changes in pipeline_state might not get stored.
            request.session.setdefault('ksp_login_dummy_key', 0)
            request.session['ksp_login_dummy_key'] += 1
            return redirect('social:complete', backend=backend)
    else:
        forms = [form(request=request) for form in form_classes]

    return render(request, "ksp_login/registration.html", {
        'forms': forms,
    })
Esempio n. 6
0
def register(request, creation_form=KspUserCreationForm):
    """
    As the name suggests, registers a new user.

    Can replace the create_user function in the SOCIAL_AUTH pipeline
    (through ksp_login.pipeline.register_user, with the corresponding
    save_status_to_session, of course) to make it possible for the user to
    pick a username.

    Also presents additional app-specific forms listed in the
    KSP_LOGIN_PROFILE_FORMS setting to the user.
    """
    if request.user.is_authenticated():
        return redirect('account_settings')
    try:
        pipeline_state = request.session[setting(
            'SOCIAL_AUTH_PARTIAL_PIPELINE_KEY',
            SOCIAL_AUTH_PARTIAL_PIPELINE_KEY)]
        backend = pipeline_state['backend']
        pipeline_state = pipeline_state['kwargs']
        standalone = False
    except KeyError:
        standalone = True

    form_classes = [creation_form] + get_profile_forms()

    if request.method == "POST":
        forms = [form(request.POST, request=request) for form in form_classes]
        if all(form.is_valid() for form in forms):
            user = forms[0].save()
            for form in forms[1:]:
                form.set_user(user)
                form.save()
            if standalone:
                return redirect('account_login')
            pipeline_state['user'] = user.id
            # This ensures the top-level session dict changes, otherwise
            # our changes in pipeline_state might not get stored.
            request.session.setdefault('ksp_login_dummy_key', 0)
            request.session['ksp_login_dummy_key'] += 1
            return redirect('social:complete', backend=backend)
    else:
        forms = [form(request=request) for form in form_classes]

    return render(request, "ksp_login/registration.html", {
        'forms': forms,
    })
Esempio n. 7
0
    def __init__(self, *args, **kwargs):
        """
        If the user is registering via an external service, this gathers
        initial data from the service and marks the password fields as
        optional, otherwise it just sets the help_text of the first
        password field.
        """
        try:
            request = kwargs['request']
            del kwargs['request']
        except KeyError:
            raise TypeError("Argument 'request' missing.")
        try:
            pipeline_state = request.session[setting('SOCIAL_AUTH_PARTIAL_PIPELINE_KEY',
                                                     SOCIAL_AUTH_PARTIAL_PIPELINE_KEY)]
            pipeline_state = pipeline_state['kwargs']
            self.password_required = False
        except KeyError:
            self.password_required = True
            pipeline_state = None
        if not args and 'initial' not in kwargs:
            kwargs['initial'] = self.get_initial_from_pipeline(pipeline_state)

        super(KspUserCreationForm, self).__init__(*args, **kwargs)

        self.fields['password1'].help_text = _(
            "We recommend choosing a strong passphrase but we don't "
            "enforce any ridiculous constraints on your passwords."
        )

        if not self.password_required:
            self.fields['password1'].required = False
            self.fields['password2'].required = False
            self.fields['password1'].help_text = string_concat(_(
                "Since you're logging in using an external provider, "
                "this field is optional; however, by supplying it, you "
                "will be able to log in using a password. "
            ), self.fields['password1'].help_text)
Esempio n. 8
0
from django.contrib.auth import login, REDIRECT_FIELD_NAME, BACKEND_SESSION_KEY
from django.contrib.auth.decorators import login_required
from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.views.decorators.http import require_POST

from social.actions import do_auth, do_complete, do_disconnect
from social.apps.django_app.utils import strategy, setting, BackendWrapper

DEFAULT_REDIRECT = setting('LOGIN_REDIRECT_URL')
LOGIN_ERROR_URL = setting('LOGIN_ERROR_URL', setting('LOGIN_URL'))


@strategy('social:complete')
def auth(request, backend):
    return do_auth(request.strategy, redirect_name=REDIRECT_FIELD_NAME)


@csrf_exempt
@strategy('social:complete')
def complete(request, backend, *args, **kwargs):
    """Authentication complete view, override this view if transaction
    management doesn't suit your needs."""
    return do_complete(request.strategy,
                       _do_login,
                       request.user,
                       redirect_name=REDIRECT_FIELD_NAME,
                       *args,
                       **kwargs)


@login_required
Esempio n. 9
0
def get_profile_forms():
    form_names = setting('KSP_LOGIN_PROFILE_FORMS', [])
    return [import_string(name) for name in form_names]
Esempio n. 10
0
from django.contrib.auth import login, REDIRECT_FIELD_NAME, BACKEND_SESSION_KEY
from django.contrib.auth.decorators import login_required
from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.views.decorators.http import require_POST

from social.apps.actions import do_auth, do_complete, do_disconnect
from social.apps.django_app.utils import strategy, setting, BackendWrapper


DEFAULT_REDIRECT = setting('LOGIN_REDIRECT_URL')
LOGIN_ERROR_URL = setting('LOGIN_ERROR_URL', setting('LOGIN_URL'))


@strategy('social:complete')
def auth(request, backend):
    return do_auth(request.strategy, redirect_name=REDIRECT_FIELD_NAME)


@csrf_exempt
@strategy('social:complete')
def complete(request, backend, *args, **kwargs):
    """Authentication complete view, override this view if transaction
    management doesn't suit your needs."""
    return do_complete(request.strategy, _do_login, request.user,
                       redirect_name=REDIRECT_FIELD_NAME, *args, **kwargs)


@login_required
@strategy()
@require_POST
@csrf_protect
Esempio n. 11
0
def complete(request, backend, *args, **kwargs):
    """Authentication complete view, override this view if transaction
    management doesn't suit your needs."""
    strategy = request.strategy
    # pop redirect value before the session is trashed on login()
    redirect_value = request.session.get(REDIRECT_FIELD_NAME, '') or \
                     request.REQUEST.get(REDIRECT_FIELD_NAME, '')

    is_authenticated = user_is_authenticated(request.user)
    user = is_authenticated and request.user or None
    url = DEFAULT_REDIRECT

    if request.session.get('partial_pipeline'):
        data = request.session.pop('partial_pipeline')
        kwargs = kwargs.copy()
        kwargs.setdefault('user', user)
        idx, xargs, xkwargs = strategy.from_session(data, request=request,
                                                    *args, **kwargs)
        if xkwargs.get('backend', '') == backend:
            user = strategy.continue_pipeline(pipeline_index=idx,
                                              *xargs, **xkwargs)
        else:
            strategy.clean_partial_pipeline()
            user = strategy.complete(user=user, request=request,
                                     *args, **kwargs)
    else:
        user = strategy.complete(user=user, request=request,
                                 *args, **kwargs)

    if isinstance(user, HttpResponse):
        return user

    if is_authenticated:
        if not user:
            url = redirect_value or DEFAULT_REDIRECT
        else:
            url = redirect_value or \
                  strategy.setting('NEW_ASSOCIATION_REDIRECT_URL') or \
                  DEFAULT_REDIRECT
    elif user:
        if user_is_active(user):
            # catch is_new flag before login() resets the instance
            is_new = getattr(user, 'is_new', False)
            login(request, user)
            # Hack django.auth backend loading since they create an instance
            # that won't know about the strategy/storage layout being used
            request.session['original_' + BACKEND_SESSION_KEY] = \
                    request.session[BACKEND_SESSION_KEY]
            request.session[BACKEND_SESSION_KEY] = '%s.%s' % (
                BackendWrapper.__module__,
                BackendWrapper.__name__
            )
            # user.social_user is the used UserSocialAuth instance defined
            # in authenticate process
            social_user = user.social_user

            if setting('SESSION_EXPIRATION', True):
                # Set session expiration date if present and not disabled
                # by setting. Use last social-auth instance for current
                # provider, users can associate several accounts with
                # a same provider.
                expiration = social_user.expiration_datetime()
                if expiration:
                    try:
                        request.session.set_expiry(expiration)
                    except OverflowError:
                        # Handle django time zone overflow
                        request.session.set_expiry(None)

            # store last login backend name in session
            request.session['social_auth_last_login_backend'] = \
                    social_user.provider

            # Remove possible redirect URL from session, if this is a new
            # account, send him to the new-users-page if defined.
            new_user_redirect = strategy.setting('NEW_USER_REDIRECT_URL')
            if new_user_redirect and is_new:
                url = new_user_redirect
            else:
                url = redirect_value or strategy.setting('LOGIN_REDIRECT_URL')
        else:
            url = strategy.setting('INACTIVE_USER_URL', LOGIN_ERROR_URL)
    else:
        url = strategy.setting('LOGIN_ERROR_URL', LOGIN_ERROR_URL)

    if redirect_value and redirect_value != url:
        redirect_value = quote(redirect_value)
        url += ('?' in url and '&' or '?') + \
               '%s=%s' % (REDIRECT_FIELD_NAME, redirect_value)
    return HttpResponseRedirect(url)