Loading app/src/main/java/com/nextcloud/android/sso/OidcTokenRefresher.kt +4 −2 Original line number Diff line number Diff line Loading @@ -66,7 +66,7 @@ object OidcTokenRefresher { account: Account?, getClientAuth: () -> ClientAuthentication?, readAuthState: () -> AuthState?, writeAuthState: (AuthState) -> Unit writeAuthState: ((AuthState) -> Unit)? = null ): AuthState? = synchronized(javaClass) { val authState = readAuthState() ?: return null // Use cached authState if possible Loading Loading @@ -97,7 +97,9 @@ object OidcTokenRefresher { authState.performActionWithFreshTokens( authService, clientAuth ) { accessToken, _, exception -> if (writeAuthState != null) { writeAuthState(authState) } when { accessToken != null -> { logger.info("Token refreshed for $account") Loading app/src/main/kotlin/at/bitfire/davdroid/token/MurenaTokenManager.kt +40 −36 Original line number Diff line number Diff line Loading @@ -25,12 +25,12 @@ import android.app.PendingIntent import android.content.Context import android.content.Intent import at.bitfire.davdroid.BuildConfig import at.bitfire.davdroid.OpenIdUtils import at.bitfire.davdroid.R import at.bitfire.davdroid.log.Logger import at.bitfire.davdroid.network.HttpClient import at.bitfire.davdroid.settings.AccountSettings import at.bitfire.davdroid.ui.NetworkUtils import dagger.hilt.android.EntryPointAccessors import com.nextcloud.android.sso.OidcTokenRefresher import net.openid.appauth.AuthState import net.openid.appauth.AuthorizationException import java.text.SimpleDateFormat Loading Loading @@ -134,11 +134,6 @@ object MurenaTokenManager { // Refreshes the authentication token and updates stored credentials if successful. private fun refreshAuthToken(context: Context, onComplete: ((AuthState?) -> Unit)? = null) { try { val httpEntryPoint = EntryPointAccessors.fromApplication( context, HttpClient.HttpClientEntryPoint::class.java ) val authService = httpEntryPoint.authorizationService() val accountSettings = getAccountSettings(context) ?: run { Logger.log.warning("No account settings found during token refresh.") return Loading @@ -156,38 +151,47 @@ object MurenaTokenManager { return } val tokenRequest = authState.createTokenRefreshRequest() authService.performTokenRequest(tokenRequest) { response, exception -> when { response != null && exception == null -> { authState.update(response, null) accountSettings.credentials(credentials.copy(authState = authState)) Logger.log.info("Token refreshed for ${accountSettings.account.name}") val updatedAuthState: AuthState? = try { OidcTokenRefresher.refreshAuthState( context = context, account = accountSettings.account, getClientAuth = { OpenIdUtils.getClientAuthentication(credentials.clientSecret) }, readAuthState = { authState } ) } catch (e: AuthorizationException) { if (isInvalidGrant(e)) { Logger.log.log( Level.SEVERE, "Invalid grant: refresh cancelled, User must re-authenticate.", e ) cancelTokenRefreshAlarm(context) } else { Logger.log.log(Level.SEVERE, "Token refresh failed: $e, retrying in 5 minutes.") setTokenRefreshAlarm( context, System.currentTimeMillis() + 5.minutes.inWholeMilliseconds ) } onComplete?.invoke(null) null } if (updatedAuthState != null) { accountSettings.credentials(credentials.copy(authState = updatedAuthState)) Logger.log.info("Token refreshed for ${accountSettings.account}") // Schedule at least 2 minutes early for the new token. val refreshAt = authState.accessTokenExpirationTime?.minus(2.minutes.inWholeMilliseconds) val refreshAt = updatedAuthState.accessTokenExpirationTime?.minus(2.minutes.inWholeMilliseconds) if (refreshAt != null) { setTokenRefreshAlarm(context, refreshAt) } onComplete?.invoke(authState) } isInvalidGrant(exception) -> { Logger.log.log(Level.SEVERE, "Invalid grant: refresh cancelled, User must re-authenticate.", exception) cancelTokenRefreshAlarm(context) onComplete?.invoke(updatedAuthState) } else -> { Logger.log.log(Level.SEVERE, "Token refresh failed: unknown error, retrying in 5 minutes.") setTokenRefreshAlarm(context, System.currentTimeMillis() + 5.minutes.inWholeMilliseconds) } } } } catch (e: Exception) { Logger.log.log(Level.SEVERE, "Token refresh failed due to unexpected exception.", e) } finally { onComplete?.invoke(null) } } Loading @@ -199,7 +203,7 @@ object MurenaTokenManager { // Retrieves the Murena account settings for the currently active account, if available. // We only allow one murena account. fun getAccountSettings(context: Context): AccountSettings? { private fun getAccountSettings(context: Context): AccountSettings? { val accountType = context.getString(R.string.eelo_account_type) val account = AccountManager.get(context) .getAccountsByType(accountType) Loading Loading
app/src/main/java/com/nextcloud/android/sso/OidcTokenRefresher.kt +4 −2 Original line number Diff line number Diff line Loading @@ -66,7 +66,7 @@ object OidcTokenRefresher { account: Account?, getClientAuth: () -> ClientAuthentication?, readAuthState: () -> AuthState?, writeAuthState: (AuthState) -> Unit writeAuthState: ((AuthState) -> Unit)? = null ): AuthState? = synchronized(javaClass) { val authState = readAuthState() ?: return null // Use cached authState if possible Loading Loading @@ -97,7 +97,9 @@ object OidcTokenRefresher { authState.performActionWithFreshTokens( authService, clientAuth ) { accessToken, _, exception -> if (writeAuthState != null) { writeAuthState(authState) } when { accessToken != null -> { logger.info("Token refreshed for $account") Loading
app/src/main/kotlin/at/bitfire/davdroid/token/MurenaTokenManager.kt +40 −36 Original line number Diff line number Diff line Loading @@ -25,12 +25,12 @@ import android.app.PendingIntent import android.content.Context import android.content.Intent import at.bitfire.davdroid.BuildConfig import at.bitfire.davdroid.OpenIdUtils import at.bitfire.davdroid.R import at.bitfire.davdroid.log.Logger import at.bitfire.davdroid.network.HttpClient import at.bitfire.davdroid.settings.AccountSettings import at.bitfire.davdroid.ui.NetworkUtils import dagger.hilt.android.EntryPointAccessors import com.nextcloud.android.sso.OidcTokenRefresher import net.openid.appauth.AuthState import net.openid.appauth.AuthorizationException import java.text.SimpleDateFormat Loading Loading @@ -134,11 +134,6 @@ object MurenaTokenManager { // Refreshes the authentication token and updates stored credentials if successful. private fun refreshAuthToken(context: Context, onComplete: ((AuthState?) -> Unit)? = null) { try { val httpEntryPoint = EntryPointAccessors.fromApplication( context, HttpClient.HttpClientEntryPoint::class.java ) val authService = httpEntryPoint.authorizationService() val accountSettings = getAccountSettings(context) ?: run { Logger.log.warning("No account settings found during token refresh.") return Loading @@ -156,38 +151,47 @@ object MurenaTokenManager { return } val tokenRequest = authState.createTokenRefreshRequest() authService.performTokenRequest(tokenRequest) { response, exception -> when { response != null && exception == null -> { authState.update(response, null) accountSettings.credentials(credentials.copy(authState = authState)) Logger.log.info("Token refreshed for ${accountSettings.account.name}") val updatedAuthState: AuthState? = try { OidcTokenRefresher.refreshAuthState( context = context, account = accountSettings.account, getClientAuth = { OpenIdUtils.getClientAuthentication(credentials.clientSecret) }, readAuthState = { authState } ) } catch (e: AuthorizationException) { if (isInvalidGrant(e)) { Logger.log.log( Level.SEVERE, "Invalid grant: refresh cancelled, User must re-authenticate.", e ) cancelTokenRefreshAlarm(context) } else { Logger.log.log(Level.SEVERE, "Token refresh failed: $e, retrying in 5 minutes.") setTokenRefreshAlarm( context, System.currentTimeMillis() + 5.minutes.inWholeMilliseconds ) } onComplete?.invoke(null) null } if (updatedAuthState != null) { accountSettings.credentials(credentials.copy(authState = updatedAuthState)) Logger.log.info("Token refreshed for ${accountSettings.account}") // Schedule at least 2 minutes early for the new token. val refreshAt = authState.accessTokenExpirationTime?.minus(2.minutes.inWholeMilliseconds) val refreshAt = updatedAuthState.accessTokenExpirationTime?.minus(2.minutes.inWholeMilliseconds) if (refreshAt != null) { setTokenRefreshAlarm(context, refreshAt) } onComplete?.invoke(authState) } isInvalidGrant(exception) -> { Logger.log.log(Level.SEVERE, "Invalid grant: refresh cancelled, User must re-authenticate.", exception) cancelTokenRefreshAlarm(context) onComplete?.invoke(updatedAuthState) } else -> { Logger.log.log(Level.SEVERE, "Token refresh failed: unknown error, retrying in 5 minutes.") setTokenRefreshAlarm(context, System.currentTimeMillis() + 5.minutes.inWholeMilliseconds) } } } } catch (e: Exception) { Logger.log.log(Level.SEVERE, "Token refresh failed due to unexpected exception.", e) } finally { onComplete?.invoke(null) } } Loading @@ -199,7 +203,7 @@ object MurenaTokenManager { // Retrieves the Murena account settings for the currently active account, if available. // We only allow one murena account. fun getAccountSettings(context: Context): AccountSettings? { private fun getAccountSettings(context: Context): AccountSettings? { val accountType = context.getString(R.string.eelo_account_type) val account = AccountManager.get(context) .getAccountsByType(accountType) Loading