def process_do_auth(self, user_profile, *args, **kwargs): # type: (UserProfile, *Any, **Any) -> Optional[HttpResponse] # This function needs to be imported from here due to the cyclic # dependency. from zerver.views.auth import login_or_register_remote_user, redirect_to_subdomain_login_url from zerver.views import redirect_and_log_into_subdomain return_data = kwargs.get("return_data", {}) inactive_user = return_data.get("inactive_user") inactive_realm = return_data.get("inactive_realm") invalid_subdomain = return_data.get("invalid_subdomain") if inactive_user or inactive_realm: return None strategy = self.strategy # type: ignore # This comes from Python Social Auth. request = strategy.request email_address = self.get_email_address(*args, **kwargs) full_name = self.get_full_name(*args, **kwargs) subdomain = strategy.session_get("subdomain") if not subdomain: return login_or_register_remote_user( request, email_address, user_profile, full_name, bool(invalid_subdomain) ) try: realm = Realm.objects.get(string_id=subdomain) except Realm.DoesNotExist: return redirect_to_subdomain_login_url() return redirect_and_log_into_subdomain(realm, full_name, email_address)
def process_do_auth(self, user_profile, *args, **kwargs): # type: (UserProfile, *Any, **Any) -> Optional[HttpResponse] # This function needs to be imported from here due to the cyclic # dependency. from zerver.views.auth import (login_or_register_remote_user, redirect_to_subdomain_login_url) from zerver.views import redirect_and_log_into_subdomain return_data = kwargs.get('return_data', {}) inactive_user = return_data.get('inactive_user') inactive_realm = return_data.get('inactive_realm') invalid_subdomain = return_data.get('invalid_subdomain') if inactive_user or inactive_realm: return None strategy = self.strategy # type: ignore # This comes from Python Social Auth. request = strategy.request email_address = self.get_email_address(*args, **kwargs) full_name = self.get_full_name(*args, **kwargs) subdomain = strategy.session_get('subdomain') if not subdomain: return login_or_register_remote_user(request, email_address, user_profile, full_name, bool(invalid_subdomain)) try: realm = Realm.objects.get(string_id=subdomain) except Realm.DoesNotExist: return redirect_to_subdomain_login_url() return redirect_and_log_into_subdomain(realm, full_name, email_address)
def finish_google_oauth2(request): # type: (HttpRequest) -> HttpResponse error = request.GET.get('error') if error == 'access_denied': return redirect('/') elif error is not None: logging.warning('Error from google oauth2 login: %s' % (request.GET.get("error"),)) return HttpResponse(status=400) csrf_state = request.GET.get('state') if csrf_state is None or len(csrf_state.split(':')) != 3: logging.warning('Missing Google oauth2 CSRF state') return HttpResponse(status=400) value, hmac_value, subdomain = csrf_state.split(':') if hmac_value != google_oauth2_csrf(request, value + subdomain): logging.warning('Google oauth2 CSRF error') return HttpResponse(status=400) resp = requests.post( 'https://www.googleapis.com/oauth2/v3/token', data={ 'code': request.GET.get('code'), 'client_id': settings.GOOGLE_OAUTH2_CLIENT_ID, 'client_secret': settings.GOOGLE_OAUTH2_CLIENT_SECRET, 'redirect_uri': ''.join(( settings.EXTERNAL_URI_SCHEME, settings.EXTERNAL_HOST, reverse('zerver.views.auth.finish_google_oauth2'), )), 'grant_type': 'authorization_code', }, ) if resp.status_code == 400: logging.warning('User error converting Google oauth2 login to token: %s' % (resp.text,)) return HttpResponse(status=400) elif resp.status_code != 200: logging.error('Could not convert google oauth2 code to access_token: %s' % (resp.text,)) return HttpResponse(status=400) access_token = resp.json()['access_token'] resp = requests.get( 'https://www.googleapis.com/plus/v1/people/me', params={'access_token': access_token} ) if resp.status_code == 400: logging.warning('Google login failed making info API call: %s' % (resp.text,)) return HttpResponse(status=400) elif resp.status_code != 200: logging.error('Google login failed making API call: %s' % (resp.text,)) return HttpResponse(status=400) body = resp.json() try: full_name = body['name']['formatted'] except KeyError: # Only google+ users have a formated name. I am ignoring i18n here. full_name = u'{} {}'.format( body['name']['givenName'], body['name']['familyName'] ) for email in body['emails']: if email['type'] == 'account': break else: logging.error('Google oauth2 account email not found: %s' % (body,)) return HttpResponse(status=400) email_address = email['value'] if not subdomain: # When request was not initiated from subdomain. user_profile, return_data = authenticate_remote_user(request, email_address) invalid_subdomain = bool(return_data.get('invalid_subdomain')) return login_or_register_remote_user(request, email_address, user_profile, full_name, invalid_subdomain) try: realm = Realm.objects.get(string_id=subdomain) except Realm.DoesNotExist: return redirect_to_subdomain_login_url() return redirect_and_log_into_subdomain(realm, full_name, email_address)
def finish_google_oauth2(request): # type: (HttpRequest) -> HttpResponse error = request.GET.get('error') if error == 'access_denied': return redirect('/') elif error is not None: logging.warning('Error from google oauth2 login: %s' % (request.GET.get("error"), )) return HttpResponse(status=400) csrf_state = request.GET.get('state') if csrf_state is None or len(csrf_state.split(':')) != 3: logging.warning('Missing Google oauth2 CSRF state') return HttpResponse(status=400) value, hmac_value, subdomain = csrf_state.split(':') if hmac_value != google_oauth2_csrf(request, value + subdomain): logging.warning('Google oauth2 CSRF error') return HttpResponse(status=400) resp = requests.post( 'https://www.googleapis.com/oauth2/v3/token', data={ 'code': request.GET.get('code'), 'client_id': settings.GOOGLE_OAUTH2_CLIENT_ID, 'client_secret': settings.GOOGLE_OAUTH2_CLIENT_SECRET, 'redirect_uri': ''.join(( settings.EXTERNAL_URI_SCHEME, settings.EXTERNAL_HOST, reverse('zerver.views.auth.finish_google_oauth2'), )), 'grant_type': 'authorization_code', }, ) if resp.status_code == 400: logging.warning( 'User error converting Google oauth2 login to token: %s' % (resp.text, )) return HttpResponse(status=400) elif resp.status_code != 200: logging.error( 'Could not convert google oauth2 code to access_token: %s' % (resp.text, )) return HttpResponse(status=400) access_token = resp.json()['access_token'] resp = requests.get('https://www.googleapis.com/plus/v1/people/me', params={'access_token': access_token}) if resp.status_code == 400: logging.warning('Google login failed making info API call: %s' % (resp.text, )) return HttpResponse(status=400) elif resp.status_code != 200: logging.error('Google login failed making API call: %s' % (resp.text, )) return HttpResponse(status=400) body = resp.json() try: full_name = body['name']['formatted'] except KeyError: # Only google+ users have a formated name. I am ignoring i18n here. full_name = u'{} {}'.format(body['name']['givenName'], body['name']['familyName']) for email in body['emails']: if email['type'] == 'account': break else: logging.error('Google oauth2 account email not found: %s' % (body, )) return HttpResponse(status=400) email_address = email['value'] if not subdomain: # When request was not initiated from subdomain. user_profile, return_data = authenticate_remote_user( request, email_address) invalid_subdomain = bool(return_data.get('invalid_subdomain')) return login_or_register_remote_user(request, email_address, user_profile, full_name, invalid_subdomain) try: realm = Realm.objects.get(string_id=subdomain) except Realm.DoesNotExist: return redirect_to_subdomain_login_url() return redirect_and_log_into_subdomain(realm, full_name, email_address)