public boolean hasOAuth2Tokens() { return getOauth2Username() != null && getOauth2Token() != null; }
/** * TODO: this should probably be handled in K9 * * <p> * The SASL XOAUTH2 initial client response has the following format: * </p> * <code>base64("user="{User}"^Aauth=Bearer "{Access Token}"^A^A")</code> * <p> * For example, before base64-encoding, the initial client response might look like this: * </p> * <code>user=someuser@example.com^Aauth=Bearer vF9dft4qmTc2Nvb3RlckBhdHRhdmlzdGEuY29tCg==^A^A</code> * <p/> * <em>Note:</em> ^A represents a Control+A (\001). * * @see <a href="https://developers.google.com/google-apps/gmail/xoauth2_protocol#the_sasl_xoauth2_mechanism"> * The SASL XOAUTH2 Mechanism</a> */ private @NonNull String generateXOAuth2Token() { final String username = getOauth2Username(); final String token = getOauth2Token(); final String formatted = "user=" + username + "\001auth=Bearer " + token + "\001\001"; try { return Base64.encodeToString(formatted.getBytes(UTF_8), NO_WRAP); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } }
public String getUserEmail() { switch (getAuthMode()) { case XOAUTH: return getOauth2Username(); default: return getImapUsername(); } }
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); } }
@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); }
@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"); } }
private String getConnectedSummary(TwoStatePreference connected) { final String username = authPreferences.getOauth2Username(); if (connected.isEnabled()) { return connected.isChecked() && !TextUtils.isEmpty(username) ? getString(R.string.gmail_already_connected, username) : getString(R.string.gmail_needs_connecting); } else if (authPreferences.isLoginInformationSet()) { return getString(R.string.custom_imap, authPreferences.getImapUsername() + "@" + authPreferences.getServername()); } else { return getString(R.string.custom_imap_not_configured); } }
@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"); }
public String getStoreUri() { if (useXOAuth()) { if (hasOAuth2Tokens()) { return formatUri( AuthType.XOAUTH2, DEFAULT_SERVER_PROTOCOL, getOauth2Username(), generateXOAuth2Token(), DEFAULT_SERVER_ADDRESS); } else { Log.w(TAG, "No valid xoauth2 tokens"); return null; } } else { return formatUri(AuthType.PLAIN, getServerProtocol(), getImapUsername(), getImapPassword(), getServerAddress()); } }