Skip to content
This repository has been archived by the owner on Dec 14, 2021. It is now read-only.

Commit

Permalink
Auto-signin with mozilla AuthProvider (#879) — behind a feature flag.
Browse files Browse the repository at this point in the history
* WIP Automatic FxA sign-in support

* Cleanup welcome fragment/account detection

* Upgrade to Android Components 9.0.0

* Ensure landable, even if not releasable

* gradlew lint
  • Loading branch information
jhugman authored Sep 3, 2019
1 parent fecc2f0 commit 5a83079
Show file tree
Hide file tree
Showing 13 changed files with 294 additions and 24 deletions.
109 changes: 109 additions & 0 deletions .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions app/src/main/java/mozilla/lockbox/action/AccountAction.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@

package mozilla.lockbox.action

import mozilla.components.service.fxa.sharing.ShareableAccount
import mozilla.lockbox.flux.Action

sealed class AccountAction : Action {
object Reset : AccountAction()
object UseTestData : AccountAction()
data class OauthRedirect(val url: String) : AccountAction()
data class AutomaticLogin(val account: ShareableAccount) : AccountAction()
}
21 changes: 18 additions & 3 deletions app/src/main/java/mozilla/lockbox/action/DialogAction.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
package mozilla.lockbox.action

import mozilla.appservices.logins.ServerPassword
import mozilla.components.service.fxa.sharing.ShareableAccount
import mozilla.lockbox.R
import mozilla.lockbox.flux.Action
import mozilla.lockbox.model.DialogViewModel
Expand Down Expand Up @@ -47,7 +48,7 @@ sealed class DialogAction(
listOf(LifecycleAction.UserReset)
)

object OnboardingSecurityDialog : DialogAction(
data class OnboardingSecurityDialogAutomatic(val account: ShareableAccount) : DialogAction(
DialogViewModel(
R.string.secure_your_device,
R.string.device_security_description,
Expand All @@ -56,7 +57,7 @@ sealed class DialogAction(
),
listOf(
SystemSetting(SettingIntent.Security),
Login
AccountAction.AutomaticLogin(account)
),
listOf(Login)
)
Expand All @@ -76,4 +77,18 @@ sealed class DialogAction(
ItemList
)
)
}

object OnboardingSecurityDialogManual : DialogAction(
DialogViewModel(
R.string.secure_your_device,
R.string.device_security_description,
R.string.set_up_now,
R.string.skip_button
),
listOf(
SystemSetting(SettingIntent.Security),
Login
),
listOf(Login)
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ class AppRoutePresenter(
R.id.fragment_null to R.id.fragment_welcome -> R.id.action_init_to_unprepared

R.id.fragment_welcome to R.id.fragment_fxa_login -> R.id.action_welcome_to_fxaLogin
R.id.fragment_welcome to R.id.fragment_item_list -> R.id.action_welcome_to_autoLogin

R.id.fragment_fxa_login to R.id.fragment_item_list -> R.id.action_fxaLogin_to_itemList
R.id.fragment_fxa_login to R.id.fragment_fingerprint_onboarding ->
Expand Down
51 changes: 43 additions & 8 deletions app/src/main/java/mozilla/lockbox/presenter/WelcomePresenter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,52 @@ package mozilla.lockbox.presenter

import io.reactivex.Observable
import io.reactivex.rxkotlin.addTo
import kotlinx.coroutines.ExperimentalCoroutinesApi
import mozilla.components.service.fxa.sharing.ShareableAccount
import mozilla.lockbox.action.AccountAction
import mozilla.lockbox.action.AppWebPageAction
import mozilla.lockbox.action.DialogAction
import mozilla.lockbox.action.RouteAction
import mozilla.lockbox.flux.Dispatcher
import mozilla.lockbox.flux.Presenter
import mozilla.lockbox.store.AccountStore
import mozilla.lockbox.store.FingerprintStore
import mozilla.lockbox.support.FeatureFlags

interface WelcomeView {
val getStartedClicks: Observable<Unit>
val getStartedAutomaticallyClicks: Observable<Unit>
val getStartedManuallyClicks: Observable<Unit>
val learnMoreClicks: Observable<Unit>
fun showExistingAccount(email: String)
fun hideExistingAccount()
}

@ExperimentalCoroutinesApi
class WelcomePresenter(
private val view: WelcomeView,
private val dispatcher: Dispatcher = Dispatcher.shared,
private val accountStore: AccountStore = AccountStore.shared,
private val fingerprintStore: FingerprintStore = FingerprintStore.shared
) : Presenter() {

override fun onViewReady() {
view.getStartedClicks
if (FeatureFlags.FXA_LOGIN_WITTH_AUTHPROVIDER) {
accountStore.shareableAccount()?.let { account ->
view.showExistingAccount(account.email)
view.getStartedAutomaticallyClicks
.map {
routeToExistingAccount(account)
}
.subscribe(dispatcher::dispatch)
.addTo(compositeDisposable)
} ?: view.hideExistingAccount()
} else {
view.hideExistingAccount()
}

view.getStartedManuallyClicks
.map {
if (fingerprintStore.isKeyguardDeviceSecure)
RouteAction.Login
else {
DialogAction.OnboardingSecurityDialog
}
routeToLoginManually()
}
.subscribe(dispatcher::dispatch)
.addTo(compositeDisposable)
Expand All @@ -43,4 +64,18 @@ class WelcomePresenter(
}
.addTo(compositeDisposable)
}
}

private fun routeToExistingAccount(account: ShareableAccount) =
if (fingerprintStore.isKeyguardDeviceSecure) {
AccountAction.AutomaticLogin(account)
} else {
DialogAction.OnboardingSecurityDialogAutomatic(account)
}

private fun routeToLoginManually() =
if (fingerprintStore.isKeyguardDeviceSecure) {
RouteAction.Login
} else {
DialogAction.OnboardingSecurityDialogManual
}
}
28 changes: 25 additions & 3 deletions app/src/main/java/mozilla/lockbox/store/AccountStore.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import mozilla.components.concept.sync.Avatar
import mozilla.components.concept.sync.Profile
import mozilla.components.service.fxa.ServerConfig
import mozilla.components.service.fxa.FirefoxAccount
import mozilla.components.service.fxa.sharing.AccountSharing
import mozilla.components.service.fxa.sharing.ShareableAccount
import mozilla.lockbox.action.AccountAction
import mozilla.lockbox.action.DataStoreAction
import mozilla.lockbox.action.LifecycleAction
Expand Down Expand Up @@ -91,6 +93,7 @@ open class AccountStore(

private lateinit var webView: WebView
private lateinit var logDirectory: File
private lateinit var context: Context

init {
val resetObservable = lifecycleStore.lifecycleEvents
Expand All @@ -109,6 +112,7 @@ open class AccountStore(
when (it) {
is AccountAction.OauthRedirect -> this.oauthLogin(it.url)
is AccountAction.UseTestData -> this.populateTestAccountInformation(true)
is AccountAction.AutomaticLogin -> this.automaticLogin(it.account)
is AccountAction.Reset -> this.clear()
}
}
Expand All @@ -126,10 +130,29 @@ open class AccountStore(

override fun injectContext(context: Context) {
detectAccount()
this.context = context
webView = WebView(context)
logDirectory = context.getDir("webview", Context.MODE_PRIVATE)
}

fun shareableAccount(): ShareableAccount? {
return AccountSharing.queryShareableAccounts(context).firstOrNull()
}

private fun automaticLogin(account: ShareableAccount) {
fxa?.migrateFromSessionTokenAsync(
account.authInfo.sessionToken,
account.authInfo.kSync,
account.authInfo.kXCS
)
?.let {
it.asSingle(coroutineContext)
.map { true }
.subscribe(this::populateAccountInformation, this::pushError)
.addTo(compositeDisposable)
}
}

private fun detectAccount() {
storedAccountJSON?.let { accountJSON ->
if (accountJSON == Constant.App.testMarker) {
Expand Down Expand Up @@ -202,7 +225,7 @@ open class AccountStore(
private fun generateLoginURL() {
val fxa = fxa ?: return

fxa.beginOAuthFlowAsync(Constant.FxA.scopes, true)
fxa.beginOAuthFlowAsync(Constant.FxA.scopes)
.asMaybe(coroutineContext)
.subscribe((this.loginURL as Subject)::onNext, this::pushError)
.addTo(compositeDisposable)
Expand Down Expand Up @@ -243,8 +266,7 @@ open class AccountStore(

private fun removeDeviceFromFxA() {
if (fxa != null) {
fxa!!.deviceConstellation()
.destroyCurrentDeviceAsync()
fxa!!.disconnectAsync()
.asSingle(coroutineContext)
.subscribe()
.addTo(compositeDisposable)
Expand Down
15 changes: 14 additions & 1 deletion app/src/main/java/mozilla/lockbox/support/FeatureFlags.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,17 @@ object FeatureFlags {
isRelease -> false
else -> false
}
}

/**
* Use existing apps' FxA credentials to login.
*
* Currently, only Fennec will detect the release version of Lockwise.
* To see this work, you need a custom build of Fennec and Android Components.
*/
val FXA_LOGIN_WITTH_AUTHPROVIDER = when {
isDebug -> true
isTesting -> false
isRelease -> false
else -> false
}
}
Loading

0 comments on commit 5a83079

Please sign in to comment.