Fixed visibility of authorization details when the device is turned aside; removed unused classes from old OAuth flow

This commit is contained in:
David A. Velasco 2013-01-24 18:31:40 +01:00
parent ac07e35d8a
commit 1e5aa5345f
5 changed files with 3 additions and 486 deletions

View file

@ -1,19 +0,0 @@
package com.owncloud.android.authenticator.oauth2;
import org.json.JSONObject;
/**
* Listener that expects results from OAuth2GetCodeRunnable class.
*
* @author SolidGear S.L.
*
*/
public interface OnOAuth2GetCodeResultListener {
enum ResultOAuthType {
OK_SSL, OK_NO_SSL, SSL_INIT_ERROR, HOST_NOT_AVAILABLE, TIMEOUT, NO_NETWORK_CONNECTION, INCORRECT_ADDRESS, INSTANCE_NOT_CONFIGURED, FILE_NOT_FOUND, UNKNOWN_ERROR, WRONG_CONNECTION, SSL_UNVERIFIED_SERVER, BAD_OC_VERSION
}
public void onOAuth2GetCodeResult(ResultOAuthType type, JSONObject code);
}

View file

@ -1,113 +0,0 @@
package com.owncloud.android.authenticator.oauth2.connection;
import org.apache.http.HttpResponse;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.client.params.CookiePolicy;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import android.util.Log;
/**
* Implements HTTP POST communications with an oAuth2 server.
*
* @author SolidGear S.L.
*
*/
public class ConnectorOAuth2 {
private static final String TAG = "ConnectorOAuth2";
/** Maximum time to wait for a response from the server when the connection is being tested, in MILLISECONDs. */
private static final int TRY_CONNECTION_TIMEOUT = 5000;
private DefaultHttpClient httpClient;
private HttpContext localContext;
private String ConnectorOAuth2Url;
public ConnectorOAuth2 (String destUrl) {
prepareConn();
setConnectorOAuth2Url(destUrl);
}
public ConnectorOAuth2 () {
prepareConn();
}
public String getConnectorOAuth2Url() {
return ConnectorOAuth2Url;
}
public void setConnectorOAuth2Url(String connectorOAuth2Url) {
ConnectorOAuth2Url = connectorOAuth2Url;
}
/**
* Starts the communication with the server.
*
* @param UrlEncodedFormEntity : parameters included in the POST call.
* @return String : data returned from the server in String format.
*/
public String connPost(UrlEncodedFormEntity data) {
String dataOut = null;
HttpPost httpPost = null;
int responseCode = -1;
HttpResponse response = null;
httpClient.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.RFC_2109);
if (ConnectorOAuth2Url == null) {
Log.e(TAG, "connPost error: destination URI could not be null");
return null;
}
if (data == null){
Log.e(TAG, "connPost error: data to send to URI " + ConnectorOAuth2Url + "could not be null");
return null;
}
httpPost = new HttpPost(ConnectorOAuth2Url);
httpPost.setHeader("Accept","text/html,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");
httpPost.setEntity((UrlEncodedFormEntity) data);
try {
response = httpClient.execute(httpPost,localContext);
if (response == null) {
Log.e(TAG, "connPost error: response from uri " + ConnectorOAuth2Url + " is null");
return null;
}
responseCode = response.getStatusLine().getStatusCode();
if ((responseCode != 200)) {
Log.e(TAG, "connPost error: response from uri "+ ConnectorOAuth2Url + " returns status " + responseCode);
return null;
}
dataOut = EntityUtils.toString(response.getEntity());
} catch (Exception e) {
Log.e(TAG, "connPost Exception: " + e);
}
return dataOut;
}
private void prepareConn () {
HttpParams localParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(localParams, TRY_CONNECTION_TIMEOUT);
HttpConnectionParams.setSoTimeout(localParams, TRY_CONNECTION_TIMEOUT);
httpClient = new DefaultHttpClient(localParams);
localContext = new BasicHttpContext();
}
}

View file

