Add AuthorizationServiceProvider

pull/1244/head
Alex Baker 5 years ago
parent f126e7e462
commit 13d10eb203

@ -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,

@ -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()
}
}

@ -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 {

@ -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!!,

@ -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)
}

@ -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()
}
}
Loading…
Cancel
Save