From 0d97fc51a347a45d57d99508806c5def11978094 Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Fri, 21 Jul 2023 11:49:48 +0600 Subject: [PATCH 1/5] Add support to pass userNameHint on openId login flow --- .gitlab-ci.yml | 3 + app/build.gradle | 7 ++- app/src/main/AndroidManifest.xml | 1 + .../authorization/IdentityProvider.java | 11 ++++ .../davdroid/syncadapter/AccountUtils.kt | 1 + .../DefaultAccountAuthenticatorService.kt | 5 ++ .../ui/setup/AccountDetailsFragment.kt | 31 ++++++++--- .../ui/setup/DetectConfigurationFragment.kt | 2 +- .../ui/setup/EeloAuthenticatorFragment.kt | 17 +++++- .../davdroid/ui/setup/LoginActivity.kt | 2 + .../ui/setup/MurenaLoginFragmentFactory.kt | 11 +++- .../ui/setup/MurenaOpenIdAuthFragment.kt | 55 +++++++++++++++++++ .../ui/setup/OpenIdAuthenticationViewModel.kt | 18 +++++- .../layout/fragment_eelo_authenticator.xml | 2 + 14 files changed, 150 insertions(+), 16 deletions(-) create mode 100644 app/src/main/java/at/bitfire/davdroid/ui/setup/MurenaOpenIdAuthFragment.kt diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7a3601b0e..f9934458f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -6,6 +6,9 @@ stages: before_script: - echo email.key=$PEPPER >> local.properties + - echo MURENA_CLIENT_ID=$MURENA_CLIENT_ID >> local.properties + - echo MURENA_CLIENT_SECRET=$MURENA_CLIENT_SECRET >> local.properties + - echo MURENA_REDIRECT_URI=$MURENA_REDIRECT_URI >> local.properties - echo GOOGLE_CLIENT_ID=$GOOGLE_CLIENT_ID >> local.properties - echo GOOGLE_REDIRECT_URI=$GOOGLE_REDIRECT_URI >> local.properties - echo YAHOO_CLIENT_ID=$YAHOO_CLIENT_ID >> local.properties diff --git a/app/build.gradle b/app/build.gradle index 1a900b11a..6418c44c0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -108,6 +108,10 @@ android { } defaultConfig { + buildConfigField "String", "MURENA_CLIENT_ID", "\"${retrieveKey("MURENA_CLIENT_ID")}\"" + buildConfigField "String", "MURENA_CLIENT_SECRET", "\"${retrieveKey("MURENA_CLIENT_SECRET")}\"" + buildConfigField "String", "MURENA_REDIRECT_URI", "\"${retrieveKey("MURENA_REDIRECT_URI")}\"" + buildConfigField "String", "GOOGLE_CLIENT_ID", "\"${retrieveKey("GOOGLE_CLIENT_ID")}\"" buildConfigField "String", "GOOGLE_REDIRECT_URI", "\"${retrieveKey("GOOGLE_REDIRECT_URI")}\"" @@ -115,7 +119,8 @@ android { manifestPlaceholders = [ 'appAuthRedirectScheme': applicationId, - "googleAuthRedirectScheme": retrieveKey("GOOGLE_REDIRECT_URI") + "googleAuthRedirectScheme": retrieveKey("GOOGLE_REDIRECT_URI"), + "murenaAuthRedirectScheme": retrieveKey("MURENA_REDIRECT_URI") ] } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fd66593b2..24a70afbf 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -675,6 +675,7 @@ + diff --git a/app/src/main/java/at/bitfire/davdroid/authorization/IdentityProvider.java b/app/src/main/java/at/bitfire/davdroid/authorization/IdentityProvider.java index 3e25ddd2d..c4bd3d78d 100644 --- a/app/src/main/java/at/bitfire/davdroid/authorization/IdentityProvider.java +++ b/app/src/main/java/at/bitfire/davdroid/authorization/IdentityProvider.java @@ -33,6 +33,17 @@ import at.bitfire.davdroid.BuildConfig; */ public class IdentityProvider { + public static final IdentityProvider MURENA = new IdentityProvider( + "https://accounts.eeo.one/auth/realms/eeo.one/.well-known/openid-configuration", + null, + null, + BuildConfig.MURENA_CLIENT_ID, + BuildConfig.MURENA_CLIENT_SECRET, + BuildConfig.MURENA_REDIRECT_URI + ":/redirect", + "openid address profile email phone roles offline_access web-origins microprofile-jwt", + null + ); + public static final IdentityProvider GOOGLE = new IdentityProvider( "https://accounts.google.com/.well-known/openid-configuration", null, diff --git a/app/src/main/java/at/bitfire/davdroid/syncadapter/AccountUtils.kt b/app/src/main/java/at/bitfire/davdroid/syncadapter/AccountUtils.kt index cbe2ba8eb..22ebaf529 100644 --- a/app/src/main/java/at/bitfire/davdroid/syncadapter/AccountUtils.kt +++ b/app/src/main/java/at/bitfire/davdroid/syncadapter/AccountUtils.kt @@ -111,6 +111,7 @@ object AccountUtils { fun getOpenIdMainAccountTypes(context: Context) = listOf( + context.getString(R.string.eelo_account_type), context.getString(R.string.google_account_type), context.getString(R.string.yahoo_account_type) ) diff --git a/app/src/main/java/at/bitfire/davdroid/syncadapter/DefaultAccountAuthenticatorService.kt b/app/src/main/java/at/bitfire/davdroid/syncadapter/DefaultAccountAuthenticatorService.kt index e31e04345..100b18bfd 100644 --- a/app/src/main/java/at/bitfire/davdroid/syncadapter/DefaultAccountAuthenticatorService.kt +++ b/app/src/main/java/at/bitfire/davdroid/syncadapter/DefaultAccountAuthenticatorService.kt @@ -143,6 +143,11 @@ abstract class DefaultAccountAuthenticatorService : Service(), OnAccountsUpdateL LoginActivity.OPEN_APP_ACTIVITY_AFTER_AUTH, it.getString(LoginActivity.OPEN_APP_ACTIVITY_AFTER_AUTH) ) + + intent.putExtra( + LoginActivity.USERNAME_HINT, + it.getString(LoginActivity.USERNAME_HINT) + ) } val bundle = Bundle(1) diff --git a/app/src/main/java/at/bitfire/davdroid/ui/setup/AccountDetailsFragment.kt b/app/src/main/java/at/bitfire/davdroid/ui/setup/AccountDetailsFragment.kt index 747b0310c..343ae97ef 100644 --- a/app/src/main/java/at/bitfire/davdroid/ui/setup/AccountDetailsFragment.kt +++ b/app/src/main/java/at/bitfire/davdroid/ui/setup/AccountDetailsFragment.kt @@ -279,14 +279,8 @@ class AccountDetailsFragment : Fragment() { val accountManager = AccountManager.get(context) if (!AccountUtils.createAccount(context, account, userData, credentials?.password)) { - if (accountType in AccountUtils.getOpenIdMainAccountTypes(context)) { - for (openIdAccount in AccountUtils.getOpenIdMainAccounts(context)) { - if (userData.get(AccountSettings.KEY_EMAIL_ADDRESS) == accountManager - .getUserData(account, AccountSettings.KEY_EMAIL_ADDRESS)) { - accountManager.setUserData(openIdAccount, AccountSettings.KEY_AUTH_STATE, - userData.getString(AccountSettings.KEY_AUTH_STATE)) - } - } + if (accountType in AccountUtils.getOpenIdMainAccountTypes(context) && credentials?.authState != null) { + updateAuthState(userData, accountManager, account) } else { result.postValue(false) return@launch @@ -383,6 +377,27 @@ class AccountDetailsFragment : Fragment() { return result } + private fun updateAuthState( + userData: Bundle, + accountManager: AccountManager, + account: Account + ) { + for (openIdAccount in AccountUtils.getOpenIdMainAccounts(context)) { + if (userData.get(AccountSettings.KEY_EMAIL_ADDRESS) == accountManager + .getUserData(account, AccountSettings.KEY_EMAIL_ADDRESS) + ) { + accountManager.setUserData( + openIdAccount, AccountSettings.KEY_AUTH_STATE, + userData.getString(AccountSettings.KEY_AUTH_STATE) + ) + accountManager.setUserData( + openIdAccount, AccountSettings.KEY_CLIENT_SECRET, + userData.getString(AccountSettings.KEY_CLIENT_SECRET) + ) + } + } + } + private fun insertService( accountName: String, authState: String?, diff --git a/app/src/main/java/at/bitfire/davdroid/ui/setup/DetectConfigurationFragment.kt b/app/src/main/java/at/bitfire/davdroid/ui/setup/DetectConfigurationFragment.kt index c5286e67c..5d1d208f1 100644 --- a/app/src/main/java/at/bitfire/davdroid/ui/setup/DetectConfigurationFragment.kt +++ b/app/src/main/java/at/bitfire/davdroid/ui/setup/DetectConfigurationFragment.kt @@ -51,7 +51,7 @@ class DetectConfigurationFragment: Fragment() { val baseURI = loginModel.baseURI ?: return - model.detectConfiguration(baseURI, loginModel.credentials, loginModel.cardDavURI, isMurenaAccountType).observe(this) { result -> + model.detectConfiguration(baseURI, loginModel.credentials, loginModel.cardDavURI, false).observe(this) { result -> // save result for next step loginModel.configuration = result diff --git a/app/src/main/java/at/bitfire/davdroid/ui/setup/EeloAuthenticatorFragment.kt b/app/src/main/java/at/bitfire/davdroid/ui/setup/EeloAuthenticatorFragment.kt index 50061c91b..533b2a5b2 100644 --- a/app/src/main/java/at/bitfire/davdroid/ui/setup/EeloAuthenticatorFragment.kt +++ b/app/src/main/java/at/bitfire/davdroid/ui/setup/EeloAuthenticatorFragment.kt @@ -55,6 +55,7 @@ class EeloAuthenticatorFragment : Fragment() { private lateinit var serverUrlEditTextLayout: TextInputLayout private lateinit var serverUrlEditText: TextInputEditText private lateinit var passwordEditText: TextInputEditText + private lateinit var passwordHolder: View private fun isNetworkAvailable(): Boolean { val connectivityManager = requireActivity().getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager @@ -79,6 +80,7 @@ class EeloAuthenticatorFragment : Fragment() { serverUrlEditTextLayout = v.root.findViewById(R.id.urlpwd_server_uri_layout) serverUrlEditText = v.root.findViewById(R.id.urlpwd_server_uri) passwordEditText = v.root.findViewById(R.id.urlpwd_password) + passwordHolder = v.root.findViewById(R.id.password_holder) serverToggleButton.setOnClickListener { expandCollapse() } @@ -196,14 +198,20 @@ class EeloAuthenticatorFragment : Fragment() { requireActivity().finish() } - if ((userIdEditText.text.toString() != "") && (passwordEditText.text.toString() != "")) { + if (!toggleButtonState && (userIdEditText.text.toString() != "")) { + requireActivity().intent.putExtra(LoginActivity.USERNAME_HINT, userIdEditText.text.toString()) + parentFragmentManager.beginTransaction() + .replace(android.R.id.content, MurenaOpenIdAuthFragment(), null) + .addToBackStack(null) + .commit() + } else if (toggleButtonState && (userIdEditText.text.toString() != "") && (passwordEditText.text.toString() != "")) { if (validate()) parentFragmentManager.beginTransaction() .replace(android.R.id.content, DetectConfigurationFragment(), null) .addToBackStack(null) .commit() } else { - Toast.makeText(context, "Please enter a valid username and password", Toast.LENGTH_LONG).show() + Toast.makeText(context, "Please enter a valid credentials", Toast.LENGTH_LONG).show() } } @@ -279,11 +287,16 @@ class EeloAuthenticatorFragment : Fragment() { serverUrlEditTextLayout.visibility = View.VISIBLE serverUrlEditText.isEnabled = true toggleButtonState = true + + passwordHolder.visibility = View.VISIBLE } else { serverToggleButton.setCompoundDrawablesWithIntrinsicBounds(null, null , ContextCompat.getDrawable(requireContext(), R.drawable.ic_expand_more), null) serverUrlEditTextLayout.visibility = View.GONE serverUrlEditText.isEnabled = false toggleButtonState = false + + passwordHolder.visibility = View.GONE + passwordEditText.setText("") } } diff --git a/app/src/main/java/at/bitfire/davdroid/ui/setup/LoginActivity.kt b/app/src/main/java/at/bitfire/davdroid/ui/setup/LoginActivity.kt index 8bbd99bf0..df981373c 100644 --- a/app/src/main/java/at/bitfire/davdroid/ui/setup/LoginActivity.kt +++ b/app/src/main/java/at/bitfire/davdroid/ui/setup/LoginActivity.kt @@ -38,6 +38,8 @@ class LoginActivity: AppCompatActivity() { */ const val EXTRA_PASSWORD = "password" + const val USERNAME_HINT = "userNameHint" + const val AUTH_STATE = "authState" const val ACCOUNT_TYPE = "account_type" const val OPENID_AUTH_FLOW_COMPLETE = "openId_authFlow_complete" diff --git a/app/src/main/java/at/bitfire/davdroid/ui/setup/MurenaLoginFragmentFactory.kt b/app/src/main/java/at/bitfire/davdroid/ui/setup/MurenaLoginFragmentFactory.kt index 3a2462e93..4bb15ba6f 100644 --- a/app/src/main/java/at/bitfire/davdroid/ui/setup/MurenaLoginFragmentFactory.kt +++ b/app/src/main/java/at/bitfire/davdroid/ui/setup/MurenaLoginFragmentFactory.kt @@ -35,12 +35,21 @@ class MurenaLoginFragmentFactory @Inject constructor(@ApplicationContext val con val accountType = intent.getStringExtra(LoginActivity.ACCOUNT_TYPE) ?: return null return when (accountType) { - context.getString(R.string.eelo_account_type) -> EeloAuthenticatorFragment() + context.getString(R.string.eelo_account_type) -> getMurenaFragment(intent) context.getString(R.string.google_account_type) -> GoogleAuthFragment() context.getString(R.string.yahoo_account_type) -> YahooAuthFragment() else -> null } } + + private fun getMurenaFragment(intent: Intent): Fragment { + val isAuthFlowComplete = intent.getBooleanExtra(LoginActivity.OPENID_AUTH_FLOW_COMPLETE, false) + + return when (isAuthFlowComplete) { + true -> MurenaOpenIdAuthFragment() + else -> EeloAuthenticatorFragment() + } + } } @Module diff --git a/app/src/main/java/at/bitfire/davdroid/ui/setup/MurenaOpenIdAuthFragment.kt b/app/src/main/java/at/bitfire/davdroid/ui/setup/MurenaOpenIdAuthFragment.kt new file mode 100644 index 000000000..361dcb770 --- /dev/null +++ b/app/src/main/java/at/bitfire/davdroid/ui/setup/MurenaOpenIdAuthFragment.kt @@ -0,0 +1,55 @@ +/* + * Copyright MURENA SAS 2023 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package at.bitfire.davdroid.ui.setup + +import android.os.Bundle +import android.view.View +import at.bitfire.davdroid.ECloudAccountHelper +import at.bitfire.davdroid.authorization.IdentityProvider +import org.json.JSONObject + +class MurenaOpenIdAuthFragment : OpenIdAuthenticationBaseFragment(IdentityProvider.MURENA) { + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + if (!isAuthFlowComplete() && ECloudAccountHelper.alreadyHasECloudAccount(requireContext())) { + ECloudAccountHelper.showMultipleECloudAccountNotAcceptedDialog(requireActivity()) + return + } + + startAuthFLow() + } + + override fun onAuthenticationComplete(userData: JSONObject) { + val userNameKey = "username" + + if (!userData.has(userNameKey)) { + handleLoginFailedToast() + return + } + + val userName = userData.getString(userNameKey) + if (userName.isBlank()) { + handleLoginFailedToast() + return + } + + //val baseUrl = "https://${Constants.EELO_SYNC_HOST}" + proceedNext(userName, "https://murenatest.io/remote.php/dav/files/$userName") + } +} diff --git a/app/src/main/java/at/bitfire/davdroid/ui/setup/OpenIdAuthenticationViewModel.kt b/app/src/main/java/at/bitfire/davdroid/ui/setup/OpenIdAuthenticationViewModel.kt index b5c23d460..0bdfef119 100644 --- a/app/src/main/java/at/bitfire/davdroid/ui/setup/OpenIdAuthenticationViewModel.kt +++ b/app/src/main/java/at/bitfire/davdroid/ui/setup/OpenIdAuthenticationViewModel.kt @@ -65,7 +65,8 @@ class OpenIdAuthenticationViewModel(application: Application) : AndroidViewModel } val authStateString = - intent.getStringExtra(LoginActivity.AUTH_STATE) ?: return OpenIdAuthStateSetupState.SET_UP_FAILED + intent.getStringExtra(LoginActivity.AUTH_STATE) + ?: return OpenIdAuthStateSetupState.SET_UP_FAILED authState = AuthState.jsonDeserialize(authStateString) @@ -76,15 +77,22 @@ class OpenIdAuthenticationViewModel(application: Application) : AndroidViewModel return OpenIdAuthStateSetupState.SET_UP_SUCCEED } - fun requestAuthCode(serviceConfiguration: AuthorizationServiceConfiguration, intent: Intent) { + fun requestAuthCode( + serviceConfiguration: AuthorizationServiceConfiguration, + intent: Intent + ) { authState = AuthState(serviceConfiguration) + val loginHint = intent.getStringExtra(LoginActivity.USERNAME_HINT) + val authRequest = AuthorizationRequest.Builder( serviceConfiguration, identityProvider!!.clientId, ResponseTypeValues.CODE, identityProvider!!.redirectUri - ).setScope(identityProvider!!.scope) + ) + .setScope(identityProvider!!.scope) + .setLoginHint(sanitizeHint(loginHint)) .build() authorizationService.performAuthorizationRequest( @@ -94,6 +102,10 @@ class OpenIdAuthenticationViewModel(application: Application) : AndroidViewModel ) } + private fun sanitizeHint(hint: String?): String? { + return if (hint.isNullOrBlank()) null else hint + } + private fun createPostAuthorizationIntent( request: AuthorizationRequest, providedIntent: Intent diff --git a/app/src/main/res/layout/fragment_eelo_authenticator.xml b/app/src/main/res/layout/fragment_eelo_authenticator.xml index 0321f345d..fb20b45e4 100644 --- a/app/src/main/res/layout/fragment_eelo_authenticator.xml +++ b/app/src/main/res/layout/fragment_eelo_authenticator.xml @@ -82,6 +82,7 @@ Date: Tue, 22 Aug 2023 19:03:14 +0600 Subject: [PATCH 2/5] open openId authentication flow in customTab Browser --- .../ui/setup/OpenIdAuthenticationViewModel.kt | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/at/bitfire/davdroid/ui/setup/OpenIdAuthenticationViewModel.kt b/app/src/main/java/at/bitfire/davdroid/ui/setup/OpenIdAuthenticationViewModel.kt index 0bdfef119..175872dc5 100644 --- a/app/src/main/java/at/bitfire/davdroid/ui/setup/OpenIdAuthenticationViewModel.kt +++ b/app/src/main/java/at/bitfire/davdroid/ui/setup/OpenIdAuthenticationViewModel.kt @@ -25,6 +25,7 @@ import androidx.lifecycle.AndroidViewModel import at.bitfire.davdroid.OpenIdUtils import at.bitfire.davdroid.authorization.IdentityProvider import at.bitfire.davdroid.log.Logger +import net.openid.appauth.AppAuthConfiguration import net.openid.appauth.AuthState import net.openid.appauth.AuthState.AuthStateAction import net.openid.appauth.AuthorizationException @@ -46,10 +47,20 @@ import java.util.logging.Level class OpenIdAuthenticationViewModel(application: Application) : AndroidViewModel(application) { - private val authorizationService: AuthorizationService = AuthorizationService(getApplication()) + private val authorizationService: AuthorizationService private var authState: AuthState? = null var identityProvider: IdentityProvider? = null + init { + val appAuthConfig = AppAuthConfiguration.Builder() + .setBrowserMatcher { + it.useCustomTab + } + .build() + + authorizationService = AuthorizationService(getApplication(), appAuthConfig) + } + override fun onCleared() { authorizationService.dispose() super.onCleared() -- GitLab From 639a6263ec36444f139ab6f8c7e35d5e1f5be2ac Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Mon, 28 Aug 2023 18:46:06 +0600 Subject: [PATCH 3/5] fix clientSecrect is missing issue --- .../at/bitfire/davdroid/network/HttpClient.kt | 18 ++++++++++++++---- .../DefaultAccountAuthenticatorService.kt | 5 +++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/at/bitfire/davdroid/network/HttpClient.kt b/app/src/main/java/at/bitfire/davdroid/network/HttpClient.kt index 4cd6b08e4..a43bdd0b2 100644 --- a/app/src/main/java/at/bitfire/davdroid/network/HttpClient.kt +++ b/app/src/main/java/at/bitfire/davdroid/network/HttpClient.kt @@ -156,10 +156,20 @@ class HttpClient private constructor( } // use account settings for authentication and cookies - if (accountSettings != null) - addAuthentication(null, accountSettings.credentials(), authStateCallback = { authState: AuthState -> - accountSettings.credentials(Credentials(authState = authState)) - }) + if (accountSettings != null) { + val cred = accountSettings.credentials() + addAuthentication( + null, + cred, + authStateCallback = { authState: AuthState -> + accountSettings.credentials( + Credentials( + authState = authState, + clientSecret = cred.clientSecret + ) + ) + }) + } } constructor(context: Context, host: String?, credentials: Credentials?) : this(context) { diff --git a/app/src/main/java/at/bitfire/davdroid/syncadapter/DefaultAccountAuthenticatorService.kt b/app/src/main/java/at/bitfire/davdroid/syncadapter/DefaultAccountAuthenticatorService.kt index 100b18bfd..cc19d2dfa 100644 --- a/app/src/main/java/at/bitfire/davdroid/syncadapter/DefaultAccountAuthenticatorService.kt +++ b/app/src/main/java/at/bitfire/davdroid/syncadapter/DefaultAccountAuthenticatorService.kt @@ -215,6 +215,11 @@ abstract class DefaultAccountAuthenticatorService : Service(), OnAccountsUpdateL AccountSettings.KEY_AUTH_STATE, authState.jsonSerializeString() ) + accountManager.setUserData( + account, + AccountSettings.KEY_CLIENT_SECRET, + clientSecretString + ) val result = Bundle() result.putString(AccountManager.KEY_ACCOUNT_NAME, account!!.name) result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type) -- GitLab From 16df29333cf18285df1a374810e84be8f7b845ab Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Tue, 29 Aug 2023 18:36:40 +0600 Subject: [PATCH 4/5] add flag to disable murena account openID feature --- .../ui/setup/DetectConfigurationFragment.kt | 6 +- .../ui/setup/EeloAuthenticatorFragment.kt | 57 ++++++++++++------- .../ui/setup/EeloAuthenticatorModel.kt | 14 ++--- .../ui/setup/MurenaOpenIdAuthFragment.kt | 3 +- .../layout/fragment_eelo_authenticator.xml | 1 + app/src/main/res/values/strings.xml | 1 + 6 files changed, 48 insertions(+), 34 deletions(-) diff --git a/app/src/main/java/at/bitfire/davdroid/ui/setup/DetectConfigurationFragment.kt b/app/src/main/java/at/bitfire/davdroid/ui/setup/DetectConfigurationFragment.kt index 5d1d208f1..92114462c 100644 --- a/app/src/main/java/at/bitfire/davdroid/ui/setup/DetectConfigurationFragment.kt +++ b/app/src/main/java/at/bitfire/davdroid/ui/setup/DetectConfigurationFragment.kt @@ -47,11 +47,11 @@ class DetectConfigurationFragment: Fragment() { return } - val isMurenaAccountType = (accountType == getString(R.string.eelo_account_type)) + val blockOnUnauthorizedException = (accountType == getString(R.string.eelo_account_type)) && !EeloAuthenticatorModel.enableOpenIdSupport val baseURI = loginModel.baseURI ?: return - model.detectConfiguration(baseURI, loginModel.credentials, loginModel.cardDavURI, false).observe(this) { result -> + model.detectConfiguration(baseURI, loginModel.credentials, loginModel.cardDavURI, blockOnUnauthorizedException).observe(this) { result -> // save result for next step loginModel.configuration = result @@ -97,7 +97,7 @@ class DetectConfigurationFragment: Fragment() { } - fun detectConfiguration(baseURI: URI, credentials: Credentials?, cardDavURI: URI?, blockOnUnauthorizedException: Boolean): LiveData { + fun detectConfiguration(baseURI: URI, credentials: Credentials?, cardDavURI: URI?, blockOnUnauthorizedException: Boolean = false): LiveData { synchronized(result) { if (detectionThread != null) // detection already running diff --git a/app/src/main/java/at/bitfire/davdroid/ui/setup/EeloAuthenticatorFragment.kt b/app/src/main/java/at/bitfire/davdroid/ui/setup/EeloAuthenticatorFragment.kt index 533b2a5b2..6d1ce19a7 100644 --- a/app/src/main/java/at/bitfire/davdroid/ui/setup/EeloAuthenticatorFragment.kt +++ b/app/src/main/java/at/bitfire/davdroid/ui/setup/EeloAuthenticatorFragment.kt @@ -27,6 +27,7 @@ import android.view.ViewGroup import android.widget.Button import android.widget.Toast import androidx.core.content.ContextCompat +import androidx.core.view.isVisible import androidx.core.widget.doOnTextChanged import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels @@ -65,11 +66,7 @@ class EeloAuthenticatorFragment : Fragment() { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { - - if (!isNetworkAvailable()) { - Toast.makeText(context, "Please check your internet connection", Toast.LENGTH_LONG).show() - requireActivity().finish() - } + handleNoNetworkAvailable() val v = FragmentEeloAuthenticatorBinding.inflate(inflater, container, false) v.lifecycleOwner = this @@ -82,11 +79,15 @@ class EeloAuthenticatorFragment : Fragment() { passwordEditText = v.root.findViewById(R.id.urlpwd_password) passwordHolder = v.root.findViewById(R.id.password_holder) + passwordHolder.isVisible = !EeloAuthenticatorModel.enableOpenIdSupport + serverToggleButton.setOnClickListener { expandCollapse() } v.root.findViewById(R.id.sign_in).setOnClickListener { login() } - v.root.findViewById(R.id.twofa_info_button).setOnClickListener { show2FAInfoDialog() } + val tfaButton = v.root.findViewById(R.id.twofa_info_button) + tfaButton.setOnClickListener { show2FAInfoDialog() } + tfaButton.isVisible = !EeloAuthenticatorModel.enableOpenIdSupport userIdEditText.doOnTextChanged { text, _, _, _ -> val domain = computeDomain(text) @@ -192,30 +193,38 @@ class EeloAuthenticatorFragment : Fragment() { return domain } - private fun login() { - if (!isNetworkAvailable()) { - Toast.makeText(context, "Please check your internet connection", Toast.LENGTH_LONG).show() - requireActivity().finish() + private fun handleNoNetworkAvailable() { + if (isNetworkAvailable()) { + return } - if (!toggleButtonState && (userIdEditText.text.toString() != "")) { + Toast.makeText(context, R.string.no_internet_toast, Toast.LENGTH_LONG).show() + requireActivity().finish() + } + + private fun login() { + handleNoNetworkAvailable() + + val handleOpenIdAuth = EeloAuthenticatorModel.enableOpenIdSupport && !toggleButtonState + + if (handleOpenIdAuth && (userIdEditText.text.toString() != "")) { requireActivity().intent.putExtra(LoginActivity.USERNAME_HINT, userIdEditText.text.toString()) - parentFragmentManager.beginTransaction() - .replace(android.R.id.content, MurenaOpenIdAuthFragment(), null) - .addToBackStack(null) - .commit() - } else if (toggleButtonState && (userIdEditText.text.toString() != "") && (passwordEditText.text.toString() != "")) { - if (validate()) - parentFragmentManager.beginTransaction() - .replace(android.R.id.content, DetectConfigurationFragment(), null) - .addToBackStack(null) - .commit() + navigate(MurenaOpenIdAuthFragment()) + } else if ((userIdEditText.text.toString() != "") && (passwordEditText.text.toString() != "") && validate()) { + navigate(DetectConfigurationFragment()) } else { - Toast.makeText(context, "Please enter a valid credentials", Toast.LENGTH_LONG).show() + Toast.makeText(context, R.string.invalid_credentials, Toast.LENGTH_LONG).show() } } + private fun navigate(fragment: Fragment) { + parentFragmentManager.beginTransaction() + .replace(android.R.id.content, fragment, null) + .addToBackStack(null) + .commit() + } + // if user wants to login with murena account, add support to automated retry // if user in any case provide wrong accountId as email (ex: abc@murena.io instead of abc@e.email) private fun addSupportRetryOn401IfPossible(serverUrl: String) { @@ -295,6 +304,10 @@ class EeloAuthenticatorFragment : Fragment() { serverUrlEditText.isEnabled = false toggleButtonState = false + if(!EeloAuthenticatorModel.enableOpenIdSupport) { + return + } + passwordHolder.visibility = View.GONE passwordEditText.setText("") } diff --git a/app/src/main/java/at/bitfire/davdroid/ui/setup/EeloAuthenticatorModel.kt b/app/src/main/java/at/bitfire/davdroid/ui/setup/EeloAuthenticatorModel.kt index ce607af20..c65296df1 100644 --- a/app/src/main/java/at/bitfire/davdroid/ui/setup/EeloAuthenticatorModel.kt +++ b/app/src/main/java/at/bitfire/davdroid/ui/setup/EeloAuthenticatorModel.kt @@ -24,24 +24,25 @@ import at.bitfire.davdroid.ECloudAccountHelper class EeloAuthenticatorModel(application: Application) : AndroidViewModel(application) { + companion object { + // as https://gitlab.e.foundation/e/backlog/-/issues/6287 is blocked, the openId implementation is not ready yet. + // But we want to push the changes so later we won't face any conflict. So we are disabling the openId feature for now. + const val enableOpenIdSupport = false + } + private var initialized = false + val loginWithUrlAndTokens = MutableLiveData() val baseUrl = MutableLiveData() val baseUrlError = MutableLiveData() - val emailAddress = MutableLiveData() - val emailAddressError = MutableLiveData() - val username = MutableLiveData() - val usernameError = MutableLiveData() val password = MutableLiveData() - val passwordError = MutableLiveData() val certificateAlias = MutableLiveData() - val certificateAliasError = MutableLiveData() init { loginWithUrlAndTokens.value = true @@ -53,7 +54,6 @@ class EeloAuthenticatorModel(application: Application) : AndroidViewModel(applic // we've got initial login data val givenUrl = intent.getStringExtra(LoginActivity.EXTRA_URL) - val givenUsername = intent.getStringExtra(LoginActivity.EXTRA_USERNAME) val givenPassword = intent.getStringExtra(LoginActivity.EXTRA_PASSWORD) baseUrl.value = givenUrl diff --git a/app/src/main/java/at/bitfire/davdroid/ui/setup/MurenaOpenIdAuthFragment.kt b/app/src/main/java/at/bitfire/davdroid/ui/setup/MurenaOpenIdAuthFragment.kt index 361dcb770..8a5636acc 100644 --- a/app/src/main/java/at/bitfire/davdroid/ui/setup/MurenaOpenIdAuthFragment.kt +++ b/app/src/main/java/at/bitfire/davdroid/ui/setup/MurenaOpenIdAuthFragment.kt @@ -49,7 +49,6 @@ class MurenaOpenIdAuthFragment : OpenIdAuthenticationBaseFragment(IdentityProvid return } - //val baseUrl = "https://${Constants.EELO_SYNC_HOST}" - proceedNext(userName, "https://murenatest.io/remote.php/dav/files/$userName") + proceedNext(userName, "https://murena.io/remote.php/dav/files/$userName") } } diff --git a/app/src/main/res/layout/fragment_eelo_authenticator.xml b/app/src/main/res/layout/fragment_eelo_authenticator.xml index fb20b45e4..58d9cec2b 100644 --- a/app/src/main/res/layout/fragment_eelo_authenticator.xml +++ b/app/src/main/res/layout/fragment_eelo_authenticator.xml @@ -167,6 +167,7 @@ android:drawableRight="@drawable/ic_info" android:drawableTint="@color/button_text" android:drawablePadding="7dp" + android:visibility="gone" android:layout_gravity="center"/> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 100c5ad07..45cbd6c6c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -582,4 +582,5 @@ Login failed, please try again later OK + Authentication failed. Please enter a valid credentials -- GitLab From 7a26a9734fd97af2f8b383d2f135cab63db7b902 Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Wed, 30 Aug 2023 13:10:04 +0600 Subject: [PATCH 5/5] update according to review --- .../at/bitfire/davdroid/network/HttpClient.kt | 37 +++++++++++++------ .../ui/setup/EeloAuthenticatorFragment.kt | 8 ++-- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/at/bitfire/davdroid/network/HttpClient.kt b/app/src/main/java/at/bitfire/davdroid/network/HttpClient.kt index a43bdd0b2..9b85b6ab1 100644 --- a/app/src/main/java/at/bitfire/davdroid/network/HttpClient.kt +++ b/app/src/main/java/at/bitfire/davdroid/network/HttpClient.kt @@ -157,18 +157,7 @@ class HttpClient private constructor( // use account settings for authentication and cookies if (accountSettings != null) { - val cred = accountSettings.credentials() - addAuthentication( - null, - cred, - authStateCallback = { authState: AuthState -> - accountSettings.credentials( - Credentials( - authState = authState, - clientSecret = cred.clientSecret - ) - ) - }) + addAuthentication(accountSettings) } } @@ -177,6 +166,30 @@ class HttpClient private constructor( addAuthentication(host, credentials) } + private fun addAuthentication(accountSettings: AccountSettings) { + val credential = accountSettings.credentials() + + addAuthentication( + null, + credential, + authStateCallback = { authState: AuthState -> + updateCredentials(accountSettings, authState, credential.clientSecret) + }) + } + + private fun updateCredentials( + accountSettings: AccountSettings, + authState: AuthState, + clientSecret: String? + ) { + accountSettings.credentials( + Credentials( + authState = authState, + clientSecret = clientSecret + ) + ) + } + fun addAuthentication(host: String?, credentials: Credentials, insecurePreemptive: Boolean = false, authStateCallback: BearerAuthInterceptor.AuthStateUpdateCallback? = null): Builder { if (credentials.userName != null && credentials.password != null) { val authHandler = BasicDigestAuthHandler(UrlUtils.hostToDomain(host), credentials.userName, credentials.password, insecurePreemptive) diff --git a/app/src/main/java/at/bitfire/davdroid/ui/setup/EeloAuthenticatorFragment.kt b/app/src/main/java/at/bitfire/davdroid/ui/setup/EeloAuthenticatorFragment.kt index 6d1ce19a7..77b0252c7 100644 --- a/app/src/main/java/at/bitfire/davdroid/ui/setup/EeloAuthenticatorFragment.kt +++ b/app/src/main/java/at/bitfire/davdroid/ui/setup/EeloAuthenticatorFragment.kt @@ -206,11 +206,13 @@ class EeloAuthenticatorFragment : Fragment() { handleNoNetworkAvailable() val handleOpenIdAuth = EeloAuthenticatorModel.enableOpenIdSupport && !toggleButtonState + val userId = userIdEditText.text.toString() + val password = passwordEditText.text.toString() - if (handleOpenIdAuth && (userIdEditText.text.toString() != "")) { + if (handleOpenIdAuth && userId.isNotBlank()) { requireActivity().intent.putExtra(LoginActivity.USERNAME_HINT, userIdEditText.text.toString()) navigate(MurenaOpenIdAuthFragment()) - } else if ((userIdEditText.text.toString() != "") && (passwordEditText.text.toString() != "") && validate()) { + } else if (userId.isNotBlank() && password.isNotBlank() && validate()) { navigate(DetectConfigurationFragment()) } else { Toast.makeText(context, R.string.invalid_credentials, Toast.LENGTH_LONG).show() @@ -309,7 +311,7 @@ class EeloAuthenticatorFragment : Fragment() { } passwordHolder.visibility = View.GONE - passwordEditText.setText("") + passwordEditText.text?.clear() } } -- GitLab