def oauth2_callback(): try: if login_via_test_token(): return redirect('/') except: return 'error', 500 flow = flow_from_clientsecrets(get_path_to_oauth_secrets(), scope='https://www.googleapis.com/auth/userinfo.email', redirect_uri=f'{authentication.get_host_for_request(request)}/_/auth/oauth2_callback') if not session.get('oauth_state') or session.get('oauth_state') != request.args.get('state'): return redirect(url_for('base.login')) try: credentials = flow.step2_exchange(request.args.get('code')) except (FlowExchangeError, ValueError) as e: logging.warning(e) # user declined to auth; move on return redirect(session.get('redirect_to_after_oauth', '/')) user_email = authentication.get_user_email(credentials) if user_email: authentication.login('google', user_email=user_email) return redirect(session.get('redirect_to_after_oauth', '/'))
def get(self): if self.session.get('pickled_oauth_flow'): flow = pickle.loads(self.session['pickled_oauth_flow']) else: flow = flow_from_clientsecrets( get_path_to_oauth_secrets(), scope='https://www.googleapis.com/auth/userinfo.email', redirect_uri='https://trot.to/_/auth/oauth2_callback') if not self.session.get('oauth_state') or self.session.get( 'oauth_state') != self.request.get('state'): self.redirect('/_/auth/login') return try: credentials = flow.step2_exchange(self.request.get('code')) except (FlowExchangeError, ValueError): # user declined to auth; move on self.redirect(self.session.get('redirect_to_after_oauth', '/')) return self.session['credentials'] = pickle.dumps(credentials) self.session['user_email'] = authentication.get_user_email(credentials) user = get_or_create_user( self.session['user_email'], get_organization_id_for_email(self.session['user_email'])) if not user.accepted_terms_at: # all login methods now have UI for consenting to terms user.accepted_terms_at = datetime.datetime.utcnow() user.put() self.redirect(self.session.get('redirect_to_after_oauth', '/'))
def test_get_user_email__not_gmail_or_google_workspace(self): mock_oauth_credentials = Mock() mock_oauth_credentials.id_token = { 'email_verified': True, 'hd': None, 'email': '*****@*****.**' } self.assertEqual(None, authentication.get_user_email(mock_oauth_credentials))
def test_get_user_email__email_not_verified(self): mock_oauth_credentials = Mock() mock_oauth_credentials.id_token = { 'email_verified': False, 'hd': 'googs.com', 'email': '*****@*****.**' } self.assertEqual(None, authentication.get_user_email(mock_oauth_credentials))
def test_get_user_email__success__mixed_case(self): mock_oauth_credentials = Mock() mock_oauth_credentials.id_token = { 'email_verified': True, 'hd': None, 'email': '*****@*****.**' } self.assertEqual('*****@*****.**', authentication.get_user_email(mock_oauth_credentials))
def test_get_user_email__success__google_workspace(self): mock_oauth_credentials = Mock() mock_oauth_credentials.id_token = { 'email_verified': True, 'hd': 'googs.com', 'email': '*****@*****.**' } self.assertEqual('*****@*****.**', authentication.get_user_email(mock_oauth_credentials))
def get(self): if self.request.get('r'): # outgoing request self.session['request_data_to_replay'] = str(self.request.get('r')) self.render_login_selector_page(self.request.path_url) return try: original_request_data = json.loads(base64.urlsafe_b64decode(self.session['request_data_to_replay'])) except (KeyError, ValueError): self.redirect('/') return if self.request.get('code'): flow = pickle.loads(self.session['pickled_oauth_flow']) try: credentials = flow.step2_exchange(self.request.get('code')) except (FlowExchangeError, ValueError): # user declined to auth; move on self.redirect(original_request_data['origin']) return self.session['credentials'] = pickle.dumps(credentials) self.session['user_email'] = authentication.get_user_email(credentials) self.user_email = self.session['user_email'] self.user_org = get_organization_id_for_email(self.user_email) else: # assume this was a login via email, which would have been processed in the base handler pass object_data = json.loads(original_request_data['body']) new_link = None try: new_link = helpers.create_short_link(self.user_org, self.user_email, object_data['shortpath'], object_data['destination']) response_data = { 'shortpath': new_link.shortpath, 'destination': new_link.destination_url } except helpers.LinkCreationException as e: response_data = { 'error': str(e) } self.redirect(str(original_request_data['origin'] + '?r=' + base64.urlsafe_b64encode(json.dumps(response_data))))