From 23c909b2017dd49b2162457d91a4d00a8c8aa73d Mon Sep 17 00:00:00 2001 From: DenBond7 Date: Fri, 14 Aug 2020 17:54:06 +0300 Subject: [PATCH] Added the token encryption when we store an access token to AccountManager. Fixed a bug of the message sending.| #716 --- .../accounts/FlowcryptAccountAuthenticator.kt | 15 ++++++++++++--- .../api/email/protocol/OpenStoreHelper.kt | 8 +++++++- .../api/email/protocol/SmtpProtocolUtil.kt | 19 ++++++++++++++++++- .../OAuth2AuthCredentialsViewModel.kt | 3 ++- 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/accounts/FlowcryptAccountAuthenticator.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/accounts/FlowcryptAccountAuthenticator.kt index 777ed401a5..4dff4094bf 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/accounts/FlowcryptAccountAuthenticator.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/accounts/FlowcryptAccountAuthenticator.kt @@ -16,6 +16,7 @@ import com.flowcrypt.email.BuildConfig import com.flowcrypt.email.api.oauth.OAuth2Helper import com.flowcrypt.email.api.retrofit.ApiHelper import com.flowcrypt.email.api.retrofit.ApiService +import com.flowcrypt.email.security.KeyStoreCryptoManager import com.flowcrypt.email.ui.activity.SignInActivity @@ -58,13 +59,21 @@ class FlowcryptAccountAuthenticator(val context: Context) : AbstractAccountAuthe var authToken = accountManager.peekAuthToken(account, authTokenType) if (authToken.isNullOrEmpty()) { - val refreshToken = accountManager.getUserData(account, KEY_REFRESH_TOKEN) + val encryptedRefreshToken = accountManager.getUserData(account, KEY_REFRESH_TOKEN) + if (encryptedRefreshToken.isNullOrEmpty()) { + return Bundle().apply { + putInt(AccountManager.KEY_ERROR_CODE, AccountManager.ERROR_CODE_BAD_ARGUMENTS) + putString(AccountManager.KEY_ERROR_MESSAGE, "Refresh token is wrong or was corrupted!") + } + } + val refreshToken = KeyStoreCryptoManager.decrypt(encryptedRefreshToken) val apiService = ApiHelper.getInstance(context).retrofit.create(ApiService::class.java) val apiResponse = apiService.refreshMicrosoftOAuth2Token(refreshToken).execute() if (apiResponse.isSuccessful) { val tokenResponse = apiResponse.body() - authToken = tokenResponse?.accessToken - accountManager.setUserData(account, KEY_REFRESH_TOKEN, tokenResponse?.refreshToken) + authToken = KeyStoreCryptoManager.encrypt(tokenResponse?.accessToken) + accountManager.setAuthToken(account, authTokenType, authToken) + accountManager.setUserData(account, KEY_REFRESH_TOKEN, KeyStoreCryptoManager.encrypt(tokenResponse?.refreshToken)) accountManager.setUserData(account, KEY_EXPIRES_AT, OAuth2Helper.getExpiresAtTime(tokenResponse?.expiresIn).toString()) } else return Bundle().apply { putInt(AccountManager.KEY_ERROR_CODE, AccountManager.ERROR_CODE_BAD_AUTHENTICATION) diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/email/protocol/OpenStoreHelper.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/email/protocol/OpenStoreHelper.kt index af89736af4..12d0108f2a 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/email/protocol/OpenStoreHelper.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/email/protocol/OpenStoreHelper.kt @@ -13,6 +13,7 @@ import com.flowcrypt.email.api.email.JavaEmailConstants import com.flowcrypt.email.api.email.gmail.GmailConstants import com.flowcrypt.email.api.email.model.SecurityType import com.flowcrypt.email.database.entity.AccountEntity +import com.flowcrypt.email.security.KeyStoreCryptoManager import com.flowcrypt.email.util.LogsUtil import com.google.android.gms.auth.GoogleAuthUtil import com.sun.mail.gimap.GmailSSLStore @@ -151,8 +152,13 @@ class OpenStoreHelper { val accountManager = AccountManager.get(context) val oauthAccount = accountManager.accounts.firstOrNull { it.name == account.email } if (oauthAccount != null) { - accountManager.blockingGetAuthToken(oauthAccount, + val encryptedToken = accountManager.blockingGetAuthToken(oauthAccount, FlowcryptAccountAuthenticator.AUTH_TOKEN_TYPE_EMAIL, true) + if (encryptedToken.isNullOrEmpty()) { + ""//need to think about + } else { + KeyStoreCryptoManager.decrypt(encryptedToken) + } } else { account.password } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/email/protocol/SmtpProtocolUtil.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/email/protocol/SmtpProtocolUtil.kt index ea47098b62..169fd8dd66 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/email/protocol/SmtpProtocolUtil.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/email/protocol/SmtpProtocolUtil.kt @@ -5,11 +5,14 @@ package com.flowcrypt.email.api.email.protocol +import android.accounts.AccountManager import android.content.Context +import com.flowcrypt.email.accounts.FlowcryptAccountAuthenticator import com.flowcrypt.email.api.email.EmailUtil import com.flowcrypt.email.api.email.JavaEmailConstants import com.flowcrypt.email.api.email.gmail.GmailConstants import com.flowcrypt.email.database.entity.AccountEntity +import com.flowcrypt.email.security.KeyStoreCryptoManager import com.google.android.gms.auth.GoogleAuthException import java.io.IOException import javax.mail.MessagingException @@ -50,7 +53,7 @@ class SmtpProtocolUtil { else -> { val userName: String? - val password: String? + var password: String? if (accountEntity.useCustomSignForSmtp == true) { userName = accountEntity.smtpUsername @@ -60,6 +63,20 @@ class SmtpProtocolUtil { password = accountEntity.password } + if (accountEntity.useOAuth2) { + val accountManager = AccountManager.get(context) + val oAuthAccount = accountManager.accounts.firstOrNull { it.name == accountEntity.email } + if (oAuthAccount != null) { + val encryptedToken = accountManager.blockingGetAuthToken(oAuthAccount, + FlowcryptAccountAuthenticator.AUTH_TOKEN_TYPE_EMAIL, true) + password = if (encryptedToken.isNullOrEmpty()) { + ""//need to think about + } else { + KeyStoreCryptoManager.decrypt(encryptedToken) + } + } + } + transport.connect(accountEntity.smtpServer, accountEntity.smtpPort ?: 0, userName, password) } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/OAuth2AuthCredentialsViewModel.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/OAuth2AuthCredentialsViewModel.kt index 735d3b7267..9c4a7ecc20 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/OAuth2AuthCredentialsViewModel.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/OAuth2AuthCredentialsViewModel.kt @@ -15,6 +15,7 @@ import com.flowcrypt.email.api.oauth.OAuth2Helper import com.flowcrypt.email.api.retrofit.ApiRepository import com.flowcrypt.email.api.retrofit.FlowcryptApiRepository import com.flowcrypt.email.api.retrofit.response.base.Result +import com.flowcrypt.email.security.KeyStoreCryptoManager import com.flowcrypt.email.util.exception.ApiException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -123,7 +124,7 @@ class OAuth2AuthCredentialsViewModel(application: Application) : BaseAndroidView email = email, accessToken = accessToken, expiresAt = OAuth2Helper.getExpiresAtTime(response.data.expiresIn), - refreshToken = response.data.refreshToken + refreshToken = KeyStoreCryptoManager.encryptSuspend(response.data.refreshToken) ) )?.copy(password = "", smtpSignInPassword = null) ?: throw NullPointerException("Couldn't find default settings for $email!")