st4lk / django-rest-social-auth

OAuth signin with django rest framework
MIT License
521 stars 122 forks source link

[TODO] Partial IN SOCIAL_AUTH_PIPELINE #105

Open wuuuduu opened 4 years ago

wuuuduu commented 4 years ago

Tested with these settings using SIMPLE JWT:

Maybe someone has time to go further with this?

settings:

SOCIAL_AUTH_FACEBOOK_KEY = 'facebook_public_key'
SOCIAL_AUTH_FACEBOOK_SECRET = 'facebook_secret_key'
SOCIAL_AUTH_FACEBOOK_SCOPE = ['email', ]
SOCIAL_AUTH_FACEBOOK_FORCE_EMAIL_VALIDATION = True
EMAIL_VALIDATION_FUNCTION = 'jwt_auth.pipeline.email.send_email_verification',

SOCIAL_AUTH_FACEBOOK_PROFILE_EXTRA_PARAMS = {
    'fields': ','.join([
        # public_profile
        'id', 'cover', 'name', 'first_name', 'last_name', 'age_range', 'link',
        'gender', 'locale', 'picture', 'timezone', 'updated_time', 'verified',
        # extra fields
        'email',
    ]),
}

SOCIAL_AUTH_PIPELINE = (
    'social_core.pipeline.social_auth.social_details',
    'social_core.pipeline.social_auth.social_uid',
    'social_core.pipeline.social_auth.auth_allowed',
    'jwt_auth.pipeline.email.check_for_email',  # custom action
    'social_core.pipeline.social_auth.social_user',
    'social_core.pipeline.user.get_username',
    'jwt_auth.pipeline.email.mail_validation',  # custom action | partial
    'social_core.pipeline.user.create_user',
    'social_core.pipeline.social_auth.associate_user',
    'social_core.pipeline.social_auth.load_extra_data',
    'social_core.pipeline.user.user_details',
)

jwt_auth.pipeline.email.send_email_verification:

def send_email_verification(strategy, backend, code, partial_token):
    print('sending email veryfication! code={code}, partial_token: {partial_token}'.format(code=code,
                                                                                           partial_token=partial_token
                                                                                           ))

jwt_auth.pipeline.email.check_for_email:

def check_for_email(backend, uid, user=None, *args, **kwargs):
    if not kwargs['details'].get('email'):
        return Response({'error': "Email wasn't provided by oauth provider"}, status=400)

jwt_auth.pipeline.email.mail_validation:

@partial
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']):
                return Response(
                    {
                        'error': "Verification code for email {email} is wrong or already confirmed.".format(
                            email=details['email']
                        )
                    },
                    status=400
                )
        else:
            current_partial = kwargs.get('current_partial')
            backend.strategy.send_email_validation(backend,
                                                   details['email'],
                                                   current_partial.token)
            backend.strategy.session_set('email_validation_address',
                                         details['email'])

            return Response(
                {
                    'error': "Waiting for verification_code for email {email}".format(email=details['email'])
                },
                status=400
            )
jd-solanki commented 4 years ago

Hi @wuuuduu can you please mention the flow of continuing the pipeline once we pause it by sending response from partial pipeline?

Do I have to create view to handle it? Do I need to add social_django's views & URLs in my project?

Awaiting your response.

~ Regards