mirror of
https://github.com/owncloud/android-library.git
synced 2025-06-07 07:56:19 +00:00
add update authToken code to connectionValidator
This commit is contained in:
parent
cfd69987e9
commit
e27a968ddb
@ -1,31 +1,37 @@
|
||||
package com.owncloud.android.lib.common
|
||||
|
||||
import android.accounts.AccountManager
|
||||
import android.accounts.AccountsException
|
||||
import android.content.Context
|
||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentials
|
||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory
|
||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory.OwnCloudAnonymousCredentials
|
||||
import com.owncloud.android.lib.common.http.HttpConstants
|
||||
import com.owncloud.android.lib.common.http.methods.HttpBaseMethod
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult
|
||||
import com.owncloud.android.lib.resources.files.CheckPathExistenceRemoteOperation
|
||||
import com.owncloud.android.lib.resources.status.GetRemoteStatusOperation
|
||||
import com.owncloud.android.lib.resources.status.RemoteServerInfo
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils
|
||||
import timber.log.Timber
|
||||
import java.io.IOException
|
||||
import java.lang.Exception
|
||||
|
||||
class ConnectionValidator (
|
||||
val context: Context,
|
||||
val clearCookiesOnValidation: Boolean
|
||||
){
|
||||
|
||||
fun validate(baseClient: OwnCloudClient): Boolean {
|
||||
fun validate(baseClient: OwnCloudClient, singleSessionManager: SingleSessionManager): Boolean {
|
||||
try {
|
||||
var validationRetryCount = 0
|
||||
val client = OwnCloudClient(baseClient.baseUri, null, false)
|
||||
val client = OwnCloudClient(baseClient.baseUri, null, false, singleSessionManager)
|
||||
if (clearCookiesOnValidation) {
|
||||
client.clearCookies();
|
||||
} else {
|
||||
client.cookiesForBaseUri = baseClient.cookiesForBaseUri
|
||||
}
|
||||
|
||||
client.account = baseClient.account
|
||||
client.credentials = baseClient.credentials
|
||||
while (validationRetryCount < 5) {
|
||||
Timber.d("+++++++++++++++++++++++++++++++++++++ validationRetryCout %d", validationRetryCount)
|
||||
@ -40,7 +46,7 @@ class ConnectionValidator (
|
||||
}
|
||||
|
||||
// Skip the part where we try to check if we can access the parts where we have to be logged in... if we are not logged in
|
||||
if(baseClient.credentials !is OwnCloudCredentialsFactory.OwnCloudAnonymousCredentials) {
|
||||
if(baseClient.credentials !is OwnCloudAnonymousCredentials) {
|
||||
client.setFollowRedirects(false)
|
||||
val contentReply = canAccessRootFolder(client)
|
||||
if (contentReply.httpCode == HttpConstants.HTTP_OK) {
|
||||
@ -51,8 +57,8 @@ class ConnectionValidator (
|
||||
}
|
||||
} else {
|
||||
failCounter++
|
||||
if (contentReply.hashCode() == HttpConstants.HTTP_UNAUTHORIZED) {
|
||||
triggerAuthRefresh()
|
||||
if (contentReply.httpCode == HttpConstants.HTTP_UNAUTHORIZED) {
|
||||
checkUnauthorizedAccess(client, singleSessionManager, contentReply.httpCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -92,4 +98,89 @@ class ConnectionValidator (
|
||||
val checkPathExistenceRemoteOperation = CheckPathExistenceRemoteOperation("/", true)
|
||||
return checkPathExistenceRemoteOperation.execute(client)
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if credentials should be invalidated according the to the HTTPS status
|
||||
* of a network request just performed.
|
||||
*
|
||||
* @param httpStatusCode Result of the last request ran with the 'credentials' belows.
|
||||
* @return 'True' if credentials should and might be invalidated, 'false' if shouldn't or
|
||||
* cannot be invalidated with the given arguments.
|
||||
*/
|
||||
private fun shouldInvalidateAccountCredentials(credentials: OwnCloudCredentials, account: OwnCloudAccount, httpStatusCode: Int): Boolean {
|
||||
var shouldInvalidateAccountCredentials = httpStatusCode == HttpConstants.HTTP_UNAUTHORIZED
|
||||
shouldInvalidateAccountCredentials = shouldInvalidateAccountCredentials and // real credentials
|
||||
(credentials !is OwnCloudAnonymousCredentials)
|
||||
|
||||
// test if have all the needed to effectively invalidate ...
|
||||
shouldInvalidateAccountCredentials =
|
||||
shouldInvalidateAccountCredentials and (account.savedAccount != null)
|
||||
return shouldInvalidateAccountCredentials
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates credentials stored for the given account in the system [AccountManager] and in
|
||||
* current [SingleSessionManager.getDefaultSingleton] instance.
|
||||
*
|
||||
*
|
||||
* [.shouldInvalidateAccountCredentials] should be called first.
|
||||
*
|
||||
*/
|
||||
private fun invalidateAccountCredentials(account: OwnCloudAccount, credentials: OwnCloudCredentials) {
|
||||
val am = AccountManager.get(context)
|
||||
am.invalidateAuthToken(
|
||||
account.savedAccount.type,
|
||||
credentials.authToken
|
||||
)
|
||||
am.clearPassword(account.savedAccount) // being strict, only needed for Basic Auth credentials
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the status code of an execution and decides if should be repeated with fresh credentials.
|
||||
*
|
||||
*
|
||||
* Invalidates current credentials if the request failed as anauthorized.
|
||||
*
|
||||
*
|
||||
* Refresh current credentials if possible, and marks a retry.
|
||||
*
|
||||
* @param status
|
||||
* @param repeatCounter
|
||||
* @return
|
||||
*/
|
||||
private fun checkUnauthorizedAccess(client: OwnCloudClient, singleSessionManager: SingleSessionManager, status: Int): Boolean {
|
||||
var credentialsWereRefreshed = false
|
||||
val account = client.account
|
||||
val credentials = account.credentials
|
||||
if (shouldInvalidateAccountCredentials(credentials, account, status)) {
|
||||
invalidateAccountCredentials(account, credentials)
|
||||
if (credentials.authTokenCanBeRefreshed()) {
|
||||
try {
|
||||
account.loadCredentials(context)
|
||||
// if mAccount.getCredentials().length() == 0 --> refresh failed
|
||||
client.credentials = account.credentials
|
||||
credentialsWereRefreshed = true
|
||||
} catch (e: AccountsException) {
|
||||
Timber.e(
|
||||
e, "Error while trying to refresh auth token for %s\ntrace: %s",
|
||||
account.savedAccount.name,
|
||||
ExceptionUtils.getStackTrace(e)
|
||||
)
|
||||
} catch (e: IOException) {
|
||||
Timber.e(
|
||||
e, "Error while trying to refresh auth token for %s\ntrace: %s",
|
||||
account.savedAccount.name,
|
||||
ExceptionUtils.getStackTrace(e)
|
||||
)
|
||||
}
|
||||
if (!credentialsWereRefreshed) {
|
||||
// if credentials are not refreshed, client must be removed
|
||||
// from the OwnCloudClientManager to prevent it is reused once and again
|
||||
singleSessionManager.removeClientFor(account)
|
||||
}
|
||||
}
|
||||
// else: onExecute will finish with status 401
|
||||
}
|
||||
return credentialsWereRefreshed
|
||||
}
|
||||
}
|
@ -59,7 +59,6 @@ public class OwnCloudClient extends HttpClient {
|
||||
public static final String STATUS_PATH = "/status.php";
|
||||
private static final String WEBDAV_UPLOADS_PATH_4_0 = "/remote.php/dav/uploads/";
|
||||
private static final int MAX_REDIRECTIONS_COUNT = 5;
|
||||
private static final int MAX_REPEAT_COUNT_WITH_FRESH_CREDENTIALS = 1;
|
||||
|
||||
private static int sIntanceCounter = 0;
|
||||
private OwnCloudCredentials mCredentials = null;
|
||||
@ -80,12 +79,13 @@ public class OwnCloudClient extends HttpClient {
|
||||
|
||||
private boolean mFollowRedirects = false;
|
||||
|
||||
public OwnCloudClient(Uri baseUri, ConnectionValidator connectionValidator, boolean synchronizeRequests) {
|
||||
public OwnCloudClient(Uri baseUri, ConnectionValidator connectionValidator, boolean synchronizeRequests, SingleSessionManager singleSessionManager) {
|
||||
if (baseUri == null) {
|
||||
throw new IllegalArgumentException("Parameter 'baseUri' cannot be NULL");
|
||||
}
|
||||
mBaseUri = baseUri;
|
||||
mSynchronizeRequests = synchronizeRequests;
|
||||
mSingleSessionManager = singleSessionManager;
|
||||
|
||||
mInstanceNumber = sIntanceCounter++;
|
||||
Timber.d("#" + mInstanceNumber + "Creating OwnCloudClient");
|
||||
@ -134,8 +134,10 @@ public class OwnCloudClient extends HttpClient {
|
||||
stacklog(status, method);
|
||||
|
||||
if (mConnectionValidator != null &&
|
||||
status == HttpConstants.HTTP_MOVED_TEMPORARILY) {
|
||||
retry = mConnectionValidator.validate(this); // retry on success fail on no success
|
||||
(status == HttpConstants.HTTP_MOVED_TEMPORARILY ||
|
||||
(!(mCredentials instanceof OwnCloudAnonymousCredentials) &&
|
||||
status == HttpConstants.HTTP_UNAUTHORIZED))) {
|
||||
retry = mConnectionValidator.validate(this, mSingleSessionManager); // retry on success fail on no success
|
||||
} else if (mFollowRedirects) {
|
||||
status = followRedirection(method).getLastStatus();
|
||||
}
|
||||
@ -145,8 +147,8 @@ public class OwnCloudClient extends HttpClient {
|
||||
if (repeatWithFreshCredentials) {
|
||||
repeatCounter++;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
} while (retry);
|
||||
|
||||
return status;
|
||||
@ -163,6 +165,7 @@ public class OwnCloudClient extends HttpClient {
|
||||
"\nMethod: " + method.toString() +
|
||||
"\nUrl: " + method.getHttpUrl() +
|
||||
"\nCookeis: " + getCookiesForBaseUri().toString() +
|
||||
"\nCredentials type: " + mCredentials.getClass().toString() +
|
||||
"\ntrace: " + ExceptionUtils.getStackTrace(e) +
|
||||
"---------------------------");
|
||||
}
|
||||
@ -336,8 +339,8 @@ public class OwnCloudClient extends HttpClient {
|
||||
}
|
||||
|
||||
public List<Cookie> getCookiesForBaseUri() {
|
||||
return getOkHttpClient().cookieJar().loadForRequest(
|
||||
HttpUrl.parse(mBaseUri.toString()));
|
||||
return getOkHttpClient().cookieJar().loadForRequest(
|
||||
HttpUrl.parse(mBaseUri.toString()));
|
||||
}
|
||||
|
||||
public OwnCloudVersion getOwnCloudVersion() {
|
||||
@ -374,7 +377,7 @@ public class OwnCloudClient extends HttpClient {
|
||||
invalidateAccountCredentials();
|
||||
|
||||
if (getCredentials().authTokenCanBeRefreshed() &&
|
||||
repeatCounter < MAX_REPEAT_COUNT_WITH_FRESH_CREDENTIALS) {
|
||||
repeatCounter < 1) {
|
||||
try {
|
||||
mAccount.loadCredentials(getContext());
|
||||
// if mAccount.getCredentials().length() == 0 --> refresh failed
|
||||
|
@ -77,9 +77,8 @@ public class SingleSessionManager {
|
||||
sUserAgent = userAgent;
|
||||
}
|
||||
|
||||
private static OwnCloudClient createOwnCloudClient(Uri uri, Context context, boolean followRedirects, ConnectionValidator connectionValidator) {
|
||||
OwnCloudClient client = new OwnCloudClient(uri, connectionValidator, true);
|
||||
client.setFollowRedirects(followRedirects);
|
||||
private static OwnCloudClient createOwnCloudClient(Uri uri, Context context, ConnectionValidator connectionValidator, SingleSessionManager singleSessionManager) {
|
||||
OwnCloudClient client = new OwnCloudClient(uri, connectionValidator, true, singleSessionManager);
|
||||
HttpClient.setContext(context);
|
||||
|
||||
return client;
|
||||
@ -132,8 +131,8 @@ public class SingleSessionManager {
|
||||
client = createOwnCloudClient(
|
||||
account.getBaseUri(),
|
||||
context.getApplicationContext(),
|
||||
true,
|
||||
connectionValidator); // TODO remove dependency on OwnCloudClientFactory
|
||||
connectionValidator,
|
||||
this);
|
||||
|
||||
//the next two lines are a hack because okHttpclient is used as a singleton instead of being an
|
||||
//injected instance that can be deleted when required
|
||||
|
Loading…
x
Reference in New Issue
Block a user