Esempio n. 1
0
def partial_pipeline_data(backend, user=None, *args, **kwargs):  # pragma: no cover
    """
    Add the session key to a signed base64 encoded signature on the email request.
    """
    data = backend.strategy.request_data()
    if 'signature' in data:
        try:
            signed_details = signing.loads(data['signature'], key=settings.SECRET_KEY)
            session = Session.objects.get(pk=signed_details['session_key'])
        except (BadSignature, Session.DoesNotExist) as e:
            raise InvalidEmail(backend)

        session_details = session.get_decoded()
        backend.strategy.session_set('email_validation_address', session_details['email_validation_address'])
        backend.strategy.session_set('next', session_details.get('next'))
        backend.strategy.session_set('partial_pipeline', session_details['partial_pipeline'])
        backend.strategy.session_set(backend.name + '_state', session_details.get(backend.name + '_state'))
        backend.strategy.session_set(backend.name + 'unauthorized_token_name',
                                     session_details.get(backend.name + 'unauthorized_token_name'))

    partial = backend.strategy.session_get('partial_pipeline', None)
    if partial:
        idx, backend_name, xargs, xkwargs = \
            backend.strategy.partial_from_session(partial)
        if backend_name == backend.name:
            kwargs.setdefault('pipeline_index', idx)
            if user:  # don't update user if it's None
                kwargs.setdefault('user', user)
            kwargs.setdefault('request', backend.strategy.request_data())
            xkwargs.update(kwargs)
            return xargs, xkwargs
        else:
            backend.strategy.clean_partial_pipeline()
Esempio n. 2
0
def mail_validation(backend, details, is_new=False, *args, **kwargs):
    """Mail validation taken from Python Social Auth master.

    It just allows to pass partial_token without API change.

    Can be removed once we depend on something newer than social_core 1.2.0.
    """
    requires_validation = backend.REQUIRES_EMAIL_VALIDATION or \
        backend.setting('FORCE_EMAIL_VALIDATION', False)
    do_send_validation = details.get('email') and \
        (is_new or backend.setting('PASSWORDLESS', False))
    if requires_validation and do_send_validation:
        data = backend.strategy.request_data()
        if 'verification_code' in data:
            backend.strategy.session_pop('email_validation_address')
            if not backend.strategy.validate_email(details['email'],
                                                   data['verification_code']):
                raise InvalidEmail(backend)
        else:
            current_partial = kwargs.get('current_partial')
            # Hack to pass
            backend.partial_token = current_partial.token
            backend.strategy.send_email_validation(backend, details['email'])
            backend.strategy.session_set('email_validation_address',
                                         details['email'])
            return backend.strategy.redirect(
                backend.strategy.setting('EMAIL_VALIDATION_URL'))
Esempio n. 3
0
def partial_pipeline_data(backend, user=None, *args, **kwargs):
    """
    Monkey-patch utils.partial_pipeline_data to enable us to retrieve session data by signature key in request.
    This is necessary to allow users to follow a link in an email to validate their account from a different
    browser than the one they were using to sign up for the account, or after they've closed/re-opened said
    browser and potentially flushed their cookies. By adding the session key to a signed base64 encoded signature
    on the email request, we can retrieve the necessary details from our Django session table.
    We fetch only the needed details to complete the pipeline authorization process from the session, to prevent
    nefarious use.
    """
    data = backend.strategy.request_data()
    if 'signature' in data:
        try:
            signed_details = signing.loads(data['signature'],
                                           key=settings.EMAIL_SECRET_KEY)
            session = Session.objects.get(pk=signed_details['session_key'])
        except BadSignature, Session.DoesNotExist:
            raise InvalidEmail(backend)

        session_details = session.get_decoded()
        backend.strategy.session_set(
            'email_validation_address',
            session_details['email_validation_address'])
        backend.strategy.session_set('next', session_details.get('next'))
        backend.strategy.session_set('partial_pipeline',
                                     session_details['partial_pipeline'])
        backend.strategy.session_set(
            backend.name + '_state',
            session_details.get(backend.name + '_state'))
        backend.strategy.session_set(
            backend.name + 'unauthorized_token_name',
            session_details.get(backend.name + 'unauthorized_token_name'))
