Skip to content

Commit 8cf7a1c

Browse files
committed
Merge pull request owncloud#347 from owncloud/refactor_remote_saml_authentication
Refactored remote saml authentication
2 parents 6974339 + f601a31 commit 8cf7a1c

File tree

5 files changed

+190
-56
lines changed

5 files changed

+190
-56
lines changed

oc_framework/src/com/owncloud/android/oc_framework/accounts/AccountUtils.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,8 @@ public static String constructFullURLForAccount(Context context, Account account
111111

112112
public static class AccountNotFoundException extends AccountsException {
113113

114-
/** Generated - should be refreshed every time the class changes!! */
115-
private static final long serialVersionUID = -9013287181793186830L;
114+
/** Generated - should be refreshed every time the class changes!! */
115+
private static final long serialVersionUID = -1684392454798508693L;
116116

117117
private Account mFailedAccount;
118118

@@ -125,5 +125,4 @@ public Account getFailedAccount() {
125125
return mFailedAccount;
126126
}
127127
}
128-
129128
}

oc_framework/src/com/owncloud/android/oc_framework/operations/RemoteOperationResult.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.apache.commons.httpclient.HttpException;
3434
import org.apache.commons.httpclient.HttpStatus;
3535
import org.apache.jackrabbit.webdav.DavException;
36+
import org.json.JSONException;
3637

