diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 7a3601b0e3b7dcc6881020733acfa8fa52ad594d..f9934458fa6c5cc4a686c4bf80221cf6a2ecd7b2 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 1a900b11a777a22ae344e2c2b1f650205091ed9e..6418c44c0ba5565b784d8e0b4720470149eb9acb 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 fd66593b2d4d009d1af3d7ecd79ddab4f8d08b82..24a70afbfa21c93fc2b7e00eb1229a25ad5e7f2f 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 3e25ddd2de4e720f9e1ecc4607ac97dae78b5caf..c4bd3d78d1899f7994cb75079d3920b7e1228d55 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/network/HttpClient.kt b/app/src/main/java/at/bitfire/davdroid/network/HttpClient.kt
index 4cd6b08e46b2c5b0e9872808a6868aa41cdd8b3f..9b85b6ab17f0ab142af36eb9fee8a078e57b502f 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,9 @@ 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) {
+ addAuthentication(accountSettings)
+ }
}
constructor(context: Context, host: String?, credentials: Credentials?) : this(context) {
@@ -167,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/syncadapter/AccountUtils.kt b/app/src/main/java/at/bitfire/davdroid/syncadapter/AccountUtils.kt
index cbe2ba8ebdf6e33c8cbb04fb4fbf510a8c15fb1d..22ebaf52938ff06cce0dba3b908f9d64fb0ceab6 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 e31e04345b60d1d6b58b4b57ba775bd5f1336115..cc19d2dfa086f3be63a4e23adfeb1f0cc8c893bd 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)
@@ -210,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)
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 747b0310c1b18d5f6712960cdbf20075450389a0..343ae97ef91c7be0b3409c49200595348de4d0b4 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 c5286e67cfc56dc6eb0db624c273feb5e0df0bf4..92114462c591cc8ef88f598159f127d8a15182a7 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, isMurenaAccountType).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 50061c91beeb83e72fd7a2a373ae35eb55ec7c91..77b0252c74c3991a0685e53b924bf7db4da990a0 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
@@ -55,6 +56,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
@@ -64,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
@@ -79,12 +77,17 @@ 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)
+
+ 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)
@@ -190,24 +193,40 @@ 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 ((userIdEditText.text.toString() != "") && (passwordEditText.text.toString() != "")) {
- if (validate())
- parentFragmentManager.beginTransaction()
- .replace(android.R.id.content, DetectConfigurationFragment(), null)
- .addToBackStack(null)
- .commit()
+ Toast.makeText(context, R.string.no_internet_toast, Toast.LENGTH_LONG).show()
+ requireActivity().finish()
+ }
+
+ private fun login() {
+ handleNoNetworkAvailable()
+
+ val handleOpenIdAuth = EeloAuthenticatorModel.enableOpenIdSupport && !toggleButtonState
+ val userId = userIdEditText.text.toString()
+ val password = passwordEditText.text.toString()
+
+ if (handleOpenIdAuth && userId.isNotBlank()) {
+ requireActivity().intent.putExtra(LoginActivity.USERNAME_HINT, userIdEditText.text.toString())
+ navigate(MurenaOpenIdAuthFragment())
+ } else if (userId.isNotBlank() && password.isNotBlank() && validate()) {
+ navigate(DetectConfigurationFragment())
} else {
- Toast.makeText(context, "Please enter a valid username and password", 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) {
@@ -279,11 +298,20 @@ 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
+
+ if(!EeloAuthenticatorModel.enableOpenIdSupport) {
+ return
+ }
+
+ passwordHolder.visibility = View.GONE
+ passwordEditText.text?.clear()
}
}
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 ce607af20cf88c454b59cc16796c6541ecf9967c..c65296df1a15c71d505ded1a55fa11ec712ec70f 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/LoginActivity.kt b/app/src/main/java/at/bitfire/davdroid/ui/setup/LoginActivity.kt
index 8bbd99bf090d8cf7322c1a5dad908bb65b8cd561..df981373c778b678a3590d15218754be983a0313 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 3a2462e932083d00fea25a2691a59dc26bc8cd8d..4bb15ba6f81fb8ef3432c0ede540840abd66012e 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 0000000000000000000000000000000000000000..8a5636accfa099f12f1f09e08f94ddfe05d34c00
--- /dev/null
+++ b/app/src/main/java/at/bitfire/davdroid/ui/setup/MurenaOpenIdAuthFragment.kt
@@ -0,0 +1,54 @@
+/*
+ * 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
+ }
+
+ proceedNext(userName, "https://murena.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 b5c23d460068d4dc97449455adefe283f26a2204..175872dc535f3ca318c76db71bfc31a20cc6ccd3 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()
@@ -65,7 +76,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 +88,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 +113,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 0321f345d07c5c0ffcf01c8e65edae8667a11b0a..58d9cec2be88c8c3dee7b12043dee6b0c450a0c6 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 @@
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 100c5ad075ae851dbb5b89cab4526cffb35f976b..45cbd6c6c8a19235257aafe8f08a3ef86ff6b63b 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