diff --git a/synchronization/src/main/java/de/cyface/synchronization/WiFiSurveyor.java b/synchronization/src/main/java/de/cyface/synchronization/WiFiSurveyor.java index de48aa980..559f9a8a8 100644 --- a/synchronization/src/main/java/de/cyface/synchronization/WiFiSurveyor.java +++ b/synchronization/src/main/java/de/cyface/synchronization/WiFiSurveyor.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2021 Cyface GmbH + * Copyright 2017-2024 Cyface GmbH * * This file is part of the Cyface SDK for Android. * @@ -49,8 +49,6 @@ * * @author Klemens Muthmann * @author Armin Schnabel - * @version 7.2.1 - * @since 2.0.0 */ public class WiFiSurveyor extends BroadcastReceiver { @@ -374,8 +372,8 @@ public void makeAccountSyncable(@NonNull final Account account, boolean enabled) * @return The only Account existing */ public Account getAccount() { - final AccountManager accountManager = AccountManager.get(context.get()); - final Account[] cyfaceAccounts = accountManager.getAccountsByType(accountType); + final var accountManager = AccountManager.get(context.get()); + final var cyfaceAccounts = accountManager.getAccountsByType(accountType); if (cyfaceAccounts.length == 0) { throw new IllegalStateException("No cyface account exists."); } diff --git a/synchronization/src/main/kotlin/de/cyface/synchronization/AuthStateManager.kt b/synchronization/src/main/kotlin/de/cyface/synchronization/AuthStateManager.kt index 79dad5c27..ee292566f 100644 --- a/synchronization/src/main/kotlin/de/cyface/synchronization/AuthStateManager.kt +++ b/synchronization/src/main/kotlin/de/cyface/synchronization/AuthStateManager.kt @@ -32,16 +32,10 @@ import java.util.concurrent.locks.ReentrantLock * This stores the instance in a shared preferences file, and provides thread-safe access and * mutation. */ -class AuthStateManager private constructor(context: Context) { - private val mPrefs: SharedPreferences - private val mPrefsLock: ReentrantLock - private val mCurrentAuthState: AtomicReference - - init { - mPrefs = context.getSharedPreferences(STORE_NAME, Context.MODE_PRIVATE) - mPrefsLock = ReentrantLock() - mCurrentAuthState = AtomicReference() - } +class AuthStateManager private constructor(private val context: Context) { + private val mPrefs: SharedPreferences = context.getSharedPreferences(STORE_NAME, Context.MODE_PRIVATE) + private val mPrefsLock: ReentrantLock = ReentrantLock() + private val mCurrentAuthState: AtomicReference = AtomicReference() @get:AnyThread val current: AuthState diff --git a/synchronization/src/main/kotlin/de/cyface/synchronization/CyfaceAuthenticator.kt b/synchronization/src/main/kotlin/de/cyface/synchronization/CyfaceAuthenticator.kt index 989a34ee6..c0b5c5fae 100644 --- a/synchronization/src/main/kotlin/de/cyface/synchronization/CyfaceAuthenticator.kt +++ b/synchronization/src/main/kotlin/de/cyface/synchronization/CyfaceAuthenticator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2023 Cyface GmbH + * Copyright 2018-2024 Cyface GmbH * * This file is part of the Cyface SDK for Android. * @@ -44,13 +44,11 @@ import kotlinx.coroutines.runBlocking * * @author Klemens Muthmann * @author Armin Schnabel - * @version 5.1.1 - * @since 2.0.0 */ class CyfaceAuthenticator(private val context: Context) : AbstractAccountAuthenticator(context), LoginActivityProvider { - private var auth: OAuth2 = OAuth2(context, settings) + var auth: OAuth2 = OAuth2(context, settings, "CyfaceAuthenticator") override fun editProperties( response: AccountAuthenticatorResponse, diff --git a/synchronization/src/main/kotlin/de/cyface/synchronization/CyfaceAuthenticatorService.kt b/synchronization/src/main/kotlin/de/cyface/synchronization/CyfaceAuthenticatorService.kt index 24248d9f3..049a58d9b 100644 --- a/synchronization/src/main/kotlin/de/cyface/synchronization/CyfaceAuthenticatorService.kt +++ b/synchronization/src/main/kotlin/de/cyface/synchronization/CyfaceAuthenticatorService.kt @@ -21,7 +21,6 @@ package de.cyface.synchronization import android.app.Service import android.content.Intent import android.os.IBinder -import android.util.Log /** * The Android service used to communicate with the Stub Authenticator. This has been implemented as described in @@ -29,8 +28,6 @@ import android.util.Log * * @author Klemens Muthmann * @author Armin Schnabel - * @version 1.0.7 - * @since 2.0.0 */ class CyfaceAuthenticatorService : Service() { /** diff --git a/synchronization/src/main/kotlin/de/cyface/synchronization/CyfaceSyncService.kt b/synchronization/src/main/kotlin/de/cyface/synchronization/CyfaceSyncService.kt index 50b485e8c..538efe679 100644 --- a/synchronization/src/main/kotlin/de/cyface/synchronization/CyfaceSyncService.kt +++ b/synchronization/src/main/kotlin/de/cyface/synchronization/CyfaceSyncService.kt @@ -1,5 +1,5 @@ /* - * Copyright 2017-2023 Cyface GmbH + * Copyright 2017-2024 Cyface GmbH * * This file is part of the Cyface SDK for Android. * @@ -34,8 +34,6 @@ import kotlinx.coroutines.runBlocking * * @author Armin Schnabel * @author Klemens Muthmann - * @version 1.0.9 - * @since 2.0.0 */ class CyfaceSyncService : Service() { @@ -46,7 +44,7 @@ class CyfaceSyncService : Service() { syncAdapter = SyncAdapter( applicationContext, true, - OAuth2(applicationContext, CyfaceAuthenticator.settings), + OAuth2(applicationContext, CyfaceAuthenticator.settings, "CyfaceSyncService"), DefaultUploader(collectorApi), ) } diff --git a/synchronization/src/main/kotlin/de/cyface/synchronization/OAuth2.kt b/synchronization/src/main/kotlin/de/cyface/synchronization/OAuth2.kt index 1acca884b..e584f5128 100644 --- a/synchronization/src/main/kotlin/de/cyface/synchronization/OAuth2.kt +++ b/synchronization/src/main/kotlin/de/cyface/synchronization/OAuth2.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023 Cyface GmbH + * Copyright 2023-2024 Cyface GmbH * * This file is part of the Cyface SDK for Android. * @@ -22,7 +22,6 @@ import android.accounts.Account import android.accounts.AccountManager import android.content.ContentResolver import android.content.Context -import android.content.Intent import android.os.Build import android.os.Bundle import android.util.Log @@ -38,7 +37,6 @@ import net.openid.appauth.AuthState import net.openid.appauth.AuthorizationException import net.openid.appauth.AuthorizationResponse import net.openid.appauth.AuthorizationService -import net.openid.appauth.AuthorizationServiceConfiguration import net.openid.appauth.ClientAuthentication import net.openid.appauth.EndSessionRequest import net.openid.appauth.TokenRequest @@ -52,12 +50,10 @@ import org.json.JSONObject * accounts, and handling sessions. * * @author Armin Schnabel - * @version 1.0.0 - * @since 7.9.0 * @param context The context to load settings and accounts from. * @param settings The settings which store the user preferences. */ -class OAuth2(context: Context, settings: SynchronizationSettings) : Auth { +class OAuth2(context: Context, settings: SynchronizationSettings, caller: String) : Auth { /** * The service used for authorization. @@ -67,23 +63,21 @@ class OAuth2(context: Context, settings: SynchronizationSettings) : Auth { /** * The authorization state. */ - private var stateManager: AuthStateManager + private var stateManager: AuthStateManager = AuthStateManager.getInstance(context) /** * The configuration of the OAuth 2 endpoint to authorize against. */ - private var configuration: Configuration + private var configuration: Configuration = Configuration.getInstance(context, settings) init { - // Authorization - stateManager = AuthStateManager.getInstance(context) - configuration = Configuration.getInstance(context, settings) /*if (config.hasConfigurationChanged()) { //throw IllegalArgumentException("config changed (SyncAdapter)") Toast.makeText(context, "Ignoring: config changed (SyncAdapter)", Toast.LENGTH_SHORT).show() //Handler().postDelayed({signOut()}, 2000) //return }*/ + Log.i(TAG, "OAuth2 init ($caller)") authService = AuthorizationService( context, AppAuthConfiguration.Builder() @@ -259,7 +253,7 @@ class OAuth2(context: Context, settings: SynchronizationSettings) : Auth { fun signOut() { // discard the authorization and token state, but retain the configuration and // dynamic client registration (if applicable), to save from retrieving them again. - val currentState: AuthState = stateManager.current + val currentState = stateManager.current if (currentState.authorizationServiceConfiguration != null) { // Replace the state with a fresh `AuthState` val clearedState = AuthState(currentState.authorizationServiceConfiguration!!) @@ -267,16 +261,26 @@ class OAuth2(context: Context, settings: SynchronizationSettings) : Auth { clearedState.update(currentState.lastRegistrationResponse) } stateManager.replace(clearedState) + + // [LEIP-233] Completely deleting the sharedPreferences/AuthState.xml file does not + // fix the `Credentials incorrect` error after re-login (app restart required) + //stateManager.deletePreferencesFile() + } else { + Log.w(TAG, "No authorization service configuration to sign out") } + + // Invalidate all tokens to ensure they are no longer used + dispose() } - // Keep: login is currently just deactivated because it's buggy + /** + * Sends the end session request to the auth service to sign out the user. + */ fun endSession(activity: FragmentActivity) { - val currentState: AuthState = stateManager.current - val config: AuthorizationServiceConfiguration = - currentState.authorizationServiceConfiguration!! + val currentState = stateManager.current + val config = currentState.authorizationServiceConfiguration!! if (config.endSessionEndpoint != null) { - val endSessionIntent: Intent = authService.getEndSessionRequestIntent( + val endSessionIntent = authService.getEndSessionRequestIntent( EndSessionRequest.Builder(config) .setIdTokenHint(currentState.idToken) .setPostLogoutRedirectUri(configuration.endSessionRedirectUri) @@ -310,4 +314,4 @@ class OAuth2(context: Context, settings: SynchronizationSettings) : Auth { .put("https_required", true) } } -} \ No newline at end of file +}