39881153a45eb27d67af24fbc42cbc7a96cef50a
[pub/Android/ownCloud.git] / src / com / owncloud / android / operations / DetectAuthenticationMethodOperation.java
1 /* ownCloud Android client application
2 *
3 * @author David A. Velasco
4 * Copyright (C) 2014 ownCloud Inc.
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2,
8 * as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20 package com.owncloud.android.operations;
21
22 import java.util.ArrayList;
23
24 import com.owncloud.android.lib.common.OwnCloudClient;
25 import com.owncloud.android.lib.common.operations.OnRemoteOperationListener;
26 import com.owncloud.android.lib.common.operations.RemoteOperation;
27 import com.owncloud.android.lib.common.operations.RemoteOperationResult;
28 import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
29 import com.owncloud.android.lib.common.utils.Log_OC;
30 import com.owncloud.android.lib.resources.files.ExistenceCheckRemoteOperation;
31
32 import android.content.Context;
33 import android.net.Uri;
34
35 /**
36 * Operation to find out what authentication method requires
37 * the server to access files.
38 *
39 * Basically, tries to access to the root folder without authorization
40 * and analyzes the response.
41 *
42 * When successful, the instance of {@link RemoteOperationResult} passed
43 * through {@link OnRemoteOperationListener#onRemoteOperationFinish(RemoteOperation,
44 * RemoteOperationResult)} returns in {@link RemoteOperationResult#getData()}
45 * a value of {@link AuthenticationMethod}.
46 */
47 public class DetectAuthenticationMethodOperation extends RemoteOperation {
48
49 private static final String TAG = DetectAuthenticationMethodOperation.class.getSimpleName();
50
51 public enum AuthenticationMethod {
52 UNKNOWN,
53 NONE,
54 BASIC_HTTP_AUTH,
55 SAML_WEB_SSO,
56 BEARER_TOKEN
57 }
58
59 private Context mContext;
60
61 /**
62 * Constructor
63 *
64 * @param context Android context of the caller.
65 * @param webdavUrl
66 */
67 public DetectAuthenticationMethodOperation(Context context) {
68 mContext = context;
69 }
70
71
72 /**
73 * Performs the operation.
74 *
75 * Triggers a check of existence on the root folder of the server, granting
76 * that the request is not authenticated.
77 *
78 * Analyzes the result of check to find out what authentication method, if
79 * any, is requested by the server.
80 */
81 @Override
82 protected RemoteOperationResult run(OwnCloudClient client) {
83 RemoteOperationResult result = null;
84 AuthenticationMethod authMethod = AuthenticationMethod.UNKNOWN;
85
86 RemoteOperation operation = new ExistenceCheckRemoteOperation("", mContext, false);
87 client.clearCredentials();
88 client.setFollowRedirects(false);
89
90 // try to access the root folder, following redirections but not SAML SSO redirections
91 result = operation.execute(client);
92 String redirectedLocation = result.getRedirectedLocation();
93 while (redirectedLocation != null && redirectedLocation.length() > 0 &&
94 !result.isIdPRedirection()) {
95 client.setBaseUri(Uri.parse(result.getRedirectedLocation()));
96 result = operation.execute(client);
97 redirectedLocation = result.getRedirectedLocation();
98 }
99
100 // analyze response
101 if (result.getCode() == ResultCode.UNAUTHORIZED) {
102 String authRequest = ((result.getAuthenticateHeader()).trim()).toLowerCase();
103 if (authRequest.startsWith("basic")) {
104 authMethod = AuthenticationMethod.BASIC_HTTP_AUTH;
105
106 } else if (authRequest.startsWith("bearer")) {
107 authMethod = AuthenticationMethod.BEARER_TOKEN;
108 }
109 // else - fall back to UNKNOWN
110
111 } else if (result.isSuccess()) {
112 authMethod = AuthenticationMethod.NONE;
113
114 } else if (result.isIdPRedirection()) {
115 authMethod = AuthenticationMethod.SAML_WEB_SSO;
116 }
117 // else - fall back to UNKNOWN
118 Log_OC.d(TAG, "Authentication method found: " + authenticationMethodToString(authMethod));
119
120 if (!authMethod.equals(AuthenticationMethod.UNKNOWN)) {
121 result = new RemoteOperationResult(true, result.getHttpCode(), null);
122 }
123 ArrayList<Object> data = new ArrayList<Object>();
124 data.add(authMethod);
125 result.setData(data);
126 return result; // same result instance, so that other errors can be handled by the caller transparently
127 }
128
129
130 private String authenticationMethodToString(AuthenticationMethod value) {
131 switch (value){
132 case NONE:
133 return "NONE";
134 case BASIC_HTTP_AUTH:
135 return "BASIC_HTTP_AUTH";
136 case BEARER_TOKEN:
137 return "BEARER_TOKEN";
138 case SAML_WEB_SSO:
139 return "SAML_WEB_SSO";
140 default:
141 return "UNKNOWN";
142 }
143 }
144
145 }