@ -1,200 +0,0 @@
package com.owncloud.android.authenticator.oauth2.services;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import com.owncloud.android.authenticator.oauth2.OAuth2Context;
import com.owncloud.android.authenticator.oauth2.connection.ConnectorOAuth2;
/**
* Service class that implements the second communication with the oAuth2 server:
* pooling for the token in an interval. It send a broadcast with the results when are positive;
* otherwise, it continues asking to the server.
*
* @author Solid Gear S.L.
*
*/
public class OAuth2GetTokenService extends Service {
public static final String TOKEN_RECEIVED_MESSAGE = "TOKEN_RECEIVED";
public static final String TOKEN_RECEIVED_DATA = "TOKEN_DATA";
public static final String TOKEN_URI = "TOKEN_URI";
public static final String TOKEN_DEVICE_CODE = "device_code";
public static final String TOKEN_INTERVAL = "interval";
public static final String TOKEN_RECEIVED_ERROR = "error";
public static final String TOKEN_RECEIVED_ERROR_AUTH_TOKEN = "authorization_pending";
public static final String TOKEN_RECEIVED_ERROR_SLOW_DOWN = "slow_down";
public static final String TOKEN_ACCESS_TOKEN = "access_token";
public static final String TOKEN_TOKEN_TYPE = "token_type";
public static final String TOKEN_EXPIRES_IN = "expires_in";
public static final String TOKEN_REFRESH_TOKEN = "refresh_token";
private String requestDeviceCode;
private int requestInterval = -1;
private String requestBaseURI;
private ConnectorOAuth2 connectorOAuth2;
private static final String TAG = "OAuth2GetTokenService";
private Timer timer = new Timer();
@Override
public IBinder onBind(Intent arg0) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Bundle param = intent.getExtras();
if (param != null) {
String mUrl = param.getString(TOKEN_URI);
if (!mUrl.startsWith("http://") || !mUrl.startsWith("https://")) {
requestBaseURI = "https://" + mUrl;
}
requestDeviceCode = param.getString(TOKEN_DEVICE_CODE);
requestInterval = param.getInt(TOKEN_INTERVAL);
Log.d(TAG, "onStartCommand -> requestDeviceCode=" + requestDeviceCode);
Log.d(TAG, "onStartCommand -> requestInterval=" + requestInterval);
} else {
Log.e(TAG, "onStartCommand -> params could not be null");
}
startService();
return Service.START_NOT_STICKY;
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onDestroy() {
super.onDestroy();
shutdownService();
}
private void startService() {
final UrlEncodedFormEntity params = prepareComm();
timer.scheduleAtFixedRate(
new TimerTask() {
public void run() {
requestToken(params);
}
}, 0, requestInterval * 1000);
Log.d(TAG, "startService -> Timer started");
}
private void shutdownService() {
if (timer != null) timer.cancel();
Log.d(TAG, "shutdownService -> Timer stopped");
}
private UrlEncodedFormEntity prepareComm() {
UrlEncodedFormEntity params = null;
connectorOAuth2 = new ConnectorOAuth2();
if (requestBaseURI == null || requestBaseURI.trim().equals("")) {
Log.e(TAG, "run -> request URI could not be null");
postResult(null);
}
if (requestInterval == -1) {
Log.e(TAG, "run -> request Interval must have valid positive value");
postResult(null);
}
if (requestDeviceCode == null || requestDeviceCode.trim().equals("")) {
Log.e(TAG, "run -> request DeviceCode could not be null");
postResult(null);
}
try{
connectorOAuth2.setConnectorOAuth2Url(requestBaseURI + OAuth2Context.OAUTH2_G_DEVICE_GETTOKEN_URL);
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("client_id", OAuth2Context.OAUTH2_G_DEVICE_CLIENT_ID));
nameValuePairs.add(new BasicNameValuePair("client_secret", OAuth2Context.OAUTH2_G_DEVICE_CLIENT_SECRET));
nameValuePairs.add(new BasicNameValuePair("code",requestDeviceCode));
nameValuePairs.add(new BasicNameValuePair("grant_type",OAuth2Context.OAUTH_G_DEVICE_GETTOKEN_GRANT_TYPE));
params = new UrlEncodedFormEntity(nameValuePairs);
}
catch (Exception ex1){
Log.w(TAG, ex1.toString());
postResult(null);
}
return params;
}
protected void requestToken(UrlEncodedFormEntity params){
JSONObject tokenJson = null;
String error = null;
HashMap<String, String> resultTokenMap;
String tokenResponse = connectorOAuth2.connPost(params);
try {
tokenJson = new JSONObject(tokenResponse);
} catch (JSONException e) {
Log.e(TAG, "Exception converting to Json " + e.toString());
}
try {
// We try to get error string.
if (tokenJson.has(TOKEN_RECEIVED_ERROR)) {
error = tokenJson.getString(TOKEN_RECEIVED_ERROR);
Log.d(TAG, "requestToken -> Obtained error "+ error);
} else {
//We have got the token. Parse the answer.
resultTokenMap = parseResult(tokenJson);
postResult(resultTokenMap);
}
} catch (JSONException e) {
Log.e(TAG, "Exception converting to Json " + e.toString());
}
}
private HashMap<String, String> parseResult (JSONObject tokenJson) {
HashMap<String, String> resultTokenMap=new HashMap<String, String>();
try {
resultTokenMap.put(TOKEN_ACCESS_TOKEN, tokenJson.getString(TOKEN_ACCESS_TOKEN));
resultTokenMap.put(TOKEN_TOKEN_TYPE, tokenJson.getString(TOKEN_TOKEN_TYPE));
resultTokenMap.put(TOKEN_EXPIRES_IN, tokenJson.getString(TOKEN_EXPIRES_IN));
resultTokenMap.put(TOKEN_REFRESH_TOKEN, tokenJson.getString(TOKEN_REFRESH_TOKEN));
} catch (JSONException e) {
Log.e(TAG, "parseResult: Exception converting to Json " + e.toString());
}
return resultTokenMap;
}
/**
* Returns obtained values with a broadcast.
*
* @param tokenResponse : obtained values.
*/
private void postResult(HashMap<String, String> tokenResponse) {
Intent intent = new Intent(TOKEN_RECEIVED_MESSAGE);
intent.putExtra(TOKEN_RECEIVED_DATA,tokenResponse);
sendBroadcast(intent);
shutdownService();
}
}

