From: David A. Velasco Date: Thu, 22 Aug 2013 15:50:11 +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~11 X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/commitdiff_plain/316a0a12ad4799ed0d43182a5b1b9bc04fbecee5?ds=inline;hp=-c Merge branch 'saml_based_federated_single_sign_on' into saml_based_federated_single_sign_on_expired --- 316a0a12ad4799ed0d43182a5b1b9bc04fbecee5 diff --combined res/layout-land/account_setup.xml index e00ade84,73da2b4b..2ae4b33f --- a/res/layout-land/account_setup.xml +++ b/res/layout-land/account_setup.xml @@@ -64,14 -64,7 +64,14 @@@ android:onClick="onRefreshClick" android:text="@string/auth_check_server" android:visibility="gone" /> - + - - - - + + - - - - Testing connection… 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 Unknown error occurred! An unknown error occurred. Please contact support and include logs from your device. Couldn\'t find host @@@ -209,9 -210,8 +210,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 --combined src/com/owncloud/android/authentication/AuthenticatorActivity.java index bab98de6,477af967..58c0c979 --- a/src/com/owncloud/android/authentication/AuthenticatorActivity.java +++ b/src/com/owncloud/android/authentication/AuthenticatorActivity.java @@@ -18,6 -18,8 +18,8 @@@ package com.owncloud.android.authentication; + import java.net.URLDecoder; + import android.accounts.Account; import android.accounts.AccountManager; import android.app.AlertDialog; @@@ -33,6 -35,7 +35,7 @@@ import android.net.Uri import android.os.Bundle; import android.os.Handler; import android.preference.PreferenceManager; + import android.support.v4.app.Fragment; import android.text.Editable; import android.text.InputType; import android.text.TextWatcher; @@@ -50,6 -53,7 +53,7 @@@ import android.widget.TextView import android.widget.TextView.OnEditorActionListener; import android.widget.Toast; + import com.actionbarsherlock.app.SherlockDialogFragment; import com.owncloud.android.Log_OC; import com.owncloud.android.R; import com.owncloud.android.authentication.SsoWebViewClient.SsoWebViewClientListener; @@@ -85,8 -89,6 +89,8 @@@ implements OnRemoteOperationListener, 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"; @@@ -100,6 -102,8 +104,8 @@@ private static final String KEY_AUTH_STATUS_TEXT = "AUTH_STATUS_TEXT"; private static final String KEY_AUTH_STATUS_ICON = "AUTH_STATUS_ICON"; private static final String KEY_REFRESH_BUTTON_ENABLED = "KEY_REFRESH_BUTTON_ENABLED"; + + private static final String KEY_OC_USERNAME_EQUALS = "oc_username="; private static final String AUTH_ON = "on"; private static final String AUTH_OFF = "off"; @@@ -118,8 -122,7 +124,8 @@@ 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; @@@ -137,8 -140,6 +143,8 @@@ private byte mAction; private Account mAccount; + private TextView mAuthMessage; + private EditText mHostUrlInput; private boolean mHostUrlInputEnabled; private View mRefreshButton; @@@ -153,7 -154,6 +159,6 @@@ private TextView mOAuthAuthEndpointText; private TextView mOAuthTokenEndpointText; - private TextView mAccountNameInput; private SamlWebViewDialog mSamlDialog; private View mOkButton; @@@ -173,7 -173,6 +178,7 @@@ /// 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); @@@ -181,7 -180,6 +186,6 @@@ mOAuthAuthEndpointText = (TextView)findViewById(R.id.oAuthEntryPoint_1); mOAuthTokenEndpointText = (TextView)findViewById(R.id.oAuthEntryPoint_2); mOAuth2Check = (CheckBox) findViewById(R.id.oauth_onOff_check); - mAccountNameInput = (EditText) findViewById(R.id.account_name); mOkButton = findViewById(R.id.buttonOK); mAuthStatusLayout = (TextView) findViewById(R.id.auth_status_text); @@@ -215,7 -213,6 +219,7 @@@ if (savedInstanceState == null) { /// connection state and info + mAuthMessageVisibility = View.GONE; mServerStatusText = mServerStatusIcon = 0; mServerIsValid = false; mServerIsChecked = false; @@@ -231,9 -228,6 +235,8 @@@ } 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); - mAccountNameInput.setText(userName); } initAuthorizationMethod(); // checks intent and setup.xml to determine mCurrentAuthorizationMethod mJustCreated = true; @@@ -244,8 -238,6 +247,8 @@@ } 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); @@@ -283,12 -275,6 +286,12 @@@ } + if (mAuthMessageVisibility== View.VISIBLE) { + showAuthMessage(mAuthMessageText); + } + else { + hideAuthMessage(); + } adaptViewAccordingToAuthenticationMethod(); showServerStatus(); showAuthStatus(); @@@ -300,8 -286,6 +303,6 @@@ mUsernameInput.setEnabled(false); mUsernameInput.setFocusable(false); mOAuth2Check.setVisibility(View.GONE); - mAccountNameInput.setEnabled(false); - mAccountNameInput.setFocusable(false); } //if (mServerIsChecked && !mServerIsValid && mRefreshButtonEnabled) showRefreshButton(); @@@ -317,6 -301,8 +318,8 @@@ /// bind view elements to listeners and other friends mHostUrlInput.setOnFocusChangeListener(this); + mHostUrlInput.setImeOptions(EditorInfo.IME_ACTION_NEXT); + mHostUrlInput.setOnEditorActionListener(this); mHostUrlInput.addTextChangedListener(new TextWatcher() { @Override @@@ -401,8 -387,6 +404,8 @@@ 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); @@@ -457,16 -441,10 +460,16 @@@ 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) { @@@ -660,7 -638,6 +663,7 @@@ 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)) { @@@ -1015,6 -992,9 +1018,9 @@@ case OAUTH2_ERROR_ACCESS_DENIED: mAuthStatusText = R.string.auth_oauth_error_access_denied; break; + case ACCOUNT_NOT_NEW: + mAuthStatusText = R.string.auth_account_not_new; + break; case UNHANDLED_HTTP_CODE: case UNKNOWN_ERROR: mAuthStatusText = R.string.auth_unknown_error_title; @@@ -1079,14 -1059,17 +1085,17 @@@ if (result.isSuccess()) { Log_OC.d(TAG, "Successful access - time to save the account"); + boolean success = true; if (mAction == ACTION_CREATE) { - createAccount(); + success = createAccount(); } else { updateToken(); } - finish(); + if (success) { + finish(); + } } else if (result.isServerFail() || result.isException()) { /// if server fail or exception in authorization, the UI is updated as when a server check failed @@@ -1146,9 -1129,6 +1155,9 @@@ mAccountMgr.setPassword(mAccount, mPasswordInput.getText().toString()); } setAccountAuthenticatorResult(response); + + // Sync Account + syncAccount(); } @@@ -1159,7 -1139,7 +1168,7 @@@ * * TODO Decide how to name the OAuth accounts */ - private void createAccount() { + private boolean createAccount() { /// create and save new ownCloud account boolean isOAuth = AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN.equals(mCurrentAuthTokenType); boolean isSaml = AccountAuthenticator.AUTH_TOKEN_TYPE_SAML_WEB_SSO_SESSION_COOKIE.equals(mCurrentAuthTokenType); @@@ -1167,7 -1147,7 +1176,7 @@@ Uri uri = Uri.parse(mHostBaseUrl); String username = mUsernameInput.getText().toString().trim(); if (isSaml) { - username = mAccountNameInput.getText().toString().trim(); + username = getUserNameForSamlSso(); } else if (isOAuth) { username = "OAuth_user" + (new java.util.Random(System.currentTimeMillis())).nextLong(); @@@ -1177,49 -1157,75 +1186,79 @@@ accountName += ":" + uri.getPort(); } mAccount = new Account(accountName, AccountAuthenticator.ACCOUNT_TYPE); - if (isOAuth || isSaml) { - mAccountMgr.addAccountExplicitly(mAccount, "", null); // with external authorizations, the password is never input in the app + if (AccountUtils.exists(mAccount, getApplicationContext())) { + // fail - not a new account, but an existing one; disallow + RemoteOperationResult result = new RemoteOperationResult(ResultCode.ACCOUNT_NOT_NEW); + updateAuthStatusIconAndText(result); + showAuthStatus(); + Log_OC.d(TAG, result.getLogMessage()); + return false; + + } else { - mAccountMgr.addAccountExplicitly(mAccount, mPasswordInput.getText().toString(), null); - } - - /// add the new account as default in preferences, if there is none already - Account defaultAccount = AccountUtils.getCurrentOwnCloudAccount(this); - if (defaultAccount == null) { - SharedPreferences.Editor editor = PreferenceManager - .getDefaultSharedPreferences(this).edit(); - editor.putString("select_oc_account", accountName); - editor.commit(); + + if (isOAuth || isSaml) { + mAccountMgr.addAccountExplicitly(mAccount, "", null); // with external authorizations, the password is never input in the app + } else { + mAccountMgr.addAccountExplicitly(mAccount, mPasswordInput.getText().toString(), null); + } + + /// add the new account as default in preferences, if there is none already + Account defaultAccount = AccountUtils.getCurrentOwnCloudAccount(this); + if (defaultAccount == null) { + SharedPreferences.Editor editor = PreferenceManager + .getDefaultSharedPreferences(this).edit(); + editor.putString("select_oc_account", accountName); + editor.commit(); + } + + /// prepare result to return to the Authenticator + // TODO check again what the Authenticator makes with it; probably has the same effect as addAccountExplicitly, but it's not well done + final Intent intent = new Intent(); + intent.putExtra(AccountManager.KEY_ACCOUNT_TYPE, AccountAuthenticator.ACCOUNT_TYPE); + intent.putExtra(AccountManager.KEY_ACCOUNT_NAME, mAccount.name); + /*if (!isOAuth) + intent.putExtra(AccountManager.KEY_AUTHTOKEN, AccountAuthenticator.ACCOUNT_TYPE); */ + intent.putExtra(AccountManager.KEY_USERDATA, username); + if (isOAuth || isSaml) { + mAccountMgr.setAuthToken(mAccount, mCurrentAuthTokenType, mAuthToken); + } + /// add user data to the new account; TODO probably can be done in the last parameter addAccountExplicitly, or in KEY_USERDATA + mAccountMgr.setUserData(mAccount, AccountAuthenticator.KEY_OC_VERSION, mDiscoveredVersion.toString()); + mAccountMgr.setUserData(mAccount, AccountAuthenticator.KEY_OC_BASE_URL, mHostBaseUrl); + if (isSaml) { + mAccountMgr.setUserData(mAccount, AccountAuthenticator.KEY_SUPPORTS_SAML_WEB_SSO, "TRUE"); + } else if (isOAuth) { + mAccountMgr.setUserData(mAccount, AccountAuthenticator.KEY_SUPPORTS_OAUTH2, "TRUE"); + } + + setAccountAuthenticatorResult(intent.getExtras()); + setResult(RESULT_OK, intent); + + /// 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); ++ syncAccount(); ++// Bundle bundle = new Bundle(); ++// bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true); ++// ContentResolver.requestSync(mAccount, AccountAuthenticator.AUTHORITY, bundle); + return true; } + } - /// prepare result to return to the Authenticator - // TODO check again what the Authenticator makes with it; probably has the same effect as addAccountExplicitly, but it's not well done - final Intent intent = new Intent(); - intent.putExtra(AccountManager.KEY_ACCOUNT_TYPE, AccountAuthenticator.ACCOUNT_TYPE); - intent.putExtra(AccountManager.KEY_ACCOUNT_NAME, mAccount.name); - /*if (!isOAuth) - intent.putExtra(AccountManager.KEY_AUTHTOKEN, AccountAuthenticator.ACCOUNT_TYPE); */ - intent.putExtra(AccountManager.KEY_USERDATA, username); - if (isOAuth || isSaml) { - mAccountMgr.setAuthToken(mAccount, mCurrentAuthTokenType, mAuthToken); - } - /// add user data to the new account; TODO probably can be done in the last parameter addAccountExplicitly, or in KEY_USERDATA - mAccountMgr.setUserData(mAccount, AccountAuthenticator.KEY_OC_VERSION, mDiscoveredVersion.toString()); - mAccountMgr.setUserData(mAccount, AccountAuthenticator.KEY_OC_BASE_URL, mHostBaseUrl); - if (isSaml) { - mAccountMgr.setUserData(mAccount, AccountAuthenticator.KEY_SUPPORTS_SAML_WEB_SSO, "TRUE"); - } else if (isOAuth) { - mAccountMgr.setUserData(mAccount, AccountAuthenticator.KEY_SUPPORTS_OAUTH2, "TRUE"); + + private String getUserNameForSamlSso() { + if (mAuthToken != null) { + String [] cookies = mAuthToken.split(";"); + for (int i=0; i