def test_does_not_need_refresh(self): self.provider.refresh_time = 1 external_account = ExternalAccountFactory( provider='mock2', provider_id='mock_provider_id', provider_name='Mock Provider', oauth_key='old_key', oauth_secret='old_secret', refresh_token='old_refresh', expires_at=datetime.utcfromtimestamp(time.time() + 200).replace(tzinfo=pytz.utc), ) # mock a successful call to the provider to refresh tokens httpretty.register_uri(httpretty.POST, self.provider.auto_refresh_url, body=json.dumps( {'err_msg': 'Should not be hit'}), status=500) # .reload() has the side effect of rounding the microsends down to 3 significant figures # (e.g. DT(YMDHMS, 365420) becomes DT(YMDHMS, 365000)), # but must occur after possible refresh to reload tokens. # Doing so before allows the `old_expiry == EA.expires_at` comparison to work. external_account.reload() old_expiry = external_account.expires_at self.provider.account = external_account self.provider.refresh_oauth_key(force=False) external_account.reload() assert_equal(external_account.oauth_key, 'old_key') assert_equal(external_account.refresh_token, 'old_refresh') assert_equal(external_account.expires_at, old_expiry)
def test_does_need_refresh(self): external_account = ExternalAccountFactory( provider='mock2', provider_id='mock_provider_id', provider_name='Mock Provider', oauth_key='old_key', oauth_secret='old_secret', expires_at=datetime.utcfromtimestamp(time.time() - 200).replace(tzinfo=pytz.utc), ) # mock a successful call to the provider to refresh tokens httpretty.register_uri(httpretty.POST, self.provider.auto_refresh_url, body=json.dumps({ 'access_token': 'refreshed_access_token', 'expires_in': 3600, 'refresh_token': 'refreshed_refresh_token' })) old_expiry = external_account.expires_at self.provider.account = external_account self.provider.refresh_oauth_key(force=False) external_account.reload() assert_equal(external_account.oauth_key, 'refreshed_access_token') assert_equal(external_account.refresh_token, 'refreshed_refresh_token') assert_not_equal(external_account.expires_at, old_expiry) assert_true(external_account.expires_at > old_expiry)
def test_does_need_refresh(self): external_account = ExternalAccountFactory( provider='mock2', provider_id='mock_provider_id', provider_name='Mock Provider', oauth_key='old_key', oauth_secret='old_secret', expires_at=datetime.utcfromtimestamp(time.time() - 200).replace(tzinfo=pytz.utc), ) # mock a successful call to the provider to refresh tokens responses.add( responses.Response( responses.POST, self.provider.auto_refresh_url, body=json.dumps({ 'access_token': 'refreshed_access_token', 'expires_in': 3600, 'refresh_token': 'refreshed_refresh_token' }) ) ) old_expiry = external_account.expires_at self.provider.account = external_account self.provider.refresh_oauth_key(force=False) external_account.reload() assert_equal(external_account.oauth_key, 'refreshed_access_token') assert_equal(external_account.refresh_token, 'refreshed_refresh_token') assert_not_equal(external_account.expires_at, old_expiry) assert_true(external_account.expires_at > old_expiry)
def test_does_not_need_refresh(self): self.provider.refresh_time = 1 external_account = ExternalAccountFactory( provider='mock2', provider_id='mock_provider_id', provider_name='Mock Provider', oauth_key='old_key', oauth_secret='old_secret', refresh_token='old_refresh', expires_at=datetime.utcfromtimestamp(time.time() + 200).replace(tzinfo=pytz.utc), ) # mock a successful call to the provider to refresh tokens httpretty.register_uri( httpretty.POST, self.provider.auto_refresh_url, body=json.dumps({ 'err_msg': 'Should not be hit' }), status=500 ) # .reload() has the side effect of rounding the microsends down to 3 significant figures # (e.g. DT(YMDHMS, 365420) becomes DT(YMDHMS, 365000)), # but must occur after possible refresh to reload tokens. # Doing so before allows the `old_expiry == EA.expires_at` comparison to work. external_account.reload() old_expiry = external_account.expires_at self.provider.account = external_account self.provider.refresh_oauth_key(force=False) external_account.reload() assert_equal(external_account.oauth_key, 'old_key') assert_equal(external_account.refresh_token, 'old_refresh') assert_equal(external_account.expires_at, old_expiry)
def test_multiple_users_associated(self): # Create only one ExternalAccount for multiple OSF users # # For some providers (ex: GitHub), the act of completing the OAuth flow # revokes previously generated credentials. In addition, there is often no # way to know the user's id on the external service until after the flow # has completed. # # Having only one ExternalAccount instance per account on the external # service means that connecting subsequent OSF users to the same external # account will not invalidate the credentials used by the OSF for users # already associated. user_a = UserFactory() external_account = ExternalAccountFactory( provider='mock2', provider_id='mock_provider_id', provider_name='Mock Provider', ) user_a.external_accounts.add(external_account) user_a.save() user_b = UserFactory() # Mock the exchange of the code for an access token _prepare_mock_oauth2_handshake_response() # Fake a request context for the callback with self.app.app.test_request_context( path="/oauth/callback/mock2/", query_string="code=mock_code&state=mock_state" ) as ctx: # make sure the user is logged in authenticate(user=user_b, access_token=None, response=None) session.data['oauth_states'] = { self.provider.short_name: { 'state': 'mock_state', }, } session.save() # do the key exchange self.provider.auth_callback(user=user_b) user_a.reload() user_b.reload() external_account.reload() assert_equal( list(user_a.external_accounts.values_list('pk', flat=True)), list(user_b.external_accounts.values_list('pk', flat=True)), ) assert_equal( ExternalAccount.find().count(), 1 )
def test_multiple_users_associated(self): # Create only one ExternalAccount for multiple OSF users # # For some providers (ex: GitHub), the act of completing the OAuth flow # revokes previously generated credentials. In addition, there is often no # way to know the user's id on the external service until after the flow # has completed. # # Having only one ExternalAccount instance per account on the external # service means that connecting subsequent OSF users to the same external # account will not invalidate the credentials used by the OSF for users # already associated. user_a = UserFactory() external_account = ExternalAccountFactory( provider='mock2', provider_id='mock_provider_id', provider_name='Mock Provider', ) user_a.external_accounts.add(external_account) user_a.save() user_b = UserFactory() # Mock the exchange of the code for an access token _prepare_mock_oauth2_handshake_response() # Fake a request context for the callback with self.app.app.test_request_context( path="/oauth/callback/mock2/", query_string="code=mock_code&state=mock_state" ) as ctx: # make sure the user is logged in authenticate(user=user_b, access_token=None, response=None) session.data['oauth_states'] = { self.provider.short_name: { 'state': 'mock_state', }, } session.save() # do the key exchange self.provider.auth_callback(user=user_b) user_a.reload() user_b.reload() external_account.reload() assert_equal( list(user_a.external_accounts.values_list('pk', flat=True)), list(user_b.external_accounts.values_list('pk', flat=True)), ) assert_equal( ExternalAccount.objects.all().count(), 1 )