diff --git a/app/src/debug/res/raw/auth_config.json b/app/src/debug/res/raw/google_config.json similarity index 100% rename from app/src/debug/res/raw/auth_config.json rename to app/src/debug/res/raw/google_config.json diff --git a/app/src/genericRelease/res/raw/auth_config.json b/app/src/genericRelease/res/raw/google_config.json similarity index 100% rename from app/src/genericRelease/res/raw/auth_config.json rename to app/src/genericRelease/res/raw/google_config.json diff --git a/app/src/googleplayRelease/res/raw/auth_config.json b/app/src/googleplayRelease/res/raw/google_config.json similarity index 100% rename from app/src/googleplayRelease/res/raw/auth_config.json rename to app/src/googleplayRelease/res/raw/google_config.json diff --git a/app/src/main/java/org/tasks/auth/AuthorizationService.kt b/app/src/main/java/org/tasks/auth/AuthorizationService.kt index 8a1bbe14c..79d2e4ec5 100644 --- a/app/src/main/java/org/tasks/auth/AuthorizationService.kt +++ b/app/src/main/java/org/tasks/auth/AuthorizationService.kt @@ -4,19 +4,17 @@ import android.content.Context import android.content.Intent import android.net.Uri import androidx.browser.customtabs.CustomTabsIntent -import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import net.openid.appauth.* import net.openid.appauth.AuthorizationService import net.openid.appauth.browser.AnyBrowserMatcher -import javax.inject.Inject import kotlin.coroutines.suspendCoroutine -class AuthorizationService @Inject constructor( - @ApplicationContext context: Context, +class AuthorizationService constructor( + context: Context, private val authStateManager: AuthStateManager, - configuration: Configuration + val configuration: Configuration ) { private val authorizationService = AuthorizationService( context, diff --git a/app/src/main/java/org/tasks/auth/AuthorizationServiceProvider.kt b/app/src/main/java/org/tasks/auth/AuthorizationServiceProvider.kt new file mode 100644 index 000000000..cebfcef9b --- /dev/null +++ b/app/src/main/java/org/tasks/auth/AuthorizationServiceProvider.kt @@ -0,0 +1,21 @@ +package org.tasks.auth + +import android.content.Context +import dagger.hilt.android.qualifiers.ApplicationContext +import org.tasks.auth.Configuration.Companion.GOOGLE_CONFIG +import javax.inject.Inject + +class AuthorizationServiceProvider @Inject constructor( + @ApplicationContext context: Context, + authStateManager: AuthStateManager +){ + val google = AuthorizationService( + context, + authStateManager, + Configuration(context, GOOGLE_CONFIG) + ) + + fun dispose() { + google.dispose() + } +} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/auth/Configuration.kt b/app/src/main/java/org/tasks/auth/Configuration.kt index 281788cab..5dee932a2 100644 --- a/app/src/main/java/org/tasks/auth/Configuration.kt +++ b/app/src/main/java/org/tasks/auth/Configuration.kt @@ -17,7 +17,6 @@ import android.content.Context import android.content.Intent import android.net.Uri import android.text.TextUtils -import dagger.hilt.android.qualifiers.ApplicationContext import net.openid.appauth.connectivity.ConnectionBuilder import net.openid.appauth.connectivity.DefaultConnectionBuilder import okio.Buffer @@ -28,17 +27,15 @@ import org.json.JSONObject import org.tasks.R import java.io.IOException import java.nio.charset.StandardCharsets -import javax.inject.Inject -import javax.inject.Singleton /** - * Reads and validates the demo app configuration from `res/raw/auth_config.json`. Configuration + * Reads and validates the app configuration from `authConfig`. Configuration * changes are detected by comparing the hash of the last known configuration to the read * configuration. When a configuration change is detected, the app state is reset. */ -@Singleton -class Configuration @Inject constructor( - @ApplicationContext private val context: Context +class Configuration constructor( + private val context: Context, + private val authConfig: Int ) { private val prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) private var configJson: JSONObject? = null @@ -100,7 +97,7 @@ class Configuration @Inject constructor( @Throws(InvalidConfigurationException::class) private fun readConfiguration() { - val configSource = context.resources.openRawResource(R.raw.auth_config).source().buffer() + val configSource = context.resources.openRawResource(authConfig).source().buffer() val configData = Buffer() configJson = try { configSource.readAll(configData) @@ -209,6 +206,7 @@ class Configuration @Inject constructor( companion object { private const val PREFS_NAME = "config" private const val KEY_LAST_HASH = "lastHash" + const val GOOGLE_CONFIG = R.raw.google_config } init { diff --git a/app/src/main/java/org/tasks/auth/SignInActivity.kt b/app/src/main/java/org/tasks/auth/SignInActivity.kt index f44d49fe0..188839717 100644 --- a/app/src/main/java/org/tasks/auth/SignInActivity.kt +++ b/app/src/main/java/org/tasks/auth/SignInActivity.kt @@ -41,8 +41,7 @@ import javax.inject.Inject /** * Demonstrates the usage of the AppAuth to authorize a user with an OAuth2 / OpenID Connect - * provider. Based on the configuration provided in `res/raw/auth_config.json`, the code - * contained here will: + * provider * * - Retrieve an OpenID Connect discovery document for the provider, or use a local static * configuration. @@ -51,9 +50,8 @@ import javax.inject.Inject */ @AndroidEntryPoint class SignInActivity : InjectingAppCompatActivity(), PurchaseDialog.PurchaseHandler { - @Inject lateinit var authService: AuthorizationService + @Inject lateinit var authorizationServiceProvider: AuthorizationServiceProvider @Inject lateinit var authStateManager: AuthStateManager - @Inject lateinit var configuration: Configuration @Inject lateinit var themeColor: ThemeColor @Inject lateinit var inventory: Inventory @@ -65,11 +63,17 @@ class SignInActivity : InjectingAppCompatActivity(), PurchaseDialog.PurchaseHand private var mAuthIntentLatch = CountDownLatch(1) private val mExecutor: ExecutorService = newSingleThreadExecutor() + lateinit var authService: AuthorizationService + lateinit var configuration: Configuration + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) viewModel.error.observe(this, this::handleError) + authService = authorizationServiceProvider.google + configuration = authService.configuration + if (authStateManager.current.isAuthorized && !configuration.hasConfigurationChanged()) { Timber.i("User is already authenticated, signing out") @@ -155,7 +159,7 @@ class SignInActivity : InjectingAppCompatActivity(), PurchaseDialog.PurchaseHand // if we are not using discovery, build the authorization service configuration directly // from the static configuration values. if (configuration.discoveryUri == null) { - Timber.i("Creating auth config from res/raw/auth_config.json") + Timber.i("Creating auth config") val config = AuthorizationServiceConfiguration( configuration.authEndpointUri!!, configuration.tokenEndpointUri!!, diff --git a/app/src/main/java/org/tasks/auth/SignInViewModel.kt b/app/src/main/java/org/tasks/auth/SignInViewModel.kt index 20c466e09..04ee559be 100644 --- a/app/src/main/java/org/tasks/auth/SignInViewModel.kt +++ b/app/src/main/java/org/tasks/auth/SignInViewModel.kt @@ -20,7 +20,7 @@ import timber.log.Timber class SignInViewModel @ViewModelInject constructor( @ApplicationContext private val context: Context, private val authStateManager: AuthStateManager, - private val authorizationService: AuthorizationService, + private val authorizationServiceProvider: AuthorizationServiceProvider, private val provider: CaldavClientProvider, private val caldavDao: CaldavDao ) : ViewModel() { @@ -88,12 +88,14 @@ class SignInViewModel @ViewModelInject constructor( throw ex } try { - authorizationService.performTokenRequest(request, clientAuthentication)?.let { - authStateManager.updateAfterTokenResponse(it, null) - if (authStateManager.current.isAuthorized) { - Timber.d("Authorization successful") - } - } + authorizationServiceProvider + .google + .performTokenRequest(request, clientAuthentication)?.let { + authStateManager.updateAfterTokenResponse(it, null) + if (authStateManager.current.isAuthorized) { + Timber.d("Authorization successful") + } + } } catch (e: AuthorizationException) { authStateManager.updateAfterTokenResponse(null, e) } diff --git a/app/src/main/java/org/tasks/caldav/CaldavClientProvider.kt b/app/src/main/java/org/tasks/caldav/CaldavClientProvider.kt index 105738773..77c0cc4fa 100644 --- a/app/src/main/java/org/tasks/caldav/CaldavClientProvider.kt +++ b/app/src/main/java/org/tasks/caldav/CaldavClientProvider.kt @@ -12,7 +12,7 @@ import okhttp3.Interceptor import okhttp3.OkHttpClient import okhttp3.internal.tls.OkHostnameVerifier import org.tasks.DebugNetworkInterceptor -import org.tasks.auth.AuthorizationService +import org.tasks.auth.AuthorizationServiceProvider import org.tasks.billing.Inventory import org.tasks.data.CaldavAccount import org.tasks.preferences.Preferences @@ -27,7 +27,7 @@ class CaldavClientProvider @Inject constructor( private val preferences: Preferences, private val interceptor: DebugNetworkInterceptor, private val inventory: Inventory, - private val authorizationService: AuthorizationService + private val authorizationServiceProvider: AuthorizationServiceProvider ) { suspend fun forUrl( url: String?, @@ -66,9 +66,11 @@ class CaldavClientProvider @Inject constructor( token: String? = null ): Interceptor? { return when { - account?.isTasksOrg == true -> authorizationService.getFreshToken()?.let { - TokenInterceptor(it, inventory) - } + account?.isTasksOrg == true -> + authorizationServiceProvider + .google + .getFreshToken() + ?.let { TokenInterceptor(it, inventory) } username?.isNotBlank() == true && password?.isNotBlank() == true -> BasicDigestAuthHandler(null, username, password) token?.isNotBlank() == true -> @@ -106,6 +108,6 @@ class CaldavClientProvider @Inject constructor( } fun dispose() { - authorizationService.dispose() + authorizationServiceProvider.dispose() } } \ No newline at end of file