Esempio n. 4
0
def custom_mail_validation(backend, details, user=None, is_new=False, force_update=False, *args, **kwargs):
    """Email validation pipeline

    Verify email or send email with validation link.
    """
    requires_validation = (
        backend.REQUIRES_EMAIL_VALIDATION or backend.setting('FORCE_EMAIL_VALIDATION', False)
    )

    u_hash = backend.strategy.request.POST.get('u_hash')
    u_hash_sess = backend.strategy.session_get('u_hash')

    not_tester_join_course = True
    if u_hash or u_hash_sess:
        not_tester_join_course = u_hash != u_hash_sess

    send_validation = (
        details.get('email') and (is_new or backend.setting('PASSWORDLESS', False)) and not_tester_join_course
    )
    if requires_validation and send_validation and backend.name == 'email':
        data = backend.strategy.request_data()
        if 'verification_code' in data:
            backend.strategy.session_pop('email_validation_address')
            if not backend.strategy.validate_email(
                    details.get('email'),
                    data.get('verification_code')
            ):
                raise InvalidEmail(backend)
            code = backend.strategy.storage.code.get_code(data['verification_code'])
            # This is very straightforward method
            # TODO Need to check current user to avoid unnecessary check
            if code.user_id:
                user_from_code = User.objects.filter(id=code.user_id).first()
                if user_from_code:
                    user = user_from_code
                    _next = code.next_page or backend.strategy.request.session.get('next')
                    logout(backend.strategy.request)
                    user.backend = 'django.contrib.auth.backends.ModelBackend'
                    login(backend.strategy.request, user)
                    if _next == reverse('accounts:settings'):
                        messages.add_message(
                            backend.strategy.request, messages.SUCCESS, 'Email has been successfully updated')
                    backend.strategy.session_set('next', _next)
                    return {'user': user, 'force_update': code.force_update or force_update}
        else:
            if user and user.groups.filter(name='Temporary').exists():
                AnonymEmail.objects.get_or_create(
                    user=user,
                    email=details.get('email'),
                    defaults={'date': datetime.now()}
                )
            code = backend.strategy.send_email_validation(backend, details.get('email'), force_update=force_update)
            backend.strategy.session_set('email_validation_address', details.get('email'))
            backend.strategy.session_set('next', data.get('next'))
            return backend.strategy.redirect(
                backend.strategy.setting('EMAIL_VALIDATION_URL')
            )
Esempio n. 5
0
def mail_validation(backend, details, is_new=False, *args, **kwargs):
    requires_validation = backend.REQUIRES_EMAIL_VALIDATION or \
                          backend.setting('FORCE_EMAIL_VALIDATION', False)
    send_validation = details.get('email') and \
                      (is_new or backend.setting('PASSWORDLESS', False))
    if requires_validation and send_validation:
        data = backend.strategy.request_data()
        if 'verification_code' in data:
            backend.strategy.session_pop('email_validation_address')
            if not backend.strategy.validate_email(details['email'],
                                                   data['verification_code']):
                raise InvalidEmail(backend)
        else:
            backend.strategy.send_email_validation(backend, details['email'])
            backend.strategy.session_set('email_validation_address',
                                         details['email'])
            return backend.strategy.redirect(
                backend.strategy.setting('EMAIL_VALIDATION_URL'))
Esempio n. 6
0
def partial_pipeline_data(backend, user=None, *args, **kwargs):  # pragma: no cover
    """
    Add the session key to a signed base64 encoded signature on the email request.
    """
    data = backend.strategy.request_data()
    if 'signature' in data:
        try:
            signed_details = signing.loads(data['signature'], key=settings.SECRET_KEY)
            session = Session.objects.get(pk=signed_details['session_key'])
        except BadSignature, Session.DoesNotExist:
            raise InvalidEmail(backend)

        session_details = session.get_decoded()
        backend.strategy.session_set('email_validation_address', session_details['email_validation_address'])
        backend.strategy.session_set('next', session_details.get('next'))
        backend.strategy.session_set('partial_pipeline', session_details['partial_pipeline'])
        backend.strategy.session_set(backend.name + '_state', session_details.get(backend.name + '_state'))
        backend.strategy.session_set(backend.name + 'unauthorized_token_name',
                                     session_details.get(backend.name + 'unauthorized_token_name'))
Esempio n. 7
0
def verify_email(backend, details, *args, **kwargs):
    if not details['email'] or not details['email'].endswith('@saitm.org'):
        raise InvalidEmail(backend)
Esempio n. 8
0
def verify_email(backend, details, *args, **kwargs):
    if not details['email']:
        raise InvalidEmail(backend)
Esempio n. 9
0
from authentication.utils import SocialAuthState

EMAIL = "*****@*****.**"
TOKEN = {"token": "value"}

pytestmark = [pytest.mark.django_db]


@pytest.mark.parametrize(
    "side_effect,result",
    (
        (
            AuthException(None, "message"),
            SocialAuthState(SocialAuthState.STATE_ERROR, errors=["message"]),
        ),
        (InvalidEmail(None),
         SocialAuthState(SocialAuthState.STATE_INVALID_EMAIL)),
    ),
)
def test_social_auth_serializer_error(mocker, side_effect, result):
    """Tests that an AuthException exception is converted correctly"""
    mocked_authenticate = mocker.patch(
        "authentication.serializers.SocialAuthSerializer._authenticate")
    mocked_authenticate.side_effect = side_effect

    result.flow = SocialAuthState.FLOW_REGISTER
    result.provider = EmailAuth.name

    serializer = RegisterEmailSerializer(
        data={
            "flow": result.flow,