From: masensio Date: Fri, 23 Aug 2013 11:42:07 +0000 (+0200) Subject: Merge branch 'saml_based_federated_single_sign_on' into saml_based_federated_single_s... X-Git-Tag: oc-android-1.4.6~17^2~6^2 X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/commitdiff_plain/71347b48a089a677d7799628abf4056bbd780d71?hp=3072a29730c5d3af409a7f0a0e07598caf3b36c3 Merge branch 'saml_based_federated_single_sign_on' into saml_based_federated_single_sign_on_expired Conflicts: src/com/owncloud/android/ui/dialog/SamlWebViewDialog.java --- diff --git a/res/layout-land/account_setup.xml b/res/layout-land/account_setup.xml index 73da2b4b..2ae4b33f 100644 --- a/res/layout-land/account_setup.xml +++ b/res/layout-land/account_setup.xml @@ -64,7 +64,14 @@ android:onClick="onRefreshClick" android:text="@string/auth_check_server" android:visibility="gone" /> - + + + Ruta errónea Error interno en el servidor, código %1$d Estado inesperado; por favor, introduzca la URL del servidor de nuevo - Su autorización ha expirado.\nPor favor, autorice de nuevo + Su autorización ha expirado. Por favor, autorice de nuevo Por favor, introduzca la contraseña actual. La aplicación finalizó inesperadamente. ¿Desea enviar un reporte de error? Enviar reporte diff --git a/res/values/strings.xml b/res/values/strings.xml index 4e375d03..0872084a 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -191,6 +191,7 @@ Malformed server configuration It seems that your server instance is not correctly configured. Contact your administrator for more details. An account for the same user and server already exists in the device + The entered user does not match the user of this account Unknown error occurred! An unknown error occurred. Please contact support and include logs from your device. Couldn\'t find host @@ -210,8 +211,9 @@ Wrong path given Internal server error, code %1$d Unexpected state; please, enter the server URL again - Your authorization expired.\nPlease, authorize again + Your authorization expired. Please, authorize again Please, enter the current password + Your session expired. Please connect again Connecting to authentication server… Follow instructions above to get authenticated The server does not support this authentication method diff --git a/src/com/owncloud/android/authentication/AuthenticatorActivity.java b/src/com/owncloud/android/authentication/AuthenticatorActivity.java index 4fd50c7f..9ba0970c 100644 --- a/src/com/owncloud/android/authentication/AuthenticatorActivity.java +++ b/src/com/owncloud/android/authentication/AuthenticatorActivity.java @@ -18,8 +18,6 @@ package com.owncloud.android.authentication; -import java.net.URLDecoder; - import android.accounts.Account; import android.accounts.AccountManager; import android.app.AlertDialog; @@ -51,7 +49,6 @@ import android.widget.CheckBox; import android.widget.EditText; import android.widget.TextView; import android.widget.TextView.OnEditorActionListener; -import android.widget.Toast; import com.actionbarsherlock.app.SherlockDialogFragment; import com.owncloud.android.Log_OC; @@ -89,6 +86,8 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList public static final String EXTRA_ACTION = "ACTION"; public static final String EXTRA_ENFORCED_UPDATE = "ENFORCE_UPDATE"; + private static final String KEY_AUTH_MESSAGE_VISIBILITY = "AUTH_MESSAGE_VISIBILITY"; + private static final String KEY_AUTH_MESSAGE_TEXT = "AUTH_MESSAGE_TEXT"; private static final String KEY_HOST_URL_TEXT = "HOST_URL_TEXT"; private static final String KEY_OC_VERSION = "OC_VERSION"; private static final String KEY_ACCOUNT = "ACCOUNT"; @@ -122,7 +121,8 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList private String mHostBaseUrl; private OwnCloudVersion mDiscoveredVersion; - private int mServerStatusText, mServerStatusIcon; + private String mAuthMessageText; + private int mAuthMessageVisibility, mServerStatusText, mServerStatusIcon; private boolean mServerIsChecked, mServerIsValid, mIsSslConn; private int mAuthStatusText, mAuthStatusIcon; private TextView mAuthStatusLayout; @@ -140,6 +140,8 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList private byte mAction; private Account mAccount; + private TextView mAuthMessage; + private EditText mHostUrlInput; private boolean mHostUrlInputEnabled; private View mRefreshButton; @@ -173,6 +175,7 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList /// set view and get references to view elements setContentView(R.layout.account_setup); + mAuthMessage = (TextView) findViewById(R.id.auth_message); mHostUrlInput = (EditText) findViewById(R.id.hostUrlInput); mHostUrlInput.setText(getString(R.string.server_url)); // valid although R.string.server_url is an empty string mUsernameInput = (EditText) findViewById(R.id.account_username); @@ -213,6 +216,7 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList if (savedInstanceState == null) { /// connection state and info + mAuthMessageVisibility = View.GONE; mServerStatusText = mServerStatusIcon = 0; mServerIsValid = false; mServerIsChecked = false; @@ -228,6 +232,8 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList } mHostBaseUrl = normalizeUrl(mAccountMgr.getUserData(mAccount, AccountAuthenticator.KEY_OC_BASE_URL)); mHostUrlInput.setText(mHostBaseUrl); + String userName = mAccount.name.substring(0, mAccount.name.lastIndexOf('@')); + mUsernameInput.setText(userName); } initAuthorizationMethod(); // checks intent and setup.xml to determine mCurrentAuthorizationMethod mJustCreated = true; @@ -238,6 +244,8 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList } else { /// connection state and info + mAuthMessageVisibility = savedInstanceState.getInt(KEY_AUTH_MESSAGE_VISIBILITY); + mAuthMessageText = savedInstanceState.getString(KEY_AUTH_MESSAGE_TEXT); mServerIsValid = savedInstanceState.getBoolean(KEY_SERVER_VALID); mServerIsChecked = savedInstanceState.getBoolean(KEY_SERVER_CHECKED); mServerStatusText = savedInstanceState.getInt(KEY_SERVER_STATUS_TEXT); @@ -275,6 +283,12 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList } + if (mAuthMessageVisibility== View.VISIBLE) { + showAuthMessage(mAuthMessageText); + } + else { + hideAuthMessage(); + } adaptViewAccordingToAuthenticationMethod(); showServerStatus(); showAuthStatus(); @@ -387,6 +401,8 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList super.onSaveInstanceState(outState); /// connection state and info + outState.putInt(KEY_AUTH_MESSAGE_VISIBILITY, mAuthMessage.getVisibility()); + outState.putString(KEY_AUTH_MESSAGE_TEXT, mAuthMessage.getText().toString()); outState.putInt(KEY_SERVER_STATUS_TEXT, mServerStatusText); outState.putInt(KEY_SERVER_STATUS_ICON, mServerStatusIcon); outState.putBoolean(KEY_SERVER_VALID, mServerIsValid); @@ -441,10 +457,16 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList protected void onResume() { super.onResume(); if (mAction == ACTION_UPDATE_TOKEN && mJustCreated && getIntent().getBooleanExtra(EXTRA_ENFORCED_UPDATE, false)) { - if (mOAuth2Check.isChecked()) - Toast.makeText(this, R.string.auth_expired_oauth_token_toast, Toast.LENGTH_LONG).show(); - else - Toast.makeText(this, R.string.auth_expired_basic_auth_toast, Toast.LENGTH_LONG).show(); + if (AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN.equals(mCurrentAuthTokenType)) { + //Toast.makeText(this, R.string.auth_expired_oauth_token_toast, Toast.LENGTH_LONG).show(); + showAuthMessage(getString(R.string.auth_expired_oauth_token_toast)); + } else if (AccountAuthenticator.AUTH_TOKEN_TYPE_SAML_WEB_SSO_SESSION_COOKIE.equals(mCurrentAuthTokenType)) { + //Toast.makeText(this, R.string.auth_expired_saml_sso_token_toast, Toast.LENGTH_LONG).show(); + showAuthMessage(getString(R.string.auth_expired_saml_sso_token_toast)); + } else { + //Toast.makeText(this, R.string.auth_expired_basic_auth_toast, Toast.LENGTH_LONG).show(); + showAuthMessage(getString(R.string.auth_expired_basic_auth_toast)); + } } if (mNewCapturedUriFromOAuth2Redirection != null) { @@ -638,6 +660,7 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList return; } + hideAuthMessage(); if (AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN.equals(mCurrentAuthTokenType)) { startOauthorization(); } else if (AccountAuthenticator.AUTH_TOKEN_TYPE_SAML_WEB_SSO_SESSION_COOKIE.equals(mCurrentAuthTokenType)) { @@ -751,7 +774,7 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList // NOTHING TO DO ; can't find out what situation that leads to the exception in this code, but user logs signal that it happens } - if (result.isTemporalRedirection() || result.isIdPRedirection()) { + if (result.isTemporalRedirection() && result.isIdPRedirection()) { String url = result.getRedirectedLocation(); String targetUrl = mHostBaseUrl + AccountUtils.getWebdavPath(mDiscoveredVersion, mCurrentAuthTokenType); @@ -996,6 +1019,9 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList case ACCOUNT_NOT_NEW: mAuthStatusText = R.string.auth_account_not_new; break; + case ACCOUNT_NOT_THE_SAME: + mAuthStatusText = R.string.auth_account_not_the_same; + break; case UNHANDLED_HTTP_CODE: case UNKNOWN_ERROR: mAuthStatusText = R.string.auth_unknown_error_title; @@ -1060,12 +1086,12 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList if (result.isSuccess()) { Log_OC.d(TAG, "Successful access - time to save the account"); - boolean success = true; + boolean success = false; if (mAction == ACTION_CREATE) { success = createAccount(); } else { - updateToken(); + success = updateToken(); } if (success) { @@ -1111,7 +1137,7 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList * Sets the proper response to get that the Account Authenticator that started this activity saves * a new authorization token for mAccount. */ - private void updateToken() { + private boolean updateToken() { Bundle response = new Bundle(); response.putString(AccountManager.KEY_ACCOUNT_NAME, mAccount.name); response.putString(AccountManager.KEY_ACCOUNT_TYPE, mAccount.type); @@ -1122,6 +1148,17 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList mAccountMgr.setAuthToken(mAccount, mCurrentAuthTokenType, mAuthToken); } else if (AccountAuthenticator.AUTH_TOKEN_TYPE_SAML_WEB_SSO_SESSION_COOKIE.equals(mCurrentAuthTokenType)) { + String username = getUserNameForSamlSso(); + if (!mUsernameInput.getText().toString().equals(username)) { + // fail - not a new account, but an existing one; disallow + RemoteOperationResult result = new RemoteOperationResult(ResultCode.ACCOUNT_NOT_THE_SAME); + updateAuthStatusIconAndText(result); + showAuthStatus(); + Log_OC.d(TAG, result.getLogMessage()); + + return false; + } + response.putString(AccountManager.KEY_AUTHTOKEN, mAuthToken); // the next line is necessary; by now, notifications are calling directly to the AuthenticatorActivity to update, without AccountManager intervention mAccountMgr.setAuthToken(mAccount, mCurrentAuthTokenType, mAuthToken); @@ -1131,6 +1168,8 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList mAccountMgr.setPassword(mAccount, mPasswordInput.getText().toString()); } setAccountAuthenticatorResult(response); + + return true; } @@ -1167,7 +1206,6 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList Log_OC.d(TAG, result.getLogMessage()); return false; - } else { if (isOAuth || isSaml) { @@ -1212,6 +1250,10 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList Bundle bundle = new Bundle(); bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true); ContentResolver.requestSync(mAccount, AccountAuthenticator.AUTHORITY, bundle); + syncAccount(); +// Bundle bundle = new Bundle(); +// bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true); +// ContentResolver.requestSync(mAccount, AccountAuthenticator.AUTHORITY, bundle); return true; } } @@ -1531,12 +1573,12 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList if (sessionCookie != null && sessionCookie.length() > 0) { Log_OC.d(TAG, "Successful SSO - time to save the account"); mAuthToken = sessionCookie; - boolean success = true; + boolean success = false; if (mAction == ACTION_CREATE) { success = createAccount(); } else { - updateToken(); + success = updateToken(); } if (success) { finish(); @@ -1569,5 +1611,24 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList } + /** Show auth_message + * + * @param message + */ + private void showAuthMessage(String message) { + mAuthMessage.setVisibility(View.VISIBLE); + mAuthMessage.setText(message); + } + + private void hideAuthMessage() { + mAuthMessage.setVisibility(View.GONE); + } + + private void syncAccount(){ + /// immediately request for the synchronization of the new account + Bundle bundle = new Bundle(); + bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true); + ContentResolver.requestSync(mAccount, AccountAuthenticator.AUTHORITY, bundle); + } } diff --git a/src/com/owncloud/android/files/services/FileDownloader.java b/src/com/owncloud/android/files/services/FileDownloader.java index 02a8a452..0ae09d7b 100644 --- a/src/com/owncloud/android/files/services/FileDownloader.java +++ b/src/com/owncloud/android/files/services/FileDownloader.java @@ -28,6 +28,7 @@ import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import com.owncloud.android.authentication.AccountAuthenticator; import com.owncloud.android.authentication.AuthenticatorActivity; import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; @@ -463,7 +464,9 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis int contentId = (downloadResult.isSuccess()) ? R.string.downloader_download_succeeded_content : R.string.downloader_download_failed_content; Notification finalNotification = new Notification(R.drawable.icon, getString(tickerId), System.currentTimeMillis()); finalNotification.flags |= Notification.FLAG_AUTO_CANCEL; - boolean needsToUpdateCredentials = (downloadResult.getCode() == ResultCode.UNAUTHORIZED); + boolean needsToUpdateCredentials = (downloadResult.getCode() == ResultCode.UNAUTHORIZED || + (downloadResult.isTemporalRedirection() && downloadResult.isIdPRedirection() + && AccountAuthenticator.AUTH_TOKEN_TYPE_SAML_WEB_SSO_SESSION_COOKIE.equals(mDownloadClient.getAuthTokenType()))); if (needsToUpdateCredentials) { // let the user update credentials with one click Intent updateAccountCredentials = new Intent(this, AuthenticatorActivity.class); diff --git a/src/com/owncloud/android/files/services/FileUploader.java b/src/com/owncloud/android/files/services/FileUploader.java index e9f445a0..2356c439 100644 --- a/src/com/owncloud/android/files/services/FileUploader.java +++ b/src/com/owncloud/android/files/services/FileUploader.java @@ -579,7 +579,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe mUploadClient.exhaustResponse(propfind.getResponseBodyAsStream()); } - result = new RemoteOperationResult(isMultiStatus, status); + result = new RemoteOperationResult(isMultiStatus, status, propfind.getResponseHeaders()); Log_OC.i(TAG, "Update: synchronizing properties for uploaded " + mCurrentUpload.getRemotePath() + ": " + result.getLogMessage()); @@ -791,7 +791,12 @@ public class FileUploader extends Service implements OnDatatransferProgressListe Notification finalNotification = new Notification(R.drawable.icon, getString(R.string.uploader_upload_failed_ticker), System.currentTimeMillis()); finalNotification.flags |= Notification.FLAG_AUTO_CANCEL; - if (uploadResult.getCode() == ResultCode.UNAUTHORIZED) { + String content = null; + + boolean needsToUpdateCredentials = (uploadResult.getCode() == ResultCode.UNAUTHORIZED || + (uploadResult.isTemporalRedirection() && uploadResult.isIdPRedirection() && + AccountAuthenticator.AUTH_TOKEN_TYPE_SAML_WEB_SSO_SESSION_COOKIE.equals(mUploadClient.getAuthTokenType()))); + if (needsToUpdateCredentials) { // let the user update credentials with one click Intent updateAccountCredentials = new Intent(this, AuthenticatorActivity.class); updateAccountCredentials.putExtra(AuthenticatorActivity.EXTRA_ACCOUNT, upload.getAccount()); @@ -801,62 +806,65 @@ public class FileUploader extends Service implements OnDatatransferProgressListe updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); updateAccountCredentials.addFlags(Intent.FLAG_FROM_BACKGROUND); finalNotification.contentIntent = PendingIntent.getActivity(this, (int)System.currentTimeMillis(), updateAccountCredentials, PendingIntent.FLAG_ONE_SHOT); + content = String.format(getString(R.string.uploader_upload_failed_content_single), upload.getFileName()); + finalNotification.setLatestEventInfo(getApplicationContext(), + getString(R.string.uploader_upload_failed_ticker), content, finalNotification.contentIntent); mUploadClient = null; // grant that future retries on the same account will get the fresh credentials } else { // TODO put something smart in the contentIntent below - finalNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(), (int)System.currentTimeMillis(), new Intent(), 0); - } + // finalNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(), (int)System.currentTimeMillis(), new Intent(), 0); + //} - String content = null; - if (uploadResult.getCode() == ResultCode.LOCAL_STORAGE_FULL - || uploadResult.getCode() == ResultCode.LOCAL_STORAGE_NOT_COPIED) { - // TODO we need a class to provide error messages for the users - // from a RemoteOperationResult and a RemoteOperation - content = String.format(getString(R.string.error__upload__local_file_not_copied), upload.getFileName(), - getString(R.string.app_name)); - } else if (uploadResult.getCode() == ResultCode.QUOTA_EXCEEDED) { - content = getString(R.string.failed_upload_quota_exceeded_text); - } else { - content = String - .format(getString(R.string.uploader_upload_failed_content_single), upload.getFileName()); - } + if (uploadResult.getCode() == ResultCode.LOCAL_STORAGE_FULL + || uploadResult.getCode() == ResultCode.LOCAL_STORAGE_NOT_COPIED) { + // TODO we need a class to provide error messages for the users + // from a RemoteOperationResult and a RemoteOperation + content = String.format(getString(R.string.error__upload__local_file_not_copied), upload.getFileName(), + getString(R.string.app_name)); + } else if (uploadResult.getCode() == ResultCode.QUOTA_EXCEEDED) { + content = getString(R.string.failed_upload_quota_exceeded_text); + } else { + content = String + .format(getString(R.string.uploader_upload_failed_content_single), upload.getFileName()); + } - // we add only for instant-uploads the InstantUploadActivity and the - // db entry - Intent detailUploadIntent = null; - if (upload.isInstant() && InstantUploadActivity.IS_ENABLED) { - detailUploadIntent = new Intent(this, InstantUploadActivity.class); - detailUploadIntent.putExtra(FileUploader.KEY_ACCOUNT, upload.getAccount()); - } else { - detailUploadIntent = new Intent(this, FailedUploadActivity.class); - detailUploadIntent.putExtra(FailedUploadActivity.MESSAGE, content); - } - finalNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(), - (int) System.currentTimeMillis(), detailUploadIntent, PendingIntent.FLAG_UPDATE_CURRENT - | PendingIntent.FLAG_ONE_SHOT); - - if (upload.isInstant()) { - DbHandler db = null; - try { - db = new DbHandler(this.getBaseContext()); - String message = uploadResult.getLogMessage() + " errorCode: " + uploadResult.getCode(); - Log_OC.e(TAG, message + " Http-Code: " + uploadResult.getHttpCode()); - if (uploadResult.getCode() == ResultCode.QUOTA_EXCEEDED) { - message = getString(R.string.failed_upload_quota_exceeded_text); - } - if (db.updateFileState(upload.getOriginalStoragePath(), DbHandler.UPLOAD_STATUS_UPLOAD_FAILED, - message) == 0) { - db.putFileForLater(upload.getOriginalStoragePath(), upload.getAccount().name, message); - } - } finally { - if (db != null) { - db.close(); + // we add only for instant-uploads the InstantUploadActivity and the + // db entry + Intent detailUploadIntent = null; + if (upload.isInstant() && InstantUploadActivity.IS_ENABLED) { + detailUploadIntent = new Intent(this, InstantUploadActivity.class); + detailUploadIntent.putExtra(FileUploader.KEY_ACCOUNT, upload.getAccount()); + } else { + detailUploadIntent = new Intent(this, FailedUploadActivity.class); + detailUploadIntent.putExtra(FailedUploadActivity.MESSAGE, content); + } + finalNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(), + (int) System.currentTimeMillis(), detailUploadIntent, PendingIntent.FLAG_UPDATE_CURRENT + | PendingIntent.FLAG_ONE_SHOT); + + if (upload.isInstant()) { + DbHandler db = null; + try { + db = new DbHandler(this.getBaseContext()); + String message = uploadResult.getLogMessage() + " errorCode: " + uploadResult.getCode(); + Log_OC.e(TAG, message + " Http-Code: " + uploadResult.getHttpCode()); + if (uploadResult.getCode() == ResultCode.QUOTA_EXCEEDED) { + message = getString(R.string.failed_upload_quota_exceeded_text); + } + if (db.updateFileState(upload.getOriginalStoragePath(), DbHandler.UPLOAD_STATUS_UPLOAD_FAILED, + message) == 0) { + db.putFileForLater(upload.getOriginalStoragePath(), upload.getAccount().name, message); + } + } finally { + if (db != null) { + db.close(); + } } } } finalNotification.setLatestEventInfo(getApplicationContext(), getString(R.string.uploader_upload_failed_ticker), content, finalNotification.contentIntent); - + mNotificationManager.notify(R.string.uploader_upload_failed_ticker, finalNotification); } diff --git a/src/com/owncloud/android/network/OwnCloudClientUtils.java b/src/com/owncloud/android/network/OwnCloudClientUtils.java index 17abf6f8..75aed4ac 100644 --- a/src/com/owncloud/android/network/OwnCloudClientUtils.java +++ b/src/com/owncloud/android/network/OwnCloudClientUtils.java @@ -32,6 +32,7 @@ import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; +import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.protocol.Protocol; import org.apache.http.conn.ssl.BrowserCompatHostnameVerifier; import org.apache.http.conn.ssl.X509HostnameVerifier; @@ -90,13 +91,15 @@ public class OwnCloudClientUtils { //Log_OC.d(TAG, "Creating WebdavClient associated to " + account.name); Uri uri = Uri.parse(AccountUtils.constructFullURLForAccount(appContext, account)); - WebdavClient client = createOwnCloudClient(uri, appContext, true); AccountManager am = AccountManager.get(appContext); - if (am.getUserData(account, AccountAuthenticator.KEY_SUPPORTS_OAUTH2) != null) { // TODO avoid a call to getUserData here + boolean isOauth2 = am.getUserData(account, AccountAuthenticator.KEY_SUPPORTS_OAUTH2) != null; // TODO avoid calling to getUserData here + boolean isSamlSso = am.getUserData(account, AccountAuthenticator.KEY_SUPPORTS_SAML_WEB_SSO) != null; + WebdavClient client = createOwnCloudClient(uri, appContext, !isSamlSso); + if (isOauth2) { String accessToken = am.blockingGetAuthToken(account, AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN, false); client.setBearerCredentials(accessToken); // TODO not assume that the access token is a bearer token - } else if (am.getUserData(account, AccountAuthenticator.KEY_SUPPORTS_SAML_WEB_SSO) != null) { // TODO avoid a call to getUserData here + } else if (isSamlSso) { // TODO avoid a call to getUserData here String accessToken = am.blockingGetAuthToken(account, AccountAuthenticator.AUTH_TOKEN_TYPE_SAML_WEB_SSO_SESSION_COOKIE, false); client.setSsoSessionCookie(accessToken); @@ -113,16 +116,19 @@ public class OwnCloudClientUtils { public static WebdavClient createOwnCloudClient (Account account, Context appContext, Activity currentActivity) throws OperationCanceledException, AuthenticatorException, IOException, AccountNotFoundException { Uri uri = Uri.parse(AccountUtils.constructFullURLForAccount(appContext, account)); - WebdavClient client = createOwnCloudClient(uri, appContext, true); AccountManager am = AccountManager.get(appContext); - if (am.getUserData(account, AccountAuthenticator.KEY_SUPPORTS_OAUTH2) != null) { // TODO avoid a call to getUserData here + boolean isOauth2 = am.getUserData(account, AccountAuthenticator.KEY_SUPPORTS_OAUTH2) != null; // TODO avoid calling to getUserData here + boolean isSamlSso = am.getUserData(account, AccountAuthenticator.KEY_SUPPORTS_SAML_WEB_SSO) != null; + WebdavClient client = createOwnCloudClient(uri, appContext, !isSamlSso); + + if (isOauth2) { // TODO avoid a call to getUserData here AccountManagerFuture future = am.getAuthToken(account, AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN, null, currentActivity, null, null); Bundle result = future.getResult(); String accessToken = result.getString(AccountManager.KEY_AUTHTOKEN); if (accessToken == null) throw new AuthenticatorException("WTF!"); client.setBearerCredentials(accessToken); // TODO not assume that the access token is a bearer token - } else if (am.getUserData(account, AccountAuthenticator.KEY_SUPPORTS_SAML_WEB_SSO) != null) { // TODO avoid a call to getUserData here + } else if (isSamlSso) { // TODO avoid a call to getUserData here AccountManagerFuture future = am.getAuthToken(account, AccountAuthenticator.AUTH_TOKEN_TYPE_SAML_WEB_SSO_SESSION_COOKIE, null, currentActivity, null, null); Bundle result = future.getResult(); String accessToken = result.getString(AccountManager.KEY_AUTHTOKEN); diff --git a/src/com/owncloud/android/operations/ChunkedUploadFileOperation.java b/src/com/owncloud/android/operations/ChunkedUploadFileOperation.java index 697c154e..02e1ad04 100644 --- a/src/com/owncloud/android/operations/ChunkedUploadFileOperation.java +++ b/src/com/owncloud/android/operations/ChunkedUploadFileOperation.java @@ -68,6 +68,9 @@ public class ChunkedUploadFileOperation extends UploadFileOperation { String uriPrefix = client.getBaseUri() + WebdavUtils.encodePath(getRemotePath()) + "-chunking-" + Math.abs((new Random()).nextInt(9000)+1000) + "-" ; long chunkCount = (long) Math.ceil((double)file.length() / CHUNK_SIZE); for (int chunkIndex = 0; chunkIndex < chunkCount ; chunkIndex++, offset += CHUNK_SIZE) { + if (mPutMethod != null) { + mPutMethod.releaseConnection(); // let the connection available for other methods + } mPutMethod = new PutMethod(uriPrefix + chunkCount + "-" + chunkIndex); mPutMethod.addRequestHeader(OC_CHUNKED_HEADER, OC_CHUNKED_HEADER); ((ChunkFromFileChannelRequestEntity)mEntity).setOffset(offset); diff --git a/src/com/owncloud/android/operations/CreateFolderOperation.java b/src/com/owncloud/android/operations/CreateFolderOperation.java index 03c6868c..1a38cdbf 100644 --- a/src/com/owncloud/android/operations/CreateFolderOperation.java +++ b/src/com/owncloud/android/operations/CreateFolderOperation.java @@ -77,7 +77,7 @@ public class CreateFolderOperation extends RemoteOperation { mStorageManager.saveFile(newDir); } - result = new RemoteOperationResult(mkcol.succeeded(), status); + result = new RemoteOperationResult(mkcol.succeeded(), status, mkcol.getResponseHeaders()); Log_OC.d(TAG, "Create directory " + mRemotePath + ": " + result.getLogMessage()); client.exhaustResponse(mkcol.getResponseBodyAsStream()); diff --git a/src/com/owncloud/android/operations/DownloadFileOperation.java b/src/com/owncloud/android/operations/DownloadFileOperation.java index 5745b973..02098b81 100644 --- a/src/com/owncloud/android/operations/DownloadFileOperation.java +++ b/src/com/owncloud/android/operations/DownloadFileOperation.java @@ -58,6 +58,7 @@ public class DownloadFileOperation extends RemoteOperation { private Set mDataTransferListeners = new HashSet(); private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false); private long mModificationTimestamp = 0; + private GetMethod mGet; public DownloadFileOperation(Account account, OCFile file) { @@ -154,7 +155,7 @@ public class DownloadFileOperation extends RemoteOperation { if (!moved) result = new RemoteOperationResult(RemoteOperationResult.ResultCode.LOCAL_STORAGE_NOT_MOVED); else - result = new RemoteOperationResult(isSuccess(status), status); + result = new RemoteOperationResult(isSuccess(status), status, (mGet != null ? mGet.getResponseHeaders() : null)); Log_OC.i(TAG, "Download of " + mFile.getRemotePath() + " to " + getSavePath() + ": " + result.getLogMessage()); } catch (Exception e) { @@ -174,15 +175,15 @@ public class DownloadFileOperation extends RemoteOperation { protected int downloadFile(WebdavClient client, File targetFile) throws HttpException, IOException, OperationCancelledException { int status = -1; boolean savedFile = false; - GetMethod get = new GetMethod(client.getBaseUri() + WebdavUtils.encodePath(mFile.getRemotePath())); + mGet = new GetMethod(client.getBaseUri() + WebdavUtils.encodePath(mFile.getRemotePath())); Iterator it = null; FileOutputStream fos = null; try { - status = client.executeMethod(get); + status = client.executeMethod(mGet); if (isSuccess(status)) { targetFile.createNewFile(); - BufferedInputStream bis = new BufferedInputStream(get.getResponseBodyAsStream()); + BufferedInputStream bis = new BufferedInputStream(mGet.getResponseBodyAsStream()); fos = new FileOutputStream(targetFile); long transferred = 0; @@ -191,7 +192,7 @@ public class DownloadFileOperation extends RemoteOperation { while ((readResult = bis.read(bytes)) != -1) { synchronized(mCancellationRequested) { if (mCancellationRequested.get()) { - get.abort(); + mGet.abort(); throw new OperationCancelledException(); } } @@ -205,14 +206,14 @@ public class DownloadFileOperation extends RemoteOperation { } } savedFile = true; - Header modificationTime = get.getResponseHeader("Last-Modified"); + Header modificationTime = mGet.getResponseHeader("Last-Modified"); if (modificationTime != null) { Date d = WebdavUtils.parseResponseDate((String) modificationTime.getValue()); mModificationTimestamp = (d != null) ? d.getTime() : 0; } } else { - client.exhaustResponse(get.getResponseBodyAsStream()); + client.exhaustResponse(mGet.getResponseBodyAsStream()); } } finally { @@ -220,7 +221,7 @@ public class DownloadFileOperation extends RemoteOperation { if (!savedFile && targetFile.exists()) { targetFile.delete(); } - get.releaseConnection(); // let the connection available for other methods + mGet.releaseConnection(); // let the connection available for other methods } return status; } diff --git a/src/com/owncloud/android/operations/OAuth2GetAccessToken.java b/src/com/owncloud/android/operations/OAuth2GetAccessToken.java index 6d43caf1..5d468041 100644 --- a/src/com/owncloud/android/operations/OAuth2GetAccessToken.java +++ b/src/com/owncloud/android/operations/OAuth2GetAccessToken.java @@ -80,12 +80,12 @@ public class OAuth2GetAccessToken extends RemoteOperation { result = new RemoteOperationResult(ResultCode.OAUTH2_ERROR); } else { - result = new RemoteOperationResult(true, status); + result = new RemoteOperationResult(true, status, postMethod.getResponseHeaders()); } } else { client.exhaustResponse(postMethod.getResponseBodyAsStream()); - result = new RemoteOperationResult(false, status); + result = new RemoteOperationResult(false, status, postMethod.getResponseHeaders()); } } diff --git a/src/com/owncloud/android/operations/OwnCloudServerCheckOperation.java b/src/com/owncloud/android/operations/OwnCloudServerCheckOperation.java index 4982c664..d95b3055 100644 --- a/src/com/owncloud/android/operations/OwnCloudServerCheckOperation.java +++ b/src/com/owncloud/android/operations/OwnCloudServerCheckOperation.java @@ -80,7 +80,7 @@ public class OwnCloudServerCheckOperation extends RemoteOperation { } } else { - mLatestResult = new RemoteOperationResult(false, status); + mLatestResult = new RemoteOperationResult(false, status, get.getResponseHeaders()); } } catch (JSONException e) { diff --git a/src/com/owncloud/android/operations/RemoteOperation.java b/src/com/owncloud/android/operations/RemoteOperation.java index 9afb856f..9306e350 100644 --- a/src/com/owncloud/android/operations/RemoteOperation.java +++ b/src/com/owncloud/android/operations/RemoteOperation.java @@ -242,18 +242,27 @@ public abstract class RemoteOperation implements Runnable { result = run(mClient); repeat = false; - if (mCallerActivity != null && mAccount != null && mContext != null && !result.isSuccess() && result.getCode() == ResultCode.UNAUTHORIZED) { - /// fail due to lack of authorization in an operation performed in foreground - AccountManager am = AccountManager.get(mContext); + if (mCallerActivity != null && mAccount != null && mContext != null && !result.isSuccess() && + (result.getCode() == ResultCode.UNAUTHORIZED || (result.isTemporalRedirection() && result.isIdPRedirection()))) { + /// possible fail due to lack of authorization in an operation performed in foreground Credentials cred = mClient.getCredentials(); - if (cred instanceof BearerCredentials) { - am.invalidateAuthToken(AccountAuthenticator.ACCOUNT_TYPE, ((BearerCredentials)cred).getAccessToken()); - } else { - am.clearPassword(mAccount); + String ssoSessionCookie = mClient.getSsoSessionCookie(); + if (cred != null || ssoSessionCookie != null) { + /// confirmed : unauthorized operation + AccountManager am = AccountManager.get(mContext); + boolean bearerAuthorization = (cred != null && cred instanceof BearerCredentials); + boolean samlBasedSsoAuthorization = (cred == null && ssoSessionCookie != null); + if (bearerAuthorization) { + am.invalidateAuthToken(AccountAuthenticator.ACCOUNT_TYPE, ((BearerCredentials)cred).getAccessToken()); + } else if (samlBasedSsoAuthorization ) { + am.invalidateAuthToken(AccountAuthenticator.ACCOUNT_TYPE, ssoSessionCookie); + } else { + am.clearPassword(mAccount); + } + mClient = null; + repeat = true; // when repeated, the creation of a new OwnCloudClient after erasing the saved credentials will trigger the login activity + result = null; } - mClient = null; - repeat = true; // when repeated, the creation of a new OwnCloudClient after erasing the saved credentials will trigger the login activity - result = null; } } while (repeat); diff --git a/src/com/owncloud/android/operations/RemoteOperationResult.java b/src/com/owncloud/android/operations/RemoteOperationResult.java index f840f9ad..999974cf 100644 --- a/src/com/owncloud/android/operations/RemoteOperationResult.java +++ b/src/com/owncloud/android/operations/RemoteOperationResult.java @@ -51,7 +51,7 @@ import com.owncloud.android.network.CertificateCombinedException; public class RemoteOperationResult implements Serializable { /** Generated - should be refreshed every time the class changes!! */ - private static final long serialVersionUID = 3267227833178885664L; + private static final long serialVersionUID = -4415103901492836870L; private static final String TAG = "RemoteOperationResult"; @@ -86,7 +86,8 @@ public class RemoteOperationResult implements Serializable { QUOTA_EXCEEDED, ACCOUNT_NOT_FOUND, ACCOUNT_EXCEPTION, - ACCOUNT_NOT_NEW + ACCOUNT_NOT_NEW, + ACCOUNT_NOT_THE_SAME } private boolean mSuccess = false; @@ -100,7 +101,7 @@ public class RemoteOperationResult implements Serializable { mSuccess = (code == ResultCode.OK || code == ResultCode.OK_SSL || code == ResultCode.OK_NO_SSL); } - public RemoteOperationResult(boolean success, int httpCode) { + private RemoteOperationResult(boolean success, int httpCode) { mSuccess = success; mHttpCode = httpCode; @@ -301,6 +302,9 @@ public class RemoteOperationResult implements Serializable { } else if (mCode == ResultCode.ACCOUNT_NOT_NEW) { return "Account already existing when creating a new one"; + + } else if (mCode == ResultCode.ACCOUNT_NOT_THE_SAME) { + return "Authenticated with a different account than the one updating"; } return "Operation finished with HTTP status code " + mHttpCode + " (" + (isSuccess() ? "success" : "fail") + ")"; @@ -324,8 +328,9 @@ public class RemoteOperationResult implements Serializable { } public boolean isIdPRedirection() { - return (mRedirectedLocation.toUpperCase().contains("SAML") || - mRedirectedLocation.toLowerCase().contains("wayf")); + return (mRedirectedLocation != null && + (mRedirectedLocation.toUpperCase().contains("SAML") || + mRedirectedLocation.toLowerCase().contains("wayf"))); } } diff --git a/src/com/owncloud/android/operations/RemoveFileOperation.java b/src/com/owncloud/android/operations/RemoveFileOperation.java index 8348b72f..9dabfafd 100644 --- a/src/com/owncloud/android/operations/RemoveFileOperation.java +++ b/src/com/owncloud/android/operations/RemoveFileOperation.java @@ -88,7 +88,7 @@ public class RemoveFileOperation extends RemoteOperation { } } delete.getResponseBodyAsString(); // exhaust the response, although not interesting - result = new RemoteOperationResult((delete.succeeded() || status == HttpStatus.SC_NOT_FOUND), status); + result = new RemoteOperationResult((delete.succeeded() || status == HttpStatus.SC_NOT_FOUND), status, delete.getResponseHeaders()); Log_OC.i(TAG, "Remove " + mFileToRemove.getRemotePath() + ": " + result.getLogMessage()); } catch (Exception e) { diff --git a/src/com/owncloud/android/operations/RenameFileOperation.java b/src/com/owncloud/android/operations/RenameFileOperation.java index 1c636fba..fddb8499 100644 --- a/src/com/owncloud/android/operations/RenameFileOperation.java +++ b/src/com/owncloud/android/operations/RenameFileOperation.java @@ -136,7 +136,7 @@ public class RenameFileOperation extends RemoteOperation { } move.getResponseBodyAsString(); // exhaust response, although not interesting - result = new RemoteOperationResult(move.succeeded(), status); + result = new RemoteOperationResult(move.succeeded(), status, move.getResponseHeaders()); Log_OC.i(TAG, "Rename " + mFile.getRemotePath() + " to " + mNewRemotePath + ": " + result.getLogMessage()); } catch (Exception e) { diff --git a/src/com/owncloud/android/operations/SynchronizeFileOperation.java b/src/com/owncloud/android/operations/SynchronizeFileOperation.java index b0f2ce26..5be116bc 100644 --- a/src/com/owncloud/android/operations/SynchronizeFileOperation.java +++ b/src/com/owncloud/android/operations/SynchronizeFileOperation.java @@ -101,7 +101,7 @@ public class SynchronizeFileOperation extends RemoteOperation { } else { client.exhaustResponse(propfind.getResponseBodyAsStream()); - result = new RemoteOperationResult(false, status); + result = new RemoteOperationResult(false, status, propfind.getResponseHeaders()); } } diff --git a/src/com/owncloud/android/operations/SynchronizeFolderOperation.java b/src/com/owncloud/android/operations/SynchronizeFolderOperation.java index 7b157c38..67c7389e 100644 --- a/src/com/owncloud/android/operations/SynchronizeFolderOperation.java +++ b/src/com/owncloud/android/operations/SynchronizeFolderOperation.java @@ -243,16 +243,10 @@ public class SynchronizeFolderOperation extends RemoteOperation { result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT); // should be different result, but will do the job } else { - result = new RemoteOperationResult(true, status); - Header hCookie = query.getResponseHeader("Cookie"); - if (hCookie != null) { - Log_OC.e(TAG, "PROPFIND cookie: " + hCookie.getValue()); - } else { - Log_OC.e(TAG, "PROPFIND NO COOKIE"); - } + result = new RemoteOperationResult(true, status, query.getResponseHeaders()); } } else { - result = new RemoteOperationResult(false, status); + result = new RemoteOperationResult(false, status, query.getResponseHeaders()); } diff --git a/src/com/owncloud/android/operations/UpdateOCVersionOperation.java b/src/com/owncloud/android/operations/UpdateOCVersionOperation.java index 1b56bfbb..1643377b 100644 --- a/src/com/owncloud/android/operations/UpdateOCVersionOperation.java +++ b/src/com/owncloud/android/operations/UpdateOCVersionOperation.java @@ -65,7 +65,7 @@ public class UpdateOCVersionOperation extends RemoteOperation { int status = client.executeMethod(get); if (status != HttpStatus.SC_OK) { client.exhaustResponse(get.getResponseBodyAsStream()); - result = new RemoteOperationResult(false, status); + result = new RemoteOperationResult(false, status, get.getResponseHeaders()); } else { String response = get.getResponseBodyAsString(); diff --git a/src/com/owncloud/android/operations/UploadFileOperation.java b/src/com/owncloud/android/operations/UploadFileOperation.java index 2c891be9..cae1f179 100644 --- a/src/com/owncloud/android/operations/UploadFileOperation.java +++ b/src/com/owncloud/android/operations/UploadFileOperation.java @@ -304,7 +304,7 @@ public class UploadFileOperation extends RemoteOperation { } } - result = new RemoteOperationResult(isSuccess(status), status); + result = new RemoteOperationResult(isSuccess(status), status, (mPutMethod != null ? mPutMethod.getResponseHeaders() : null)); } catch (Exception e) { // TODO something cleaner with cancellations diff --git a/src/com/owncloud/android/syncadapter/FileSyncAdapter.java b/src/com/owncloud/android/syncadapter/FileSyncAdapter.java index 8653fe78..0ae6d775 100644 --- a/src/com/owncloud/android/syncadapter/FileSyncAdapter.java +++ b/src/com/owncloud/android/syncadapter/FileSyncAdapter.java @@ -28,6 +28,7 @@ import org.apache.jackrabbit.webdav.DavException; import com.owncloud.android.Log_OC; import com.owncloud.android.R; +import com.owncloud.android.authentication.AccountAuthenticator; import com.owncloud.android.authentication.AuthenticatorActivity; import com.owncloud.android.datamodel.DataStorageManager; import com.owncloud.android.datamodel.FileDataStorageManager; @@ -223,7 +224,9 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { sendStickyBroadcast(true, remotePath, null); } else { - if (result.getCode() == RemoteOperationResult.ResultCode.UNAUTHORIZED) { + if (result.getCode() == RemoteOperationResult.ResultCode.UNAUTHORIZED || + (result.isTemporalRedirection() && result.isIdPRedirection() && + AccountAuthenticator.AUTH_TOKEN_TYPE_SAML_WEB_SSO_SESSION_COOKIE.equals(getClient().getAuthTokenType()))) { mSyncResult.stats.numAuthExceptions++; } else if (result.getException() instanceof DavException) { @@ -304,7 +307,12 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { private void notifyFailedSynchronization() { Notification notification = new Notification(R.drawable.icon, getContext().getString(R.string.sync_fail_ticker), System.currentTimeMillis()); notification.flags |= Notification.FLAG_AUTO_CANCEL; - boolean needsToUpdateCredentials = (mLastFailedResult != null && mLastFailedResult.getCode() == ResultCode.UNAUTHORIZED); + boolean needsToUpdateCredentials = (mLastFailedResult != null && + ( mLastFailedResult.getCode() == ResultCode.UNAUTHORIZED || + (mLastFailedResult.isTemporalRedirection() && mLastFailedResult.isIdPRedirection() && + AccountAuthenticator.AUTH_TOKEN_TYPE_SAML_WEB_SSO_SESSION_COOKIE.equals(getClient().getAuthTokenType())) + ) + ); // TODO put something smart in the contentIntent below for all the possible errors notification.contentIntent = PendingIntent.getActivity(getContext().getApplicationContext(), (int)System.currentTimeMillis(), new Intent(), 0); if (needsToUpdateCredentials) { diff --git a/src/com/owncloud/android/ui/dialog/SamlWebViewDialog.java b/src/com/owncloud/android/ui/dialog/SamlWebViewDialog.java index fe20d815..a5219a22 100644 --- a/src/com/owncloud/android/ui/dialog/SamlWebViewDialog.java +++ b/src/com/owncloud/android/ui/dialog/SamlWebViewDialog.java @@ -118,7 +118,7 @@ public class SamlWebViewDialog extends SherlockDialogFragment { super.onCreate(savedInstanceState); CookieSyncManager.createInstance(getActivity()); - + if (savedInstanceState == null) { mInitialUrl = getArguments().getString(ARG_INITIAL_URL); mTargetUrl = getArguments().getString(ARG_TARGET_URL); diff --git a/src/eu/alefzero/webdav/WebdavClient.java b/src/eu/alefzero/webdav/WebdavClient.java index 570ebb85..cedf9267 100644 --- a/src/eu/alefzero/webdav/WebdavClient.java +++ b/src/eu/alefzero/webdav/WebdavClient.java @@ -41,6 +41,7 @@ import org.apache.http.params.CoreProtocolPNames; import com.owncloud.android.Log_OC; +import com.owncloud.android.authentication.AccountAuthenticator; import com.owncloud.android.network.BearerAuthScheme; import com.owncloud.android.network.BearerCredentials; @@ -51,6 +52,7 @@ public class WebdavClient extends HttpClient { private Credentials mCredentials; private boolean mFollowRedirects; private String mSsoSessionCookie; + private String mAuthTokenType; final private static String TAG = "WebdavClient"; public static final String USER_AGENT = "Android-ownCloud"; @@ -66,6 +68,7 @@ public class WebdavClient extends HttpClient { getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1); mFollowRedirects = true; mSsoSessionCookie = null; + mAuthTokenType = AccountAuthenticator.AUTH_TOKEN_TYPE_PASSWORD; } public void setBearerCredentials(String accessToken) { @@ -78,6 +81,7 @@ public class WebdavClient extends HttpClient { mCredentials = new BearerCredentials(accessToken); getState().setCredentials(AuthScope.ANY, mCredentials); mSsoSessionCookie = null; + mAuthTokenType = AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN; } public void setBasicCredentials(String username, String password) { @@ -89,6 +93,7 @@ public class WebdavClient extends HttpClient { mCredentials = new UsernamePasswordCredentials(username, password); getState().setCredentials(AuthScope.ANY, mCredentials); mSsoSessionCookie = null; + mAuthTokenType = AccountAuthenticator.AUTH_TOKEN_TYPE_PASSWORD; } public void setSsoSessionCookie(String accessToken) { @@ -96,6 +101,7 @@ public class WebdavClient extends HttpClient { getParams().setCookiePolicy(CookiePolicy.IGNORE_COOKIES); mSsoSessionCookie = accessToken; mCredentials = null; + mAuthTokenType = AccountAuthenticator.AUTH_TOKEN_TYPE_SAML_WEB_SSO_SESSION_COOKIE; } @@ -206,9 +212,17 @@ public class WebdavClient extends HttpClient { public final Credentials getCredentials() { return mCredentials; } + + public final String getSsoSessionCookie() { + return mSsoSessionCookie; + } public void setFollowRedirects(boolean followRedirects) { mFollowRedirects = followRedirects; } + public String getAuthTokenType() { + return mAuthTokenType; + } + }