|
| 1 | +from urllib.parse import quote |
| 2 | + |
| 3 | +from social_core.utils import sanitize_redirect, user_is_authenticated, \ |
| 4 | + user_is_active, partial_pipeline_data, setting_url |
| 5 | + |
| 6 | + |
| 7 | +def do_auth(backend, redirect_name='next'): |
| 8 | + # Save any defined next value into session |
| 9 | + data = backend.strategy.request_data(merge=False) |
| 10 | + |
| 11 | + # Save extra data into session. |
| 12 | + for field_name in backend.setting('FIELDS_STORED_IN_SESSION', []): |
| 13 | + if field_name in data: |
| 14 | + backend.strategy.session_set(field_name, data[field_name]) |
| 15 | + else: |
| 16 | + backend.strategy.session_set(field_name, None) |
| 17 | + # uri = None |
| 18 | + if redirect_name in data: |
| 19 | + # Check and sanitize a user-defined GET/POST next field value |
| 20 | + redirect_uri = data[redirect_name] |
| 21 | + if backend.setting('SANITIZE_REDIRECTS', True): |
| 22 | + allowed_hosts = backend.setting('ALLOWED_REDIRECT_HOSTS', []) + \ |
| 23 | + [backend.strategy.request_host()] |
| 24 | + redirect_uri = sanitize_redirect(allowed_hosts, redirect_uri) |
| 25 | + backend.strategy.session_set( |
| 26 | + redirect_name, |
| 27 | + redirect_uri or backend.setting('LOGIN_REDIRECT_URL') |
| 28 | + ) |
| 29 | + response = backend.start() |
| 30 | + url = response.url.split('?')[1] |
| 31 | + |
| 32 | + def form2json(form_data): |
| 33 | + from urllib.parse import parse_qs, urlparse |
| 34 | + query = urlparse('?' + form_data).query |
| 35 | + params = parse_qs(query) |
| 36 | + return {key: params[key][0] for key in params} |
| 37 | + from django.core.cache import cache |
| 38 | + cache.set("oidc_key_" + data.get('key', ''), form2json(url).get('state'), 60 * 10) |
| 39 | + return response |
| 40 | + |
| 41 | + |
| 42 | +def do_complete(backend, login, user=None, redirect_name='next', |
| 43 | + *args, **kwargs): |
| 44 | + data = backend.strategy.request_data() |
| 45 | + |
| 46 | + is_authenticated = user_is_authenticated(user) |
| 47 | + user = user if is_authenticated else None |
| 48 | + |
| 49 | + partial = partial_pipeline_data(backend, user, *args, **kwargs) |
| 50 | + if partial: |
| 51 | + user = backend.continue_pipeline(partial) |
| 52 | + # clean partial data after usage |
| 53 | + backend.strategy.clean_partial_pipeline(partial.token) |
| 54 | + else: |
| 55 | + user = backend.complete(user=user, *args, **kwargs) |
| 56 | + |
| 57 | + # pop redirect value before the session is trashed on login(), but after |
| 58 | + # the pipeline so that the pipeline can change the redirect if needed |
| 59 | + redirect_value = backend.strategy.session_get(redirect_name, '') or \ |
| 60 | + data.get(redirect_name, '') |
| 61 | + |
| 62 | + # check if the output value is something else than a user and just |
| 63 | + # return it to the client |
| 64 | + user_model = backend.strategy.storage.user.user_model() |
| 65 | + if user and not isinstance(user, user_model): |
| 66 | + return user |
| 67 | + |
| 68 | + if is_authenticated: |
| 69 | + if not user: |
| 70 | + url = setting_url(backend, redirect_value, 'LOGIN_REDIRECT_URL') |
| 71 | + else: |
| 72 | + url = setting_url(backend, redirect_value, |
| 73 | + 'NEW_ASSOCIATION_REDIRECT_URL', |
| 74 | + 'LOGIN_REDIRECT_URL') |
| 75 | + elif user: |
| 76 | + if user_is_active(user): |
| 77 | + # catch is_new/social_user in case login() resets the instance |
| 78 | + is_new = getattr(user, 'is_new', False) |
| 79 | + social_user = user.social_user |
| 80 | + login(backend, user, social_user) |
| 81 | + # store last login backend name in session |
| 82 | + backend.strategy.session_set('social_auth_last_login_backend', |
| 83 | + social_user.provider) |
| 84 | + |
| 85 | + if is_new: |
| 86 | + url = setting_url(backend, |
| 87 | + 'NEW_USER_REDIRECT_URL', |
| 88 | + redirect_value, |
| 89 | + 'LOGIN_REDIRECT_URL') |
| 90 | + else: |
| 91 | + url = setting_url(backend, redirect_value, |
| 92 | + 'LOGIN_REDIRECT_URL') |
| 93 | + else: |
| 94 | + if backend.setting('INACTIVE_USER_LOGIN', False): |
| 95 | + social_user = user.social_user |
| 96 | + login(backend, user, social_user) |
| 97 | + url = setting_url(backend, 'INACTIVE_USER_URL', 'LOGIN_ERROR_URL', |
| 98 | + 'LOGIN_URL') |
| 99 | + else: |
| 100 | + url = setting_url(backend, 'LOGIN_ERROR_URL', 'LOGIN_URL') |
| 101 | + |
| 102 | + if redirect_value and redirect_value != url: |
| 103 | + redirect_value = quote(redirect_value) |
| 104 | + url += ('&' if '?' in url else '?') + \ |
| 105 | + '{0}={1}'.format(redirect_name, redirect_value) |
| 106 | + |
| 107 | + if backend.setting('SANITIZE_REDIRECTS', True): |
| 108 | + allowed_hosts = backend.setting('ALLOWED_REDIRECT_HOSTS', []) + \ |
| 109 | + [backend.strategy.request_host()] |
| 110 | + url = sanitize_redirect(allowed_hosts, url) or \ |
| 111 | + backend.setting('LOGIN_REDIRECT_URL') |
| 112 | + response = backend.strategy.redirect(url) |
| 113 | + social_auth = user.social_auth.filter(provider='drycc').\ |
| 114 | + order_by('-modified').last() |
| 115 | + response.set_cookie("name", user.username, |
| 116 | + max_age=social_auth.extra_data.get('expires_in')) |
| 117 | + response.set_cookie("id_token", social_auth.extra_data.get('id_token'), |
| 118 | + max_age=social_auth.extra_data.get('expires_in')) |
| 119 | + from django.core.cache import cache |
| 120 | + cache.set("oidc_state_" + data.get('state'), |
| 121 | + {'token': social_auth.extra_data.get('id_token', 'fail'), |
| 122 | + 'username': user.username}, |
| 123 | + 60 * 10) |
| 124 | + return response |
0 commit comments