View file

@ -1,151 +0,0 @@
package com.owncloud.android.operations;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.os.Handler;
import android.util.Log;
import com.owncloud.android.authenticator.oauth2.OAuth2Context;
import com.owncloud.android.authenticator.oauth2.OnOAuth2GetCodeResultListener;
import com.owncloud.android.authenticator.oauth2.OnOAuth2GetCodeResultListener.ResultOAuthType;
import com.owncloud.android.authenticator.oauth2.connection.ConnectorOAuth2;
/**
* Implements the communication with oAuth2 server to get User Code and other useful values.
*
* @author SolidGear S.L.
*
*/
public class OAuth2GetAuthorizationToken implements Runnable {
public static final String CODE_USER_CODE = "user_code";
public static final String CODE_CLIENT_ID = "client_id";
public static final String CODE_SCOPE = "scope";
public static final String CODE_VERIFICATION_URL = "verification_url";
public static final String CODE_EXPIRES_IN = "expires_in";
public static final String CODE_DEVICE_CODE = "device_code";
public static final String CODE_INTERVAL = "interval";
private static final String CODE_RESPONSE_TYPE = "response_type";
private static final String CODE_REDIRECT_URI = "redirect_uri";
private String mGrantType = OAuth2Context.OAUTH2_AUTH_CODE_GRANT_TYPE;
private static final String TAG = "OAuth2GetCodeRunnable";
private OnOAuth2GetCodeResultListener mListener;
private String mUrl;
private Handler mHandler;
private Context mContext;
//private JSONObject codeResponseJson = null;
ResultOAuthType mLatestResult;
public void setListener(OnOAuth2GetCodeResultListener listener, Handler handler) {
mListener = listener;
mHandler = handler;
}
public OAuth2GetAuthorizationToken(String url, Context context) {
mListener = null;
mHandler = null;
mUrl = url;
mContext = context;
}
@Override
public void run() {
if (!isOnline()) {
postResult(ResultOAuthType.NO_NETWORK_CONNECTION,null);
return;
}
if (mUrl.startsWith("http://") || mUrl.startsWith("https://")) {
mLatestResult = (mUrl.startsWith("https://"))? ResultOAuthType.OK_SSL : ResultOAuthType.OK_NO_SSL;
} else {
mUrl = "https://" + mUrl;
mLatestResult = ResultOAuthType.OK_SSL;
}
if (mGrantType.equals(OAuth2Context.OAUTH2_AUTH_CODE_GRANT_TYPE)) {
requestBrowserToGetAuthorizationCode();
} /*else if (mGrantType.equals(OAuth2Context.OAUTH_G_DEVICE_GETTOKEN_GRANT_TYPE)) {
getAuthorizationCode();
}*/
}
/// open the authorization endpoint in a web browser!
private void requestBrowserToGetAuthorizationCode() {
Uri uri = Uri.parse(mUrl);
Uri.Builder uriBuilder = uri.buildUpon();
uriBuilder.appendQueryParameter(CODE_RESPONSE_TYPE, OAuth2Context.OAUTH2_CODE_RESPONSE_TYPE);
uriBuilder.appendQueryParameter(CODE_REDIRECT_URI, OAuth2Context.MY_REDIRECT_URI);
uriBuilder.appendQueryParameter(CODE_CLIENT_ID, OAuth2Context.OAUTH2_F_CLIENT_ID);
uriBuilder.appendQueryParameter(CODE_SCOPE, OAuth2Context.OAUTH2_F_SCOPE);
//uriBuilder.appendQueryParameter(CODE_STATE, whateverwewant);
uri = uriBuilder.build();
Log.d(TAG, "Starting browser to view " + uri.toString());
Intent i = new Intent(Intent.ACTION_VIEW, uri);
mContext.startActivity(i);
postResult(mLatestResult, null);
}
/*
private void getAuthorizationCode() {
ConnectorOAuth2 connectorOAuth2 = new ConnectorOAuth2(mUrl);
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair(CODE_CLIENT_ID, OAuth2Context.OAUTH2_G_DEVICE_CLIENT_ID));
nameValuePairs.add(new BasicNameValuePair(CODE_SCOPE,OAuth2Context.OAUTH2_G_DEVICE_GETCODE_SCOPES));
UrlEncodedFormEntity params = new UrlEncodedFormEntity(nameValuePairs);
codeResponseJson = new JSONObject(connectorOAuth2.connPost(params));
} catch (JSONException e) {
Log.e(TAG, "JSONException converting to Json: " + e.toString());
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "UnsupportedEncodingException encoding URL values: " + e.toString());
} catch (Exception e) {
Log.e(TAG, "Exception : " + e.toString());
}
if (codeResponseJson == null) {
mLatestResult = ResultOAuthType.HOST_NOT_AVAILABLE;
}
postResult(mLatestResult, codeResponseJson);
}
*/
private boolean isOnline() {
ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
return cm != null && cm.getActiveNetworkInfo() != null && cm.getActiveNetworkInfo().isConnectedOrConnecting();
}
private void postResult(final ResultOAuthType result,final JSONObject codeResponseJson) {
if (mHandler != null && mListener != null) {
mHandler.post(new Runnable() {
@Override
public void run() {
mListener.onOAuth2GetCodeResult(result, codeResponseJson);
}
});
}
}
}

View file

@ -126,8 +126,6 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
private TextView mOAuthAuthEndpointText;
private TextView mOAuthTokenEndpointText;
/**
@ -264,7 +262,6 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
// state of oAuth2 components
mOAuth2StatusIcon = savedInstanceState.getInt(KEY_OAUTH2_STATUS_ICON);
mOAuth2StatusText = savedInstanceState.getInt(KEY_OAUTH2_STATUS_TEXT);
changeViewByOAuth2Check(mOAuth2Check.isChecked());
/* Leave old OAuth flow
// We store a JSon object with all the data returned from oAuth2 server when we get user_code.
@ -305,6 +302,9 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
@Override
protected void onResume() {
super.onResume();
changeViewByOAuth2Check(mOAuth2Check.isChecked());
// the state of mOAuth2Check is automatically recovered between configuration changes, but not before onCreate() finishes
/* 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.
if (tokenReceiver == null) {