3738
import com.owncloud.android.oc_framework.accounts.AccountUtils.AccountNotFoundException;
3839
import com.owncloud.android.oc_framework.network.CertificateCombinedException;
@@ -51,9 +52,9 @@
5152
* @author David A. Velasco
5253
*/
5354
public class RemoteOperationResult implements Serializable {
54-
55+
5556
/** Generated - should be refreshed every time the class changes!! */
56-
private static final long serialVersionUID = -2469951225222759283L;
57+
private static final long serialVersionUID = -8257349554488668693L;
5758

5859
private static final String TAG = "RemoteOperationResult";
5960

@@ -294,6 +295,9 @@ public String getLogMessage() {
294295
} else if (mException instanceof AccountsException) {
295296
return "Exception while using account";
296297

298+
} else if (mException instanceof JSONException) {
299+
return "JSON exception";
300+
297301
} else {
298302
return "Unexpected exception";
299303
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
2+
/* ownCloud Android client application
3+
* Copyright (C) 2012-2013 ownCloud Inc.
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License version 2,
7+
* as published by the Free Software Foundation.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*
17+
*/
18+
package com.owncloud.android.oc_framework.operations.remote;
19+
20+
import java.io.IOException;
21+
22+
import org.apache.commons.httpclient.HttpException;
23+
import org.apache.commons.httpclient.methods.GetMethod;
24+
import org.apache.http.HttpStatus;
25+
import org.json.JSONException;
26+
import org.json.JSONObject;
27+
28+
import android.util.Log;
29+
30+
import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
31+
import com.owncloud.android.oc_framework.operations.RemoteOperation;
32+
import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
33+
34+
35+
/**
36+
* @author masensio
37+
*
38+
* Get the UserName for a SAML connection, from a JSON with the format:
39+
* id
40+
* display-name
41+
* email
42+
*/
43+
44+
public class GetUserNameRemoteOperation extends RemoteOperation {
45+
46+
private static final String TAG = GetUserNameRemoteOperation.class.getSimpleName();
47+
48+
// HEADER
49+
private static final String HEADER_OCS_API = "OCS-APIREQUEST";
50+
private static final String HEADER_OCS_API_VALUE = "true";
51+
52+
// OCS Route
53+
private static final String OCS_ROUTE ="/index.php/ocs/cloud/user?format=json";
54+
55+
// JSON Node names
56+
private static final String NODE_OCS = "ocs";
57+
private static final String NODE_DATA = "data";
58+
private static final String NODE_ID = "id";
59+
private static final String NODE_DISPLAY_NAME= "display-name";
60+
private static final String NODE_EMAIL= "email";
61+
62+
private String mUserName;
63+
64+
public String getUserName() {
65+
return mUserName;
66+
}
67+
68+
69+
public GetUserNameRemoteOperation() {
70+
}
71+
72+
@Override
73+
protected RemoteOperationResult run(WebdavClient client) {
74+
RemoteOperationResult result = null;
75+
int status = -1;
76+
77+
// Get Method
78+
GetMethod get = new GetMethod(client.getBaseUri() + OCS_ROUTE);
79+
Log.d(TAG, "URL ------> " + client.getBaseUri() + OCS_ROUTE);
80+
// Add the Header
81+
get.addRequestHeader(HEADER_OCS_API, HEADER_OCS_API_VALUE);
82+
83+
//Get the user
84+
try {
85+
status = client.executeMethod(get);
86+
if(isSuccess(status)) {
87+
Log.d(TAG, "Obtain RESPONSE");
88+
String response = get.getResponseBodyAsString();
89+
90+
Log.d(TAG, "GET RESPONSE.................... " + response);
91+
92+
// Parse the response
93+
JSONObject respJSON = new JSONObject(response);
94+
JSONObject respOCS = respJSON.getJSONObject(NODE_OCS);
95+
JSONObject respData = respOCS.getJSONObject(NODE_DATA);
96+
String id = respData.getString(NODE_ID);
97+
String displayName = respData.getString(NODE_DISPLAY_NAME);
98+
String email = respData.getString(NODE_EMAIL);
99+
100+
// Result
101+
result = new RemoteOperationResult(isSuccess(status), status, (get != null ? get.getResponseHeaders() : null));
102+
mUserName = displayName;
103+
104+
Log.d(TAG, "Response: " + id + " - " + displayName + " - " + email);
105+
106+
}
107+
} catch (HttpException e) {
108+
result = new RemoteOperationResult(e);
109+
e.printStackTrace();
110+
} catch (IOException e) {
111+
result = new RemoteOperationResult(e);
112+
e.printStackTrace();
113+
} catch (JSONException e) {
114+
result = new RemoteOperationResult(e);
115+
e.printStackTrace();
116+
} finally {
117+
get.releaseConnection();
118+
}
119+
120+
return result;
121+
}
122+
123+
private boolean isSuccess(int status) {
124+
return (status == HttpStatus.SC_OK);
125+
}
126+
127+
}

src/com/owncloud/android/authentication/AuthenticatorActivity.java

Lines changed: 44 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
6565
import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
6666
import com.owncloud.android.oc_framework.operations.remote.ExistenceCheckRemoteOperation;
67+
import com.owncloud.android.oc_framework.operations.remote.GetUserNameRemoteOperation;
6768
import com.owncloud.android.ui.dialog.SamlWebViewDialog;
6869
import com.owncloud.android.ui.dialog.SslValidatorDialog;
6970
import com.owncloud.android.ui.dialog.SslValidatorDialog.OnSslValidatorListener;
@@ -102,8 +103,6 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
102103
private static final String KEY_AUTH_STATUS_TEXT = "AUTH_STATUS_TEXT";
103104
private static final String KEY_AUTH_STATUS_ICON = "AUTH_STATUS_ICON";
104105
private static final String KEY_REFRESH_BUTTON_ENABLED = "KEY_REFRESH_BUTTON_ENABLED";
105-
106-
private static final String KEY_OC_USERNAME_EQUALS = "oc_username=";
107106

108107
private static final String AUTH_ON = "on";
109108
private static final String AUTH_OFF = "off";
@@ -792,10 +791,41 @@ public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationRe
792791
} else {
793792
onAuthorizationCheckFinish((ExistenceCheckRemoteOperation)operation, result);
794793
}
794+
} else if (operation instanceof GetUserNameRemoteOperation) {
795+
onGetUserNameFinish((GetUserNameRemoteOperation) operation, result);
796+
795797
}
798+
796799
}
797-
798-
800+
801+
private void onGetUserNameFinish(GetUserNameRemoteOperation operation, RemoteOperationResult result) {
802+
if (result.isSuccess()) {
803+
boolean success = false;
804+
String username = operation.getUserName();
805+
806+
if ( mAction == ACTION_CREATE) {
807+
mUsernameInput.setText(username);
808+
success = createAccount();
809+
} else {
810+
811+
if (!mUsernameInput.getText().toString().equals(username)) {
812+
// fail - not a new account, but an existing one; disallow
813+
result = new RemoteOperationResult(ResultCode.ACCOUNT_NOT_THE_SAME);
814+
updateAuthStatusIconAndText(result);
815+
showAuthStatus();
816+
Log_OC.d(TAG, result.getLogMessage());
817+
} else {
818+
updateToken();
819+
success = true;
820+
}
821+
}
822+
823+
if (success)
824+
finish();
825+
}
826+
827+
}
828+
799829
private void onSamlBasedFederatedSingleSignOnAuthorizationStart(RemoteOperation operation, RemoteOperationResult result) {
800830
try {
801831
dismissDialog(DIALOG_LOGIN_PROGRESS);
@@ -1120,7 +1150,8 @@ private void onAuthorizationCheckFinish(ExistenceCheckRemoteOperation operation,
11201150
success = createAccount();
11211151

11221152
} else {
1123-
success = updateToken();
1153+
updateToken();
1154+
success = true;
11241155
}
11251156

11261157
if (success) {
@@ -1166,7 +1197,7 @@ private void onAuthorizationCheckFinish(ExistenceCheckRemoteOperation operation,
11661197
* Sets the proper response to get that the Account Authenticator that started this activity saves
11671198
* a new authorization token for mAccount.
11681199
*/
1169-
private boolean updateToken() {
1200+
private void updateToken() {
11701201
Bundle response = new Bundle();
11711202
response.putString(AccountManager.KEY_ACCOUNT_NAME, mAccount.name);
11721203
response.putString(AccountManager.KEY_ACCOUNT_TYPE, mAccount.type);
@@ -1177,16 +1208,6 @@ private boolean updateToken() {
11771208
mAccountMgr.setAuthToken(mAccount, mAuthTokenType, mAuthToken);
11781209

11791210
} else if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType)) {
1180-
String username = getUserNameForSamlSso();
1181-
if (!mUsernameInput.getText().toString().equals(username)) {
1182-
// fail - not a new account, but an existing one; disallow
1183-
RemoteOperationResult result = new RemoteOperationResult(ResultCode.ACCOUNT_NOT_THE_SAME);
1184-
updateAuthStatusIconAndText(result);
1185-
showAuthStatus();
1186-
Log_OC.d(TAG, result.getLogMessage());
1187-
1188-
return false;
1189-
}
11901211

11911212
response.putString(AccountManager.KEY_AUTHTOKEN, mAuthToken);
11921213
// the next line is necessary; by now, notifications are calling directly to the AuthenticatorActivity to update, without AccountManager intervention
@@ -1198,7 +1219,6 @@ private boolean updateToken() {
11981219
}
11991220
setAccountAuthenticatorResult(response);
12001221

1201-
return true;
12021222
}
12031223

12041224

@@ -1216,10 +1236,7 @@ private boolean createAccount() {
12161236

12171237
Uri uri = Uri.parse(mHostBaseUrl);
12181238
String username = mUsernameInput.getText().toString().trim();
1219-
if (isSaml) {
1220-
username = getUserNameForSamlSso();
1221-
1222-
} else if (isOAuth) {
1239+
if (isOAuth) {
12231240
username = "OAuth_user" + (new java.util.Random(System.currentTimeMillis())).nextLong();
12241241
}
12251242
String accountName = username + "@" + uri.getHost();
@@ -1279,20 +1296,6 @@ private boolean createAccount() {
12791296
}
12801297
}
12811298

1282-
1283-
private String getUserNameForSamlSso() {
1284-
if (mAuthToken != null) {
1285-
String [] cookies = mAuthToken.split(";");
1286-
for (int i=0; i<cookies.length; i++) {
1287-
if (cookies[i].startsWith(KEY_OC_USERNAME_EQUALS )) {
1288-
String value = Uri.decode(cookies[i].substring(KEY_OC_USERNAME_EQUALS.length()));
1289-
return value;
1290-
}
1291-
}
1292-
}
1293-
return "";
1294-
}
1295-
12961299

12971300
/**
12981301
* {@inheritDoc}
@@ -1593,16 +1596,11 @@ public void onSamlDialogSuccess(String sessionCookie){
15931596

15941597
if (sessionCookie != null && sessionCookie.length() > 0) {
15951598
mAuthToken = sessionCookie;
1596-
boolean success = false;
1597-
if (mAction == ACTION_CREATE) {
1598-
success = createAccount();
1599-
1600-
} else {
1601-
success = updateToken();
1602-
}
1603-
if (success) {
1604-
finish();
1605-
}
1599+
1600+
GetUserNameRemoteOperation getUserOperation = new GetUserNameRemoteOperation();
1601+
WebdavClient client = OwnCloudClientFactory.createOwnCloudClient(Uri.parse(mHostBaseUrl), getApplicationContext(), true);
1602+
client.setSsoSessionCookie(mAuthToken);
1603+
getUserOperation.execute(client, this, mHandler);
16061604
}
16071605

16081606

@@ -1652,4 +1650,5 @@ public boolean onTouchEvent(MotionEvent event) {
16521650
}
16531651
return super.onTouchEvent(event);
16541652
}
1653+
16551654
}

0 commit comments

Comments
 (0)