public void clearOauth2Data() { final String oauth2token = getOauth2Token(); preferences.edit() .remove(OAUTH2_USER) .commit(); getCredentials().edit() .remove(OAUTH2_TOKEN) .remove(OAUTH2_REFRESH_TOKEN) .commit(); if (!TextUtils.isEmpty(oauth2token)) { new TokenRefresher(context, new OAuth2Client(getOAuth2ClientId()), this).invalidateToken(oauth2token); } }
private RestoreState handleAuthError(RestoreConfig config, int currentRestoredItem, XOAuth2AuthenticationFailedException e) { if (e.getStatus() == 400) { Log.d(TAG, "need to perform xoauth2 token refresh"); if (config.tries < 1) { try { tokenRefresher.refreshOAuth2Token(); // we got a new token, let's retry one more time - we need to pass in a new store object // since the auth params on it are immutable return restore(config.retryWithStore(currentRestoredItem, service.getBackupImapStore())); } catch (MessagingException ignored) { Log.w(TAG, ignored); } catch (TokenRefreshException refreshException) { Log.w(TAG, refreshException); } } else { Log.w(TAG, "no new token obtained, giving up"); } } else { Log.w(TAG, "unexpected xoauth status code " + e.getStatus()); } return transition(SmsSyncState.ERROR, e); }
private void refreshUsingAccountManager(String token, String name) throws TokenRefreshException { if (accountManager == null) throw new TokenRefreshException("account manager is null"); invalidateToken(token); try { Bundle bundle = getAuthToken(new Account(name, GOOGLE_TYPE)); if (bundle != null) { String newToken = bundle.getString(AccountManager.KEY_AUTHTOKEN); if (!isEmpty(newToken)) { authPreferences.setOauth2Token(name, newToken, null); } else { throw new TokenRefreshException("no new token obtained"); } } else { throw new TokenRefreshException("no bundle received from accountmanager"); } } catch (AccountsException e) { Log.w(TAG, e); throw new TokenRefreshException(e); } catch (IOException e) { Log.w(TAG, e); throw new TokenRefreshException(e); } }
private Bundle getAuthToken(Account account) throws AccountsException, IOException { if (Build.VERSION.SDK_INT >= 14) { return getAuthTokenApi14(account); } else { return getAuthTokenPreApi14(account); } }
public void refreshOAuth2Token() throws TokenRefreshException{ final String token = authPreferences.getOauth2Token(); final String refreshToken = authPreferences.getOauth2RefreshToken(); final String name = authPreferences.getOauth2Username(); if (isEmpty(token)) { throw new TokenRefreshException("no current token set"); } if (!isEmpty(refreshToken)) { // user authenticated using webflow refreshUsingOAuth2Client(name, refreshToken); } else { refreshUsingAccountManager(token, name); } }
@Before public void before() { initMocks(this); refresher = new TokenRefresher(accountManager, oauth2Client, authPreferences); }
@Test public void shouldHandleSecurityExceptionWhenInvalidatingToken() throws Exception { doThrow(new SecurityException()).when(accountManager).invalidateAuthToken(GOOGLE_TYPE, "token"); assertThat(refresher.invalidateToken("token")).isFalse(); }
BackupTask(@NonNull SmsBackupService service) { final Context context = service.getApplicationContext(); this.service = service; this.authPreferences = service.getAuthPreferences(); this.preferences = service.getPreferences(); this.fetcher = new BackupItemsFetcher( context.getContentResolver(), new BackupQueryBuilder(preferences.getDataTypePreferences())); PersonLookup personLookup = new PersonLookup(service.getContentResolver()); this.contactAccessor = new ContactAccessor(); this.converter = new MessageConverter(context, service.getPreferences(), authPreferences.getUserEmail(), personLookup, contactAccessor); if (preferences.isCallLogCalendarSyncEnabled()) { calendarSyncer = new CalendarSyncer( CalendarAccessor.Get.instance(service.getContentResolver()), preferences.getCallLogCalendarId(), personLookup, new CallFormatter(context.getResources()) ); } else { calendarSyncer = null; } this.tokenRefresher = new TokenRefresher(service, new OAuth2Client(authPreferences.getOAuth2ClientId()), authPreferences); }
@Test public void shouldInvalidateTokenManually() throws Exception { assertThat(refresher.invalidateToken("token")).isTrue(); verify(accountManager).invalidateAuthToken(GOOGLE_TYPE, "token"); }
@Test public void shouldSetNewTokenAfterRefresh() throws Exception { when(authPreferences.getOauth2Token()).thenReturn("token"); when(authPreferences.getOauth2Username()).thenReturn("username"); AccountManagerFuture<Bundle> future = mock(AccountManagerFuture.class); when(accountManager.getAuthToken( new Account("username", GOOGLE_TYPE), AUTH_TOKEN_TYPE, null,true, null, null) ).thenReturn(future); Bundle bundle = new Bundle(); bundle.putString(AccountManager.KEY_AUTHTOKEN, "newToken"); when(future.getResult()).thenReturn(bundle); refresher.refreshOAuth2Token(); verify(authPreferences).setOauth2Token("username", "newToken", null); }
new TokenRefresher(service, new OAuth2Client(authPreferences.getOAuth2ClientId()), authPreferences)).execute(config);
@Test public void shouldUseOAuth2ClientWhenRefreshTokenIsPresent() throws Exception { when(authPreferences.getOauth2Token()).thenReturn("token"); when(authPreferences.getOauth2RefreshToken()).thenReturn("refresh"); when(authPreferences.getOauth2Username()).thenReturn("username"); when(oauth2Client.refreshToken("refresh")).thenReturn(new OAuth2Token("newToken", "type", null, 0, null)); refresher.refreshOAuth2Token(); verify(authPreferences).setOauth2Token("username", "newToken", "refresh"); }
@Test public void shouldUpdateRefreshTokenIfPresentInResponse() throws Exception { when(authPreferences.getOauth2Token()).thenReturn("token"); when(authPreferences.getOauth2RefreshToken()).thenReturn("refresh"); when(authPreferences.getOauth2Username()).thenReturn("username"); when(oauth2Client.refreshToken("refresh")).thenReturn(new OAuth2Token("newToken", "type", "newRefresh", 0, null)); refresher.refreshOAuth2Token(); verify(authPreferences).setOauth2Token("username", "newToken", "newRefresh"); } }
@Test public void shouldHandleAuthErrorAndTokenCannotBeRefreshed() throws Exception { mockFetch(SMS, 1); when(converter.convertMessages(any(Cursor.class), notNull(DataType.class))).thenReturn(result(SMS, 1)); XOAuth2AuthenticationFailedException exception = mock(XOAuth2AuthenticationFailedException.class); when(exception.getStatus()).thenReturn(400); when(store.getFolder(notNull(DataType.class), same(dataTypePreferences))).thenThrow(exception); doThrow(new TokenRefreshException("failed")).when(tokenRefresher).refreshOAuth2Token(); task.doInBackground(config); verify(tokenRefresher, times(1)).refreshOAuth2Token(); verify(service).transition(SmsSyncState.ERROR, exception); // make sure locks only get acquired+released once verify(service).acquireLocks(); verify(service).releaseLocks(); }
@Test public void shouldHandleAuthErrorAndTokenCouldBeRefreshed() throws Exception { mockFetch(SMS, 1); when(converter.convertMessages(any(Cursor.class), notNull(DataType.class))).thenReturn(result(SMS, 1)); XOAuth2AuthenticationFailedException exception = mock(XOAuth2AuthenticationFailedException.class); when(exception.getStatus()).thenReturn(400); when(store.getFolder(notNull(DataType.class), same(dataTypePreferences))).thenThrow(exception); when(service.getBackupImapStore()).thenReturn(store); task.doInBackground(config); verify(tokenRefresher).refreshOAuth2Token(); verify(service, times(2)).transition(SmsSyncState.LOGIN, null); verify(service, times(2)).transition(SmsSyncState.CALC, null); verify(service).transition(SmsSyncState.ERROR, exception); // make sure locks only get acquired+released once verify(service).acquireLocks(); verify(service).releaseLocks(); }
@Test public void shouldInvalidateTokenOnRefresh() throws Exception { when(authPreferences.getOauth2Token()).thenReturn("token"); when(authPreferences.getOauth2Username()).thenReturn("username"); when(accountManager.getAuthToken(notNull(Account.class), anyString(), isNull(Bundle.class), anyBoolean(), any(AccountManagerCallback.class), any(Handler.class))).thenReturn(mock(AccountManagerFuture.class)); try { refresher.refreshOAuth2Token(); fail("expected error "); } catch (TokenRefreshException e) { assertThat(e.getMessage()).isEqualTo("no bundle received from accountmanager"); } verify(accountManager).invalidateAuthToken(GOOGLE_TYPE, "token"); }
@Test public void shouldHandleExceptionsThrownByFuture() throws Exception { when(authPreferences.getOauth2Token()).thenReturn("token"); when(authPreferences.getOauth2Username()).thenReturn("username"); AccountManagerFuture<Bundle> future = mock(AccountManagerFuture.class); when(accountManager.getAuthToken(notNull(Account.class), anyString(), isNull(Bundle.class), anyBoolean(), any(AccountManagerCallback.class), any(Handler.class))).thenReturn(future); AuthenticatorException exception = new AuthenticatorException(); when(future.getResult()).thenThrow(exception); try { refresher.refreshOAuth2Token(); fail("expected exception"); } catch (TokenRefreshException e) { assertThat(e.getCause()).isSameAs(exception); } verify(accountManager).invalidateAuthToken(GOOGLE_TYPE, "token"); }
private BackupState handleAuthError(BackupConfig config, XOAuth2AuthenticationFailedException e) { if (e.getStatus() == 400) { appLogDebug("need to perform xoauth2 token refresh"); if (config.currentTry < 1) { try { tokenRefresher.refreshOAuth2Token(); // we got a new token, let's handleAuthError one more time - we need to pass in a new store object // since the auth params on it are immutable appLogDebug("token refreshed, retrying"); return fetchAndBackupItems(config.retryWithStore(service.getBackupImapStore())); } catch (MessagingException ignored) { Log.w(TAG, ignored); } catch (TokenRefreshException refreshException) { appLogDebug("error refreshing token: "+refreshException+", cause="+refreshException.getCause()); } } else { appLogDebug("no new token obtained, giving up"); } } else { appLogDebug("unexpected xoauth status code " + e.getStatus()); } return transition(ERROR, e); }