@@ -93,6 +93,13 @@ import org.koin.androidx.viewmodel.ext.android.viewModel
9393import timber.log.Timber
9494import java.io.File
9595
96+
97+ private const val KEY_SERVER_BASE_URL = " KEY_SERVER_BASE_URL"
98+ private const val KEY_OIDC_SUPPORTED = " KEY_OIDC_SUPPORTED"
99+ private const val KEY_CODE_VERIFIER = " KEY_CODE_VERIFIER"
100+ private const val KEY_CODE_CHALLENGE = " KEY_CODE_CHALLENGE"
101+ private const val KEY_OIDC_STATE = " KEY_OIDC_STATE"
102+
96103class LoginActivity : AppCompatActivity (), SslUntrustedCertDialog.OnSslUntrustedCertListener, SecurityEnforced {
97104
98105 private val authenticationViewModel by viewModel<AuthenticationViewModel >()
@@ -114,6 +121,16 @@ class LoginActivity : AppCompatActivity(), SslUntrustedCertDialog.OnSslUntrusted
114121 private var resultBundle: Bundle ? = null
115122
116123 override fun onCreate (savedInstanceState : Bundle ? ) {
124+ if (intent.data != null && (intent.data?.getQueryParameter(" code" ) != null || intent.data?.getQueryParameter(" error" ) != null )) {
125+ if (! isTaskRoot) {
126+ val newIntent = Intent (this , LoginActivity ::class .java)
127+ newIntent.data = intent.data
128+ newIntent.addFlags(Intent .FLAG_ACTIVITY_CLEAR_TOP or Intent .FLAG_ACTIVITY_SINGLE_TOP )
129+ startActivity(newIntent)
130+ finish()
131+ return
132+ }
133+ }
117134 super .onCreate(savedInstanceState)
118135
119136 checkPasscodeEnforced(this )
@@ -136,6 +153,11 @@ class LoginActivity : AppCompatActivity(), SslUntrustedCertDialog.OnSslUntrusted
136153 }
137154 } else {
138155 authTokenType = savedInstanceState.getString(KEY_AUTH_TOKEN_TYPE )
156+ savedInstanceState.getString(KEY_SERVER_BASE_URL )?.let { serverBaseUrl = it }
157+ oidcSupported = savedInstanceState.getBoolean(KEY_OIDC_SUPPORTED )
158+ savedInstanceState.getString(KEY_CODE_VERIFIER )?.let { authenticationViewModel.codeVerifier = it }
159+ savedInstanceState.getString(KEY_CODE_CHALLENGE )?.let { authenticationViewModel.codeChallenge = it }
160+ savedInstanceState.getString(KEY_OIDC_STATE )?.let { authenticationViewModel.oidcState = it }
139161 }
140162
141163 // UI initialization
@@ -164,6 +186,17 @@ class LoginActivity : AppCompatActivity(), SslUntrustedCertDialog.OnSslUntrusted
164186 binding.accountUsername.setText(username)
165187 }
166188 }
189+ } else {
190+ // Restore UI state
191+ if (::serverBaseUrl.isInitialized && serverBaseUrl.isNotEmpty()) {
192+ binding.hostUrlInput.setText(serverBaseUrl)
193+
194+ if (authTokenType == BASIC_TOKEN_TYPE ) {
195+ showOrHideBasicAuthFields(shouldBeVisible = true )
196+ } else if (authTokenType == OAUTH_TOKEN_TYPE ) {
197+ showOrHideBasicAuthFields(shouldBeVisible = false )
198+ }
199+ }
167200 }
168201
169202 binding.root.filterTouchesWhenObscured =
@@ -194,10 +227,17 @@ class LoginActivity : AppCompatActivity(), SslUntrustedCertDialog.OnSslUntrusted
194227 accountAuthenticatorResponse?.onRequestContinued()
195228
196229 initLiveDataObservers()
230+
231+ if (intent.data != null && (intent.data?.getQueryParameter(" code" ) != null || intent.data?.getQueryParameter(" error" ) != null )) {
232+ if (savedInstanceState == null ) {
233+ restoreAuthState()
234+ }
235+ handleGetAuthorizationCodeResponse(intent)
236+ }
197237 }
198238
199239 private fun handleDeepLink () {
200- if (intent.data != null ) {
240+ if (intent.data != null && intent.data?.getQueryParameter( " code " ) == null && intent.data?.getQueryParameter( " error " ) == null ) {
201241 authenticationViewModel.launchedFromDeepLink = true
202242 if (getAccounts(baseContext).isNotEmpty()) {
203243 launchFileDisplayActivity()
@@ -469,6 +509,7 @@ class LoginActivity : AppCompatActivity(), SslUntrustedCertDialog.OnSslUntrusted
469509 setResult(Activity .RESULT_OK , intent)
470510
471511 authenticationViewModel.discoverAccount(accountName = accountName, discoveryNeeded = loginAction == ACTION_CREATE )
512+ clearAuthState()
472513 }
473514
474515 private fun loginIsLoading () {
@@ -498,6 +539,7 @@ class LoginActivity : AppCompatActivity(), SslUntrustedCertDialog.OnSslUntrusted
498539 }
499540 }
500541 }
542+ clearAuthState()
501543 }
502544
503545 /* *
@@ -553,6 +595,7 @@ class LoginActivity : AppCompatActivity(), SslUntrustedCertDialog.OnSslUntrusted
553595 )
554596
555597 try {
598+ saveAuthState()
556599 customTabsIntent.launchUrl(
557600 this ,
558601 authorizationEndpointUri
@@ -853,6 +896,10 @@ class LoginActivity : AppCompatActivity(), SslUntrustedCertDialog.OnSslUntrusted
853896 override fun onSaveInstanceState (outState : Bundle ) {
854897 super .onSaveInstanceState(outState)
855898 outState.putString(KEY_AUTH_TOKEN_TYPE , authTokenType)
899+ if (::serverBaseUrl.isInitialized) {
900+ outState.putString(KEY_SERVER_BASE_URL , serverBaseUrl)
901+ }
902+ outState.putBoolean(KEY_OIDC_SUPPORTED , oidcSupported)
856903 }
857904
858905 override fun finish () {
@@ -873,4 +920,26 @@ class LoginActivity : AppCompatActivity(), SslUntrustedCertDialog.OnSslUntrusted
873920 override fun optionLockSelected (type : LockType ) {
874921 manageOptionLockSelected(type)
875922 }
923+
924+ private fun saveAuthState () {
925+ val prefs = getSharedPreferences(" auth_state" , android.content.Context .MODE_PRIVATE )
926+ prefs.edit().apply {
927+ putString(KEY_CODE_VERIFIER , authenticationViewModel.codeVerifier)
928+ putString(KEY_CODE_CHALLENGE , authenticationViewModel.codeChallenge)
929+ putString(KEY_OIDC_STATE , authenticationViewModel.oidcState)
930+ apply ()
931+ }
932+ }
933+
934+ private fun restoreAuthState () {
935+ val prefs = getSharedPreferences(" auth_state" , android.content.Context .MODE_PRIVATE )
936+ prefs.getString(KEY_CODE_VERIFIER , null )?.let { authenticationViewModel.codeVerifier = it }
937+ prefs.getString(KEY_CODE_CHALLENGE , null )?.let { authenticationViewModel.codeChallenge = it }
938+ prefs.getString(KEY_OIDC_STATE , null )?.let { authenticationViewModel.oidcState = it }
939+ }
940+
941+ private fun clearAuthState () {
942+ val prefs = getSharedPreferences(" auth_state" , android.content.Context .MODE_PRIVATE )
943+ prefs.edit().clear().apply ()
944+ }
876945}
0 commit comments