Skip to content

Commit f4ad3a2

Browse files
committed
Added a temp realization of authenticator.| #716
1 parent eaddd70 commit f4ad3a2

File tree

7 files changed

+196
-2
lines changed

7 files changed

+196
-2
lines changed

FlowCrypt/src/main/AndroidManifest.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,17 @@
295295
android:exported="false"
296296
android:permission="android.permission.BIND_JOB_SERVICE" />
297297

298+
<service
299+
android:name=".accounts.FlowcryptAuthenticatorService"
300+
android:exported="false">
301+
<intent-filter>
302+
<action android:name="android.accounts.AccountAuthenticator" />
303+
</intent-filter>
304+
<meta-data
305+
android:name="android.accounts.AccountAuthenticator"
306+
android:resource="@xml/authenticator" />
307+
</service>
308+
298309
<receiver android:name=".broadcastreceivers.MarkMessagesAsOldBroadcastReceiver" />
299310

300311
<receiver android:name=".broadcastreceivers.CorruptedStorageBroadcastReceiver" />
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* © 2016-present FlowCrypt a.s. Limitations apply. Contact [email protected]
3+
* Contributors: DenBond7
4+
*/
5+
6+
package com.flowcrypt.email.accounts
7+
8+
import android.accounts.AbstractAccountAuthenticator
9+
import android.accounts.Account
10+
import android.accounts.AccountAuthenticatorResponse
11+
import android.accounts.AccountManager
12+
import android.content.Context
13+
import android.content.Intent
14+
import android.os.Bundle
15+
import android.text.TextUtils
16+
import com.flowcrypt.email.BuildConfig
17+
import com.flowcrypt.email.ui.activity.SignInActivity
18+
19+
20+
/**
21+
* @author Denis Bondarenko
22+
* Date: 8/12/20
23+
* Time: 4:14 PM
24+
25+
*/
26+
class FlowcryptAccountAuthenticator(val context: Context) : AbstractAccountAuthenticator(context) {
27+
override fun getAuthTokenLabel(authTokenType: String?): String {
28+
return ""
29+
}
30+
31+
override fun confirmCredentials(response: AccountAuthenticatorResponse?, account: Account?, options: Bundle?): Bundle {
32+
return Bundle()
33+
}
34+
35+
override fun updateCredentials(response: AccountAuthenticatorResponse?, account: Account?, authTokenType: String?, options: Bundle?): Bundle {
36+
return Bundle()
37+
}
38+
39+
override fun getAuthToken(response: AccountAuthenticatorResponse?, account: Account?, authTokenType: String?, options: Bundle?): Bundle {
40+
// Extract the username and password from the Account Manager, and ask
41+
// the server for an appropriate AuthToken.
42+
// Extract the username and password from the Account Manager, and ask
43+
// the server for an appropriate AuthToken.
44+
val accountManager = AccountManager.get(context)
45+
46+
var authToken = accountManager.peekAuthToken(account, authTokenType)
47+
48+
// Lets give another try to authenticate the user
49+
50+
// Lets give another try to authenticate the user
51+
if (TextUtils.isEmpty(authToken)) {
52+
val password = accountManager.getPassword(account)
53+
if (password != null) {
54+
authToken = "some token"//AuthTokenLoader.signIn(mContext, account.name, password);
55+
}
56+
}
57+
58+
// If we get an authToken - we return it
59+
60+
// If we get an authToken - we return it
61+
if (!TextUtils.isEmpty(authToken)) {
62+
val result = Bundle()
63+
result.putString(AccountManager.KEY_ACCOUNT_NAME, account!!.name)
64+
result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type)
65+
result.putString(AccountManager.KEY_AUTHTOKEN, authToken)
66+
return result
67+
}
68+
69+
// If we get here, then we couldn't access the user's password - so we
70+
// need to re-prompt them for their credentials. We do that by creating
71+
// an intent to display our AuthenticatorActivity.
72+
73+
// If we get here, then we couldn't access the user's password - so we
74+
// need to re-prompt them for their credentials. We do that by creating
75+
// an intent to display our AuthenticatorActivity.
76+
val intent = Intent(context, SignInActivity::class.java)
77+
//intent.putExtra(FlowcryptAuthenticatorActivity.ARG_ACCOUNT_TYPE, attr.accountType)
78+
//intent.putExtra(FlowcryptAuthenticatorActivity.ARG_AUTH_TYPE, authTokenType)
79+
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response)
80+
val bundle = Bundle()
81+
bundle.putParcelable(AccountManager.KEY_INTENT, intent)
82+
return bundle
83+
}
84+
85+
override fun hasFeatures(response: AccountAuthenticatorResponse?, account: Account?, features: Array<out String>?): Bundle {
86+
return Bundle()
87+
}
88+
89+
override fun editProperties(response: AccountAuthenticatorResponse?, accountType: String?): Bundle {
90+
return Bundle()
91+
}
92+
93+
override fun addAccount(response: AccountAuthenticatorResponse?, accountType: String?, authTokenType: String?, requiredFeatures: Array<out String>?, options: Bundle?): Bundle {
94+
val intent = Intent(context, SignInActivity::class.java)
95+
//intent.putExtra(FlowcryptAuthenticatorActivity.ARG_ACCOUNT_TYPE, attr.accountType)
96+
//intent.putExtra(FlowcryptAuthenticatorActivity.ARG_AUTH_TYPE, authTokenType)
97+
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response)
98+
val bundle = Bundle()
99+
bundle.putParcelable(AccountManager.KEY_INTENT, intent)
100+
return bundle
101+
}
102+
103+
companion object {
104+
val ACCOUNT_TYPE = BuildConfig.APPLICATION_ID
105+
val AUTH_TOKEN_TYPE_EMAIL = "email"
106+
}
107+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* © 2016-present FlowCrypt a.s. Limitations apply. Contact [email protected]
3+
* Contributors: DenBond7
4+
*/
5+
6+
package com.flowcrypt.email.accounts
7+
8+
import android.app.Service
9+
import android.content.Intent
10+
import android.os.IBinder
11+
12+
/**
13+
* @author Denis Bondarenko
14+
* Date: 8/12/20
15+
* Time: 5:03 PM
16+
17+
*/
18+
class FlowcryptAuthenticatorService : Service() {
19+
private lateinit var authenticator: FlowcryptAccountAuthenticator
20+
21+
override fun onCreate() {
22+
super.onCreate()
23+
authenticator = FlowcryptAccountAuthenticator(applicationContext)
24+
}
25+
26+
override fun onBind(intent: Intent?): IBinder? {
27+
return authenticator.iBinder
28+
}
29+
}

