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