From: David A. Velasco Date: Mon, 28 Jan 2013 12:15:28 +0000 (+0100) Subject: Fixed behaviour when authorization is denied by user; added toast message to explain... X-Git-Tag: oc-android-1.4.3~29^2~15 X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/commitdiff_plain/fb8a8a2166dd3cb54c9416722bff961797714c4a?hp=--cc Fixed behaviour when authorization is denied by user; added toast message to explain the need to update credentials --- fb8a8a2166dd3cb54c9416722bff961797714c4a diff --git a/res/values/strings.xml b/res/values/strings.xml index 009bd7f6..bc35032e 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -177,10 +177,13 @@ Secure connection established Login details Invalid credentials - Bad response from authorization server + Unsuccessful authorization + Access denied by authorization server Wrong path given Internal server error, code %1$d Unexpected state; please, enter the server URL again + Your authorization expired.\nPlease, authorize again + Your saved credentials are invalid.\nPlease, enter the current credentials Application terminated unexpectedly. Would you like to submit a crash report? Send report diff --git a/src/com/owncloud/android/authenticator/oauth2/OAuth2Context.java b/src/com/owncloud/android/authenticator/oauth2/OAuth2Context.java index fa0872e4..7d36da7b 100644 --- a/src/com/owncloud/android/authenticator/oauth2/OAuth2Context.java +++ b/src/com/owncloud/android/authenticator/oauth2/OAuth2Context.java @@ -53,4 +53,6 @@ public class OAuth2Context { public static final String CODE_RESPONSE_TYPE = "response_type"; public static final String CODE_REDIRECT_URI = "redirect_uri"; + public static final String ERROR_ACCESS_DENIED = "access_denied"; + } diff --git a/src/com/owncloud/android/operations/OAuth2GetAccessToken.java b/src/com/owncloud/android/operations/OAuth2GetAccessToken.java index 8f5dd3b2..66c4efee 100644 --- a/src/com/owncloud/android/operations/OAuth2GetAccessToken.java +++ b/src/com/owncloud/android/operations/OAuth2GetAccessToken.java @@ -19,18 +19,21 @@ public class OAuth2GetAccessToken extends RemoteOperation { private static final String TAG = OAuth2GetAccessToken.class.getSimpleName(); - private Map mOAuth2AuthorizationResponse; + private String mOAuth2AuthorizationResponse; + private Map mOAuth2ParsedAuthorizationResponse; private Map mResultTokenMap; - public OAuth2GetAccessToken(Map oAuth2AuthorizationResponse) { + public OAuth2GetAccessToken(String oAuth2AuthorizationResponse) { + mOAuth2AuthorizationResponse = oAuth2AuthorizationResponse; + mOAuth2ParsedAuthorizationResponse = new HashMap(); mResultTokenMap = null; } public Map getOauth2AutorizationResponse() { - return mOAuth2AuthorizationResponse; + return mOAuth2ParsedAuthorizationResponse; } public Map getResultTokenMap() { @@ -43,31 +46,44 @@ public class OAuth2GetAccessToken extends RemoteOperation { PostMethod postMethod = null; try { - NameValuePair[] nameValuePairs = new NameValuePair[5]; - nameValuePairs[0] = new NameValuePair(OAuth2Context.KEY_CLIENT_ID, OAuth2Context.OAUTH2_F_CLIENT_ID); - nameValuePairs[1] = new NameValuePair(OAuth2Context.KEY_CODE, mOAuth2AuthorizationResponse.get(OAuth2Context.KEY_CODE)); - nameValuePairs[2] = new NameValuePair(OAuth2Context.KEY_SCOPE, mOAuth2AuthorizationResponse.get(OAuth2Context.KEY_SCOPE)); - nameValuePairs[3] = new NameValuePair(OAuth2Context.KEY_REDIRECT_URI, OAuth2Context.MY_REDIRECT_URI); - nameValuePairs[4] = new NameValuePair(OAuth2Context.KEY_GRANT_TYPE, OAuth2Context.OAUTH2_AUTH_CODE_GRANT_TYPE); + parseAuthorizationResponse(); + if (mOAuth2ParsedAuthorizationResponse.keySet().contains(OAuth2Context.KEY_ERROR)) { + if (OAuth2Context.ERROR_ACCESS_DENIED.equals(mOAuth2ParsedAuthorizationResponse.get(OAuth2Context.KEY_ERROR))) { + result = new RemoteOperationResult(ResultCode.OAUTH2_ERROR_ACCESS_DENIED); + } else { + result = new RemoteOperationResult(ResultCode.OAUTH2_ERROR); + } + } - postMethod = new PostMethod(client.getBaseUri().toString()); - postMethod.setRequestBody(nameValuePairs); - int status = client.executeMethod(postMethod); - if (status >= 300) { - client.exhaustResponse(postMethod.getResponseBodyAsStream()); - result = new RemoteOperationResult(false, status); + if (result == null) { + NameValuePair[] nameValuePairs = new NameValuePair[5]; + nameValuePairs[0] = new NameValuePair(OAuth2Context.KEY_CLIENT_ID, OAuth2Context.OAUTH2_F_CLIENT_ID); + nameValuePairs[1] = new NameValuePair(OAuth2Context.KEY_CODE, mOAuth2ParsedAuthorizationResponse.get(OAuth2Context.KEY_CODE)); + nameValuePairs[2] = new NameValuePair(OAuth2Context.KEY_SCOPE, mOAuth2ParsedAuthorizationResponse.get(OAuth2Context.KEY_SCOPE)); + nameValuePairs[3] = new NameValuePair(OAuth2Context.KEY_REDIRECT_URI, OAuth2Context.MY_REDIRECT_URI); + nameValuePairs[4] = new NameValuePair(OAuth2Context.KEY_GRANT_TYPE, OAuth2Context.OAUTH2_AUTH_CODE_GRANT_TYPE); - } else { - JSONObject tokenJson = new JSONObject(postMethod.getResponseBodyAsString()); - parseResult(tokenJson); - if (mResultTokenMap.get(OAuth2Context.OAUTH2_TOKEN_RECEIVED_ERROR) != null) { - result = new RemoteOperationResult(ResultCode.OAUTH2_ERROR); + postMethod = new PostMethod(client.getBaseUri().toString()); + postMethod.setRequestBody(nameValuePairs); + int status = client.executeMethod(postMethod); + + String response = postMethod.getResponseBodyAsString(); + if (response != null && response.length() > 0) { + JSONObject tokenJson = new JSONObject(response); + parseAccessTokenResult(tokenJson); + if (mResultTokenMap.get(OAuth2Context.OAUTH2_TOKEN_RECEIVED_ERROR) != null || mResultTokenMap.get(OAuth2Context.KEY_ACCESS_TOKEN) == null) { + result = new RemoteOperationResult(ResultCode.OAUTH2_ERROR); + + } else { + result = new RemoteOperationResult(true, status); + } } else { - result = new RemoteOperationResult(true, status); + client.exhaustResponse(postMethod.getResponseBodyAsStream()); + result = new RemoteOperationResult(false, status); } } - + } catch (Exception e) { result = new RemoteOperationResult(e); @@ -76,16 +92,16 @@ public class OAuth2GetAccessToken extends RemoteOperation { postMethod.releaseConnection(); // let the connection available for other methods if (result.isSuccess()) { - Log.i(TAG, "OAuth2 TOKEN REQUEST with code " + mOAuth2AuthorizationResponse.get("code") + " to " + client.getBaseUri() + ": " + result.getLogMessage()); + Log.i(TAG, "OAuth2 TOKEN REQUEST with auth code " + mOAuth2ParsedAuthorizationResponse.get("code") + " to " + client.getBaseUri() + ": " + result.getLogMessage()); } else if (result.getException() != null) { - Log.e(TAG, "OAuth2 TOKEN REQUEST with code " + mOAuth2AuthorizationResponse.get("code") + " to " + client.getBaseUri() + ": " + result.getLogMessage(), result.getException()); + Log.e(TAG, "OAuth2 TOKEN REQUEST with auth code " + mOAuth2ParsedAuthorizationResponse.get("code") + " to " + client.getBaseUri() + ": " + result.getLogMessage(), result.getException()); } else if (result.getCode() == ResultCode.OAUTH2_ERROR) { - Log.e(TAG, "OAuth2 TOKEN REQUEST with code " + mOAuth2AuthorizationResponse.get("code") + " to " + client.getBaseUri() + ": " + mResultTokenMap.get(OAuth2Context.OAUTH2_TOKEN_RECEIVED_ERROR)); + Log.e(TAG, "OAuth2 TOKEN REQUEST with auth code " + mOAuth2ParsedAuthorizationResponse.get("code") + " to " + client.getBaseUri() + ": " + mResultTokenMap.get(OAuth2Context.OAUTH2_TOKEN_RECEIVED_ERROR)); } else { - Log.e(TAG, "OAuth2 TOKEN REQUEST with code " + mOAuth2AuthorizationResponse.get("code") + " to " + client.getBaseUri() + ": " + result.getLogMessage()); + Log.e(TAG, "OAuth2 TOKEN REQUEST with auth code " + mOAuth2ParsedAuthorizationResponse.get("code") + " to " + client.getBaseUri() + ": " + result.getLogMessage()); } } @@ -93,7 +109,35 @@ public class OAuth2GetAccessToken extends RemoteOperation { } - private void parseResult (JSONObject tokenJson) throws JSONException { + private void parseAuthorizationResponse() { + String[] pairs = mOAuth2AuthorizationResponse.split("&"); + int i = 0; + String key = ""; + String value = ""; + StringBuilder sb = new StringBuilder(); + while (pairs.length > i) { + int j = 0; + String[] part = pairs[i].split("="); + while (part.length > j) { + String p = part[j]; + if (j == 0) { + key = p; + sb.append(key + " = "); + } else if (j == 1) { + value = p; + mOAuth2ParsedAuthorizationResponse.put(key, value); + sb.append(value + "\n"); + } + + Log.v(TAG, "[" + i + "," + j + "] = " + p); + j++; + } + i++; + } + } + + + private void parseAccessTokenResult (JSONObject tokenJson) throws JSONException { mResultTokenMap = new HashMap(); if (tokenJson.has(OAuth2Context.KEY_ACCESS_TOKEN)) { diff --git a/src/com/owncloud/android/operations/RemoteOperationResult.java b/src/com/owncloud/android/operations/RemoteOperationResult.java index 5a14fb87..1644e1a1 100644 --- a/src/com/owncloud/android/operations/RemoteOperationResult.java +++ b/src/com/owncloud/android/operations/RemoteOperationResult.java @@ -72,7 +72,8 @@ public class RemoteOperationResult implements Serializable { SYNC_CONFLICT, LOCAL_STORAGE_FULL, LOCAL_STORAGE_NOT_MOVED, - LOCAL_STORAGE_NOT_COPIED + LOCAL_STORAGE_NOT_COPIED, + OAUTH2_ERROR_ACCESS_DENIED } private boolean mSuccess = false; diff --git a/src/com/owncloud/android/ui/activity/AuthenticatorActivity.java b/src/com/owncloud/android/ui/activity/AuthenticatorActivity.java index 6500ce5e..c39f5406 100644 --- a/src/com/owncloud/android/ui/activity/AuthenticatorActivity.java +++ b/src/com/owncloud/android/ui/activity/AuthenticatorActivity.java @@ -19,9 +19,6 @@ package com.owncloud.android.ui.activity; -import java.util.HashMap; -import java.util.Map; - import com.owncloud.android.AccountUtils; import com.owncloud.android.authenticator.AccountAuthenticator; import com.owncloud.android.authenticator.oauth2.OAuth2Context; @@ -61,6 +58,8 @@ import android.widget.EditText; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; +import android.widget.Toast; + import com.owncloud.android.R; import eu.alefzero.webdav.WebdavClient; @@ -119,6 +118,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity private Uri mNewCapturedUriFromOAuth2Redirection; private AccountManager mAccountMgr; + private boolean mJustCreated; private ImageView mRefreshButton; private ImageView mViewPasswordButton; @@ -209,6 +209,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity } mPasswordInput.setText(""); // clean password to avoid social hacking (disadvantage: password in removed if the device is turned aside) + mJustCreated = true; } @@ -318,8 +319,15 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity @Override protected void onResume() { super.onResume(); + // the state of mOAuth2Check is automatically recovered between configuration changes, but not before onCreate() finishes; so keep the next lines here changeViewByOAuth2Check(mOAuth2Check.isChecked()); - // the state of mOAuth2Check is automatically recovered between configuration changes, but not before onCreate() finishes + if (getIntent().getByteExtra(EXTRA_ACTION, ACTION_CREATE) == ACTION_UPDATE_TOKEN && mJustCreated) { + 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(); + } + /* LEAVE OLD OAUTH FLOW ; // (old oauth code) Registering token receiver. We must listening to the service that is pooling to the oAuth server for a token. @@ -332,6 +340,8 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity if (mNewCapturedUriFromOAuth2Redirection != null) { getOAuth2AccessTokenFromCapturedRedirection(); } + + mJustCreated = false; } @@ -358,46 +368,14 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity */ private void getOAuth2AccessTokenFromCapturedRedirection() { /// Parse data from OAuth redirection - Map responseValues = new HashMap(); String queryParameters = mNewCapturedUriFromOAuth2Redirection.getQuery(); mNewCapturedUriFromOAuth2Redirection = null; - String[] pairs = queryParameters.split("&"); - int i = 0; - String key = ""; - String value = ""; - StringBuilder sb = new StringBuilder(); - while (pairs.length > i) { - int j = 0; - String[] part = pairs[i].split("="); - while (part.length > j) { - String p = part[j]; - if (j == 0) { - key = p; - sb.append(key + " = "); - } else if (j == 1) { - value = p; - responseValues.put(key, value); - sb.append(value + "\n"); - } - - Log.v(TAG, "[" + i + "," + j + "] = " + p); - j++; - } - i++; - } - - /// Updating status widget to OK. -- TODO REMOVE, UNNECESSARY - /* - mStatusIcon = R.drawable.ic_ok; - mStatusText = R.string.auth_connection_established; - updateAuthStatus(); - */ /// Showing the dialog with instructions for the user. showDialog(DIALOG_OAUTH2_LOGIN_PROGRESS); /// GET ACCESS TOKEN to the oAuth server - RemoteOperation operation = new OAuth2GetAccessToken(responseValues); + RemoteOperation operation = new OAuth2GetAccessToken(queryParameters); WebdavClient client = OwnCloudClientUtils.createOwnCloudClient(Uri.parse(getString(R.string.oauth_url_endpoint_access)), getApplicationContext()); operation.execute(client, this, mHandler); } @@ -737,7 +715,11 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity break; case OAUTH2_ERROR: mStatusIcon = R.drawable.common_error; - mStatusText = R.string.auth_bad_oauth_token; + mStatusText = R.string.auth_oauth_error; + break; + case OAUTH2_ERROR_ACCESS_DENIED: + mStatusIcon = R.drawable.common_error; + mStatusText = R.string.auth_oauth_error_access_denied; break; case UNHANDLED_HTTP_CODE: case UNKNOWN_ERROR: @@ -779,11 +761,9 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity mAuthCheckOperation.execute(client, this, mHandler); } else { - if (webdav_path != null) { - mOAuthAuthEndpointText.setError("A valid authorization could not be obtained"); - } else { - mOAuthAuthEndpointText.setError(getString(R.string.auth_bad_oc_version_title)); // should never happen - } + updateStatusIconAndText(result); + updateAuthStatus(); + Log.d(TAG, "Access failed: " + result.getLogMessage()); } }