FlowCrypt/src/main/java/com/flowcrypt/email/api/email/protocol/OpenStoreHelper.kt

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55

66
package com.flowcrypt.email.api.email.protocol
77

8+
import android.accounts.AccountManager
89
import android.content.Context
10+
import com.flowcrypt.email.accounts.FlowcryptAccountAuthenticator
911
import com.flowcrypt.email.api.email.EmailUtil
1012
import com.flowcrypt.email.api.email.JavaEmailConstants
1113
import com.flowcrypt.email.api.email.gmail.GmailConstants
@@ -145,7 +147,20 @@ class OpenStoreHelper {
145147
else -> session.getStore(JavaEmailConstants.PROTOCOL_IMAPS)
146148
}
147149

148-
store.connect(account.imapServer, account.username, account.password)
150+
val password = if (account.useOAuth2) {
151+
val accountManager = AccountManager.get(context)
152+
val oauthAccount = accountManager.accounts.firstOrNull { it.name == account.email }
153+
if (oauthAccount != null) {
154+
accountManager.blockingGetAuthToken(oauthAccount,
155+
FlowcryptAccountAuthenticator.AUTH_TOKEN_TYPE_EMAIL, true)
156+
} else {
157+
account.password
158+
}
159+
} else {
160+
account.password
161+
}
162+
163+
store.connect(account.imapServer, account.username, password)
149164
store
150165
}
151166
}

FlowCrypt/src/main/java/com/flowcrypt/email/database/entity/AccountEntity.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ data class AccountEntity constructor(
6767
val account: Account? = Account(this.email, accountType
6868
?: this.email.substring(this.email.indexOf('@') + 1).toLowerCase(Locale.US))
6969

70+
val useOAuth2: Boolean
71+
get() = JavaEmailConstants.AUTH_MECHANISMS_XOAUTH2 == imapAuthMechanisms
72+
7073
constructor(googleSignInAccount: GoogleSignInAccount, uuid: String? = null,
7174
domainRules: List<String>? = null) :
7275
this(

FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/AddOtherAccountFragment.kt

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
package com.flowcrypt.email.ui.activity.fragment
77

8+
import android.accounts.Account
9+
import android.accounts.AccountManager
810
import android.app.Activity
911
import android.app.PendingIntent
1012
import android.content.Intent
@@ -29,6 +31,7 @@ import androidx.lifecycle.lifecycleScope
2931
import androidx.preference.PreferenceManager
3032
import com.flowcrypt.email.Constants
3133
import com.flowcrypt.email.R
34+
import com.flowcrypt.email.accounts.FlowcryptAccountAuthenticator
3235
import com.flowcrypt.email.api.email.EmailProviderSettingsHelper
3336
import com.flowcrypt.email.api.email.JavaEmailConstants
3437
import com.flowcrypt.email.api.email.gmail.GmailConstants
@@ -71,8 +74,10 @@ import net.openid.appauth.AuthorizationRequest
7174
import net.openid.appauth.AuthorizationResponse
7275
import net.openid.appauth.AuthorizationService
7376
import java.net.SocketTimeoutException
77+
import java.util.*
7478
import java.util.regex.Pattern
7579
import javax.mail.AuthenticationFailedException
80+
import kotlin.collections.ArrayList
7681

7782
/**
7883
* @author Denis Bondarenko
@@ -219,9 +224,23 @@ class AddOtherAccountFragment : BaseSingInFragment(), ProgressBehaviour,
219224

220225
override fun runEmailManagerActivity() {
221226
lifecycleScope.launch {
222-
val accountEntity = AccountEntity(generateAuthCreds())
227+
val authCreds = generateAuthCreds()
228+
val accountEntity = AccountEntity(
229+
if (authCreds.useOAuth2) {
230+
authCreds.copy(password = "", smtpSignInPassword = null)
231+
} else {
232+
authCreds
233+
})
223234
val roomDatabase = FlowCryptRoomDatabase.getDatabase(requireContext())
224235
roomDatabase.accountDao().addAccountSuspend(accountEntity)
236+
237+
if (authCreds.useOAuth2) {
238+
val accountManager = AccountManager.get(requireContext())
239+
val account = Account(accountEntity.email.toLowerCase(Locale.US), FlowcryptAccountAuthenticator.ACCOUNT_TYPE)
240+
accountManager.addAccountExplicitly(account, null, null)
241+
accountManager.setAuthToken(account, FlowcryptAccountAuthenticator.AUTH_TOKEN_TYPE_EMAIL, authCreds.password)
242+
}
243+
225244
EmailSyncService.startEmailSyncService(requireContext())
226245

227246
val addedAccount = roomDatabase.accountDao().getAccountSuspend(accountEntity.email)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?xml version="1.0" encoding="utf-8"?><!--
2+
~ © 2016-present FlowCrypt a.s. Limitations apply. Contact [email protected]
3+
~ Contributors: DenBond7
4+
-->
5+
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
6+
android:accountType="@string/application_id"
7+
android:customTokens="true"
8+
android:icon="@mipmap/ic_launcher"
9+
android:label="@string/app_name"
10+
android:smallIcon="@mipmap/ic_launcher" />

0 commit comments

Comments
 (0)