mirror of
https://github.com/owncloud/android-library.git
synced 2025-06-07 16:06:08 +00:00
Merge pull request #300 from owncloud/new_arch/oauth_app_auth
Implement OAuth2 with AppAuth
This commit is contained in:
commit
8f9bed2d9f
3
gradle.properties
Normal file
3
gradle.properties
Normal file
@ -0,0 +1,3 @@
|
||||
android.enableJetifier=true
|
||||
android.useAndroidX=true
|
||||
org.gradle.jvmargs=-Xmx1536M
|
@ -8,6 +8,7 @@ dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
|
||||
api 'com.gitlab.ownclouders:dav4android:oc_support_1.0.1'
|
||||
api 'com.github.hannesa2:Logcat:1.6.0'
|
||||
api 'net.openid:appauth:0.7.1'
|
||||
}
|
||||
|
||||
allOpen {
|
||||
@ -24,6 +25,10 @@ android {
|
||||
|
||||
versionCode = 10000401
|
||||
versionName = "1.0.4.1"
|
||||
|
||||
// This is pretty ugly but manifest placeholders don't seem to work very well when using different modules
|
||||
// See https://github.com/openid/AppAuth-Android/issues/325
|
||||
manifestPlaceholders = [appAuthRedirectScheme: '']
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
|
@ -334,7 +334,6 @@ public class OwnCloudClient extends HttpClient {
|
||||
if (invalidated) {
|
||||
if (getCredentials().authTokenCanBeRefreshed() &&
|
||||
repeatCounter < MAX_REPEAT_COUNT_WITH_FRESH_CREDENTIALS) {
|
||||
|
||||
try {
|
||||
mAccount.loadCredentials(getContext());
|
||||
// if mAccount.getCredentials().length() == 0 --> refresh failed
|
||||
@ -342,7 +341,9 @@ public class OwnCloudClient extends HttpClient {
|
||||
credentialsWereRefreshed = true;
|
||||
|
||||
} catch (AccountsException | IOException e) {
|
||||
Timber.e(e, "Error while trying to refresh auth token for %s", mAccount.getSavedAccount().name);
|
||||
Timber.e(e, "Error while trying to refresh auth token for %s",
|
||||
mAccount.getSavedAccount().name
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,8 +37,7 @@ public class OwnCloudClientFactory {
|
||||
* @param context Android context where the OwnCloudClient is being created.
|
||||
* @return A OwnCloudClient object ready to be used
|
||||
*/
|
||||
public static OwnCloudClient createOwnCloudClient(Uri uri, Context context,
|
||||
boolean followRedirects) {
|
||||
public static OwnCloudClient createOwnCloudClient(Uri uri, Context context, boolean followRedirects) {
|
||||
OwnCloudClient client = new OwnCloudClient(uri);
|
||||
|
||||
client.setFollowRedirects(followRedirects);
|
||||
|
@ -315,9 +315,19 @@ public class AccountUtils {
|
||||
*/
|
||||
public static final String KEY_DISPLAY_NAME = "oc_display_name";
|
||||
|
||||
/**
|
||||
* OAuth2 user id
|
||||
**/
|
||||
public static final String KEY_USER_ID = "user_id";
|
||||
|
||||
/**
|
||||
* OAuth2 refresh token
|
||||
**/
|
||||
public static final String KEY_OAUTH2_REFRESH_TOKEN = "oc_oauth2_refresh_token";
|
||||
|
||||
/**
|
||||
* OAuth2 scope
|
||||
*/
|
||||
public static final String KEY_OAUTH2_SCOPE = "oc_oauth2_scope";
|
||||
}
|
||||
}
|
||||
|
@ -1,95 +0,0 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.authentication.oauth;
|
||||
|
||||
/**
|
||||
* @author David A. Velasco
|
||||
* @author Christian Schabesberger
|
||||
*/
|
||||
public class BearerCredentials {
|
||||
|
||||
public static final int HASH_SEED = 17;
|
||||
public static final int HASH_OFFSET = 37;
|
||||
|
||||
private String mAccessToken;
|
||||
|
||||
/**
|
||||
* The constructor with the bearer token
|
||||
*
|
||||
* @param token The bearer token
|
||||
*/
|
||||
public BearerCredentials(String token) {
|
||||
mAccessToken = (token == null) ? "" : token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the access token
|
||||
*
|
||||
* @return The access token
|
||||
*/
|
||||
public String getAccessToken() {
|
||||
return mAccessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get this object string.
|
||||
*
|
||||
* @return The access token
|
||||
*/
|
||||
public String toString() {
|
||||
return mAccessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does a hash of the access token.
|
||||
*
|
||||
* @return The hash code of the access token
|
||||
*/
|
||||
public int hashCode() {
|
||||
return HASH_SEED * HASH_OFFSET + mAccessToken.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* These credentials are assumed equal if accessToken is the same.
|
||||
*
|
||||
* @param o The other object to compare with.
|
||||
* @return 'True' if the object is equivalent.
|
||||
*/
|
||||
public boolean equals(Object o) {
|
||||
if (o == null) {
|
||||
return false;
|
||||
}
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (this.getClass().equals(o.getClass())) {
|
||||
BearerCredentials that = (BearerCredentials) o;
|
||||
if (mAccessToken.equals(that.mAccessToken)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* Copyright (C) 2017 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.authentication.oauth;
|
||||
|
||||
public class OAuth2ClientConfiguration {
|
||||
|
||||
private String mClientId;
|
||||
|
||||
private String mClientSecret;
|
||||
|
||||
private String mRedirectUri;
|
||||
|
||||
public OAuth2ClientConfiguration(String clientId, String clientSecret, String redirectUri) {
|
||||
mClientId = (clientId == null) ? "" : clientId;
|
||||
mClientSecret = (clientSecret == null) ? "" : clientSecret;
|
||||
mRedirectUri = (redirectUri == null) ? "" : redirectUri;
|
||||
}
|
||||
|
||||
public String getClientId() {
|
||||
return mClientId;
|
||||
}
|
||||
|
||||
public void setClientId(String clientId) {
|
||||
mClientId = (clientId == null) ? "" : clientId;
|
||||
}
|
||||
|
||||
public String getClientSecret() {
|
||||
return mClientSecret;
|
||||
}
|
||||
|
||||
public void setClientSecret(String clientSecret) {
|
||||
mClientSecret = (clientSecret == null) ? "" : clientSecret;
|
||||
}
|
||||
|
||||
public String getRedirectUri() {
|
||||
return mRedirectUri;
|
||||
}
|
||||
|
||||
public void setRedirectUri(String redirectUri) {
|
||||
this.mRedirectUri = (redirectUri == null) ? "" : redirectUri;
|
||||
}
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* Copyright (C) 2017 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.authentication.oauth;
|
||||
|
||||
/**
|
||||
* Constant values for OAuth 2 protocol.
|
||||
* <p>
|
||||
* Includes required and optional parameter NAMES used in the 'authorization code' grant type.
|
||||
*/
|
||||
|
||||
public class OAuth2Constants {
|
||||
|
||||
/// Parameters to send to the Authorization Endpoint
|
||||
public static final String KEY_RESPONSE_TYPE = "response_type";
|
||||
public static final String KEY_REDIRECT_URI = "redirect_uri";
|
||||
public static final String KEY_CLIENT_ID = "client_id";
|
||||
public static final String KEY_SCOPE = "scope";
|
||||
public static final String KEY_STATE = "state";
|
||||
|
||||
/// Additional parameters to send to the Token Endpoint
|
||||
public static final String KEY_GRANT_TYPE = "grant_type";
|
||||
public static final String KEY_CODE = "code";
|
||||
|
||||
// Used to get the Access Token using Refresh Token
|
||||
public static final String OAUTH2_REFRESH_TOKEN_GRANT_TYPE = "refresh_token";
|
||||
|
||||
/// Parameters received in an OK response from the Token Endpoint
|
||||
public static final String KEY_ACCESS_TOKEN = "access_token";
|
||||
public static final String KEY_TOKEN_TYPE = "token_type";
|
||||
public static final String KEY_EXPIRES_IN = "expires_in";
|
||||
public static final String KEY_REFRESH_TOKEN = "refresh_token";
|
||||
|
||||
/// Parameters in an ERROR response
|
||||
public static final String KEY_ERROR = "error";
|
||||
public static final String KEY_ERROR_DESCRIPTION = "error_description";
|
||||
public static final String KEY_ERROR_URI = "error_uri";
|
||||
public static final String VALUE_ERROR_ACCESS_DENIED = "access_denied";
|
||||
|
||||
/// Extra not standard
|
||||
public static final String KEY_USER_ID = "user_id";
|
||||
|
||||
/// Depends on oauth2 grant type
|
||||
public static final String OAUTH2_RESPONSE_TYPE_CODE = "code";
|
||||
}
|
@ -1,141 +0,0 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* @author Christian Schabesberger
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.authentication.oauth;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.authentication.OwnCloudBasicCredentials;
|
||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
|
||||
import com.owncloud.android.lib.common.http.methods.nonwebdav.PostMethod;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
||||
import okhttp3.MultipartBody;
|
||||
import okhttp3.RequestBody;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
|
||||
public class OAuth2GetAccessTokenOperation extends RemoteOperation<Map<String, String>> {
|
||||
|
||||
private final String mAccessTokenEndpointPath;
|
||||
private final OAuth2ResponseParser mResponseParser;
|
||||
private String mGrantType;
|
||||
private String mCode;
|
||||
private String mClientId;
|
||||
private String mClientSecret;
|
||||
private String mRedirectUri;
|
||||
|
||||
public OAuth2GetAccessTokenOperation(
|
||||
String grantType,
|
||||
String code,
|
||||
String clientId,
|
||||
String secretId,
|
||||
String redirectUri,
|
||||
String accessTokenEndpointPath
|
||||
) {
|
||||
mClientId = clientId;
|
||||
mClientSecret = secretId;
|
||||
mRedirectUri = redirectUri;
|
||||
mGrantType = grantType;
|
||||
mCode = code;
|
||||
|
||||
mAccessTokenEndpointPath =
|
||||
accessTokenEndpointPath != null ?
|
||||
accessTokenEndpointPath :
|
||||
OwnCloudOAuth2Provider.ACCESS_TOKEN_ENDPOINT_PATH
|
||||
;
|
||||
|
||||
mResponseParser = new OAuth2ResponseParser();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
||||
RemoteOperationResult<Map<String, String>> result = null;
|
||||
|
||||
try {
|
||||
|
||||
final RequestBody requestBody = new MultipartBody.Builder()
|
||||
.setType(MultipartBody.FORM)
|
||||
.addFormDataPart(OAuth2Constants.KEY_GRANT_TYPE, mGrantType)
|
||||
.addFormDataPart(OAuth2Constants.KEY_CODE, mCode)
|
||||
.addFormDataPart(OAuth2Constants.KEY_REDIRECT_URI, mRedirectUri)
|
||||
.addFormDataPart(OAuth2Constants.KEY_CLIENT_ID, mClientId)
|
||||
.build();
|
||||
|
||||
Uri.Builder uriBuilder = client.getBaseUri().buildUpon();
|
||||
uriBuilder.appendEncodedPath(mAccessTokenEndpointPath);
|
||||
|
||||
final PostMethod postMethod = new PostMethod(new URL(
|
||||
client.getBaseUri().buildUpon()
|
||||
.appendEncodedPath(mAccessTokenEndpointPath)
|
||||
.build()
|
||||
.toString()));
|
||||
|
||||
postMethod.setRequestBody(requestBody);
|
||||
|
||||
OwnCloudCredentials oauthCredentials =
|
||||
new OwnCloudBasicCredentials(mClientId, mClientSecret);
|
||||
OwnCloudCredentials oldCredentials = switchClientCredentials(oauthCredentials);
|
||||
client.executeHttpMethod(postMethod);
|
||||
switchClientCredentials(oldCredentials);
|
||||
|
||||
String response = postMethod.getResponseBodyAsString();
|
||||
if (response != null && response.length() > 0) {
|
||||
JSONObject tokenJson = new JSONObject(response);
|
||||
Map<String, String> accessTokenResult =
|
||||
mResponseParser.parseAccessTokenResult(tokenJson);
|
||||
if (accessTokenResult.get(OAuth2Constants.KEY_ERROR) != null ||
|
||||
accessTokenResult.get(OAuth2Constants.KEY_ACCESS_TOKEN) == null) {
|
||||
result = new RemoteOperationResult<>(ResultCode.OAUTH2_ERROR);
|
||||
|
||||
} else {
|
||||
result = new RemoteOperationResult<>(ResultCode.OK);
|
||||
result.setData(accessTokenResult);
|
||||
}
|
||||
|
||||
} else {
|
||||
result = new RemoteOperationResult<>(ResultCode.OK);
|
||||
client.exhaustResponse(postMethod.getResponseBodyAsStream());
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
result = new RemoteOperationResult<>(e);
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private OwnCloudCredentials switchClientCredentials(OwnCloudCredentials newCredentials) {
|
||||
OwnCloudCredentials previousCredentials = getClient().getCredentials();
|
||||
getClient().setCredentials(newCredentials);
|
||||
return previousCredentials;
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* Copyright (C) 2017 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.authentication.oauth;
|
||||
|
||||
public enum OAuth2GrantType {
|
||||
AUTHORIZATION_CODE("authorization_code"),
|
||||
IMPLICIT("implicit"),
|
||||
PASSWORD("password"),
|
||||
CLIENT_CREDENTIAL("client_credentials"),
|
||||
REFRESH_TOKEN("refresh_token") // not a grant type conceptually, but used as such to refresh access tokens
|
||||
;
|
||||
|
||||
private String mValue;
|
||||
|
||||
OAuth2GrantType(String value) {
|
||||
mValue = value;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return mValue;
|
||||
}
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* Copyright (C) 2017 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.authentication.oauth;
|
||||
|
||||
public interface OAuth2Provider {
|
||||
|
||||
/**
|
||||
* {@link OAuth2RequestBuilder} implementation for this provider.
|
||||
*
|
||||
* @return {@link OAuth2RequestBuilder} implementation.
|
||||
*/
|
||||
OAuth2RequestBuilder getOperationBuilder();
|
||||
|
||||
/**
|
||||
* Configuration of the client that is using this {@link OAuth2Provider}
|
||||
* return Configuration of the client that is usinng this {@link OAuth2Provider}
|
||||
*/
|
||||
OAuth2ClientConfiguration getClientConfiguration();
|
||||
|
||||
/**
|
||||
* Set configuration of the client that will use this {@link OAuth2Provider}
|
||||
*
|
||||
* @param oAuth2ClientConfiguration Configuration of the client that will use this {@link OAuth2Provider}
|
||||
*/
|
||||
void setClientConfiguration(OAuth2ClientConfiguration oAuth2ClientConfiguration);
|
||||
|
||||
/**
|
||||
* base URI to authorization server.
|
||||
*
|
||||
* @return Base URL to authorization server.
|
||||
*/
|
||||
String getAuthorizationServerUri();
|
||||
|
||||
/**
|
||||
* Set base URI to authorization server.
|
||||
*
|
||||
* @param authorizationServerUri Set base URL to authorization server.
|
||||
*/
|
||||
void setAuthorizationServerUri(String authorizationServerUri);
|
||||
|
||||
}
|
@ -1,121 +0,0 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* Copyright (C) 2017 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.authentication.oauth;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class OAuth2ProvidersRegistry {
|
||||
|
||||
private Map<String, OAuth2Provider> mProviders = new HashMap<>();
|
||||
|
||||
private OAuth2Provider mDefaultProvider = null;
|
||||
|
||||
private OAuth2ProvidersRegistry() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Singleton accesor.
|
||||
*
|
||||
* @return Singleton isntance of {@link OAuth2ProvidersRegistry}
|
||||
*/
|
||||
public static OAuth2ProvidersRegistry getInstance() {
|
||||
return LazyHolder.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an {@link OAuth2Provider} with the name passed as parameter.
|
||||
*
|
||||
* @param name Name to bind 'oAuthProvider' in the registry.
|
||||
* @param oAuth2Provider An {@link OAuth2Provider} instance to keep in the registry.
|
||||
* @throws IllegalArgumentException if 'name' or 'oAuthProvider' are null.
|
||||
*/
|
||||
public void registerProvider(String name, OAuth2Provider oAuth2Provider) {
|
||||
if (name == null) {
|
||||
throw new IllegalArgumentException("Name must not be NULL");
|
||||
}
|
||||
if (oAuth2Provider == null) {
|
||||
throw new IllegalArgumentException("oAuth2Provider must not be NULL");
|
||||
}
|
||||
|
||||
mProviders.put(name, oAuth2Provider);
|
||||
if (mProviders.size() == 1) {
|
||||
mDefaultProvider = oAuth2Provider;
|
||||
}
|
||||
}
|
||||
|
||||
public OAuth2Provider unregisterProvider(String name) {
|
||||
OAuth2Provider unregisteredProvider = mProviders.remove(name);
|
||||
if (mProviders.size() == 0) {
|
||||
mDefaultProvider = null;
|
||||
} else if (unregisteredProvider != null && unregisteredProvider == mDefaultProvider) {
|
||||
mDefaultProvider = mProviders.values().iterator().next();
|
||||
}
|
||||
return unregisteredProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default {@link OAuth2Provider}.
|
||||
*
|
||||
* @return Default provider, or NULL if there is no provider.
|
||||
*/
|
||||
public OAuth2Provider getProvider() {
|
||||
return mDefaultProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get {@link OAuth2Provider} registered with the name passed as parameter.
|
||||
*
|
||||
* @param name Name used to register the desired {@link OAuth2Provider}
|
||||
* @return {@link OAuth2Provider} registered with the name 'name'
|
||||
*/
|
||||
public OAuth2Provider getProvider(String name) {
|
||||
return mProviders.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link OAuth2Provider} registered with the name passed as parameter as the default provider
|
||||
*
|
||||
* @param name Name used to register the {@link OAuth2Provider} to set as default.
|
||||
* @return {@link OAuth2Provider} set as default, or NULL if no provider was registered with 'name'.
|
||||
*/
|
||||
public OAuth2Provider setDefaultProvider(String name) {
|
||||
OAuth2Provider toDefault = mProviders.get(name);
|
||||
if (toDefault != null) {
|
||||
mDefaultProvider = toDefault;
|
||||
}
|
||||
return toDefault;
|
||||
}
|
||||
|
||||
/**
|
||||
* See https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom
|
||||
*/
|
||||
private static class LazyHolder {
|
||||
private static final OAuth2ProvidersRegistry INSTANCE = new OAuth2ProvidersRegistry();
|
||||
}
|
||||
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* Copyright (C) 2017 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.authentication.oauth;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class OAuth2QueryParser {
|
||||
|
||||
private Map<String, String> mOAuth2ParsedAuthorizationResponse;
|
||||
|
||||
public OAuth2QueryParser() {
|
||||
mOAuth2ParsedAuthorizationResponse = new HashMap<>();
|
||||
}
|
||||
|
||||
public Map<String, String> parse(String query) {
|
||||
mOAuth2ParsedAuthorizationResponse.clear();
|
||||
|
||||
if (query != null) {
|
||||
String[] pairs = query.split("&");
|
||||
int i = 0;
|
||||
String key = "";
|
||||
String value;
|
||||
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;
|
||||
} else if (j == 1) {
|
||||
value = p;
|
||||
mOAuth2ParsedAuthorizationResponse.put(key, value);
|
||||
}
|
||||
|
||||
Timber.v("[" + i + "," + j + "] = " + p);
|
||||
j++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return mOAuth2ParsedAuthorizationResponse;
|
||||
}
|
||||
|
||||
}
|
@ -1,126 +0,0 @@
|
||||
/**
|
||||
* ownCloud Android client application
|
||||
*
|
||||
* @author David González Verdugo
|
||||
* @author Christian Schabesberger
|
||||
* <p>
|
||||
* Copyright (C) 2019 ownCloud GmbH.
|
||||
* <p>
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
* <p>
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* <p>
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.authentication.oauth;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.authentication.OwnCloudBasicCredentials;
|
||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
|
||||
import com.owncloud.android.lib.common.http.methods.nonwebdav.PostMethod;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
||||
import okhttp3.MultipartBody;
|
||||
import okhttp3.RequestBody;
|
||||
import org.json.JSONObject;
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
|
||||
public class OAuth2RefreshAccessTokenOperation extends RemoteOperation<Map<String, String>> {
|
||||
|
||||
private final String mAccessTokenEndpointPath;
|
||||
private final OAuth2ResponseParser mResponseParser;
|
||||
private String mClientId;
|
||||
private String mClientSecret;
|
||||
private String mRefreshToken;
|
||||
|
||||
public OAuth2RefreshAccessTokenOperation(
|
||||
String clientId,
|
||||
String secretId,
|
||||
String refreshToken,
|
||||
String accessTokenEndpointPath
|
||||
) {
|
||||
|
||||
mClientId = clientId;
|
||||
mClientSecret = secretId;
|
||||
mRefreshToken = refreshToken;
|
||||
|
||||
mAccessTokenEndpointPath =
|
||||
accessTokenEndpointPath != null ?
|
||||
accessTokenEndpointPath :
|
||||
OwnCloudOAuth2Provider.ACCESS_TOKEN_ENDPOINT_PATH
|
||||
;
|
||||
|
||||
mResponseParser = new OAuth2ResponseParser();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RemoteOperationResult<Map<String, String>> run(OwnCloudClient client) {
|
||||
|
||||
try {
|
||||
final RequestBody requestBody = new MultipartBody.Builder()
|
||||
.setType(MultipartBody.FORM)
|
||||
.addFormDataPart(OAuth2Constants.KEY_GRANT_TYPE,
|
||||
OAuth2GrantType.REFRESH_TOKEN.getValue())
|
||||
.addFormDataPart(OAuth2Constants.KEY_CLIENT_ID, mClientId)
|
||||
.addFormDataPart(OAuth2Constants.KEY_REFRESH_TOKEN, mRefreshToken)
|
||||
.build();
|
||||
|
||||
Uri.Builder uriBuilder = client.getBaseUri().buildUpon();
|
||||
uriBuilder.appendEncodedPath(mAccessTokenEndpointPath);
|
||||
|
||||
final PostMethod postMethod = new PostMethod(new URL(
|
||||
client.getBaseUri().buildUpon()
|
||||
.appendEncodedPath(mAccessTokenEndpointPath)
|
||||
.build()
|
||||
.toString()));
|
||||
postMethod.setRequestBody(requestBody);
|
||||
|
||||
final OwnCloudCredentials oauthCredentials = new OwnCloudBasicCredentials(mClientId, mClientSecret);
|
||||
|
||||
final OwnCloudCredentials oldCredentials = switchClientCredentials(oauthCredentials);
|
||||
client.executeHttpMethod(postMethod);
|
||||
switchClientCredentials(oldCredentials);
|
||||
|
||||
final String responseData = postMethod.getResponseBodyAsString();
|
||||
Timber.d("OAUTH2: raw response from POST TOKEN: %s", responseData);
|
||||
|
||||
if (responseData != null && responseData.length() > 0) {
|
||||
final JSONObject tokenJson = new JSONObject(responseData);
|
||||
|
||||
final Map<String, String> accessTokenResult =
|
||||
mResponseParser.parseAccessTokenResult(tokenJson);
|
||||
|
||||
final RemoteOperationResult<Map<String, String>> result = new RemoteOperationResult<>(ResultCode.OK);
|
||||
result.setData(accessTokenResult);
|
||||
return (accessTokenResult.get(OAuth2Constants.KEY_ERROR) != null ||
|
||||
accessTokenResult.get(OAuth2Constants.KEY_ACCESS_TOKEN) == null)
|
||||
? new RemoteOperationResult<>(ResultCode.OAUTH2_ERROR)
|
||||
: result;
|
||||
} else {
|
||||
return new RemoteOperationResult<>(postMethod);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
return new RemoteOperationResult<>(e);
|
||||
}
|
||||
}
|
||||
|
||||
private OwnCloudCredentials switchClientCredentials(OwnCloudCredentials newCredentials) {
|
||||
OwnCloudCredentials previousCredentials = getClient().getCredentials();
|
||||
getClient().setCredentials(newCredentials);
|
||||
return previousCredentials;
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* Copyright (C) 2017 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.authentication.oauth;
|
||||
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||
|
||||
public interface OAuth2RequestBuilder {
|
||||
|
||||
void setRequest(OAuthRequest operation);
|
||||
|
||||
void setGrantType(OAuth2GrantType grantType);
|
||||
|
||||
void setAuthorizationCode(String code);
|
||||
|
||||
void setRefreshToken(String refreshToken);
|
||||
|
||||
RemoteOperation buildOperation();
|
||||
|
||||
String buildUri();
|
||||
|
||||
enum OAuthRequest {
|
||||
GET_AUTHORIZATION_CODE, CREATE_ACCESS_TOKEN, REFRESH_ACCESS_TOKEN
|
||||
}
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
/**
|
||||
* ownCloud Android client application
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* <p>
|
||||
* Copyright (C) 2017 ownCloud GmbH.
|
||||
* <p>
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
* <p>
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* <p>
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.authentication.oauth;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
class OAuth2ResponseParser {
|
||||
|
||||
Map<String, String> parseAccessTokenResult(JSONObject tokenJson) throws JSONException {
|
||||
Map<String, String> resultTokenMap = new HashMap<>();
|
||||
|
||||
if (tokenJson.has(OAuth2Constants.KEY_ACCESS_TOKEN)) {
|
||||
resultTokenMap.put(OAuth2Constants.KEY_ACCESS_TOKEN, tokenJson.
|
||||
getString(OAuth2Constants.KEY_ACCESS_TOKEN));
|
||||
}
|
||||
if (tokenJson.has(OAuth2Constants.KEY_TOKEN_TYPE)) {
|
||||
resultTokenMap.put(OAuth2Constants.KEY_TOKEN_TYPE, tokenJson.
|
||||
getString(OAuth2Constants.KEY_TOKEN_TYPE));
|
||||
}
|
||||
if (tokenJson.has(OAuth2Constants.KEY_EXPIRES_IN)) {
|
||||
resultTokenMap.put(OAuth2Constants.KEY_EXPIRES_IN, tokenJson.
|
||||
getString(OAuth2Constants.KEY_EXPIRES_IN));
|
||||
}
|
||||
if (tokenJson.has(OAuth2Constants.KEY_REFRESH_TOKEN)) {
|
||||
resultTokenMap.put(OAuth2Constants.KEY_REFRESH_TOKEN, tokenJson.
|
||||
getString(OAuth2Constants.KEY_REFRESH_TOKEN));
|
||||
}
|
||||
if (tokenJson.has(OAuth2Constants.KEY_SCOPE)) {
|
||||
resultTokenMap.put(OAuth2Constants.KEY_SCOPE, tokenJson.
|
||||
getString(OAuth2Constants.KEY_SCOPE));
|
||||
}
|
||||
if (tokenJson.has(OAuth2Constants.KEY_ERROR)) {
|
||||
resultTokenMap.put(OAuth2Constants.KEY_ERROR, tokenJson.
|
||||
getString(OAuth2Constants.KEY_ERROR));
|
||||
}
|
||||
if (tokenJson.has(OAuth2Constants.KEY_ERROR_DESCRIPTION)) {
|
||||
resultTokenMap.put(OAuth2Constants.KEY_ERROR_DESCRIPTION, tokenJson.
|
||||
getString(OAuth2Constants.KEY_ERROR_DESCRIPTION));
|
||||
}
|
||||
if (tokenJson.has(OAuth2Constants.KEY_ERROR_URI)) {
|
||||
resultTokenMap.put(OAuth2Constants.KEY_ERROR_URI, tokenJson.
|
||||
getString(OAuth2Constants.KEY_ERROR_URI));
|
||||
}
|
||||
|
||||
if (tokenJson.has(OAuth2Constants.KEY_USER_ID)) { // not standard
|
||||
resultTokenMap.put(OAuth2Constants.KEY_USER_ID, tokenJson.
|
||||
getString(OAuth2Constants.KEY_USER_ID));
|
||||
}
|
||||
|
||||
return resultTokenMap;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
package com.owncloud.android.lib.common.authentication.oauth
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import com.owncloud.android.lib.common.network.AdvancedX509TrustManager
|
||||
import com.owncloud.android.lib.common.network.NetworkUtils
|
||||
import net.openid.appauth.connectivity.ConnectionBuilder
|
||||
import timber.log.Timber
|
||||
import java.io.IOException
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.URL
|
||||
import java.security.NoSuchAlgorithmException
|
||||
import java.util.Objects
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.net.ssl.HostnameVerifier
|
||||
import javax.net.ssl.HttpsURLConnection
|
||||
import javax.net.ssl.SSLContext
|
||||
import javax.net.ssl.TrustManager
|
||||
import javax.net.ssl.X509TrustManager
|
||||
|
||||
/**
|
||||
* Based on [net.openid.appauth.connectivity.DefaultConnectionBuilder] but permitting http connections in addition
|
||||
* to https connections
|
||||
*/
|
||||
class OAuthConnectionBuilder(val context: Context) : ConnectionBuilder {
|
||||
/**
|
||||
* The singleton instance of the default connection builder.
|
||||
*/
|
||||
private val CONNECTION_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(15).toInt()
|
||||
private val READ_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(10).toInt()
|
||||
private val HTTPS_SCHEME = "https"
|
||||
|
||||
@Throws(IOException::class)
|
||||
override fun openConnection(uri: Uri): HttpURLConnection {
|
||||
val conn: HttpURLConnection
|
||||
|
||||
if (Objects.equals(uri.scheme, HTTPS_SCHEME)) {
|
||||
conn = URL(uri.toString()).openConnection() as HttpsURLConnection
|
||||
try {
|
||||
val trustManager: X509TrustManager = AdvancedX509TrustManager(
|
||||
NetworkUtils.getKnownServersStore(context)
|
||||
)
|
||||
val sslContext: SSLContext
|
||||
sslContext = try {
|
||||
SSLContext.getInstance("TLSv1.2")
|
||||
} catch (tlsv12Exception: NoSuchAlgorithmException) {
|
||||
try {
|
||||
Timber.w("TLSv1.2 is not supported in this device; falling through TLSv1.1")
|
||||
SSLContext.getInstance("TLSv1.1")
|
||||
} catch (tlsv11Exception: NoSuchAlgorithmException) {
|
||||
Timber.w("TLSv1.1 is not supported in this device; falling through TLSv1.0")
|
||||
SSLContext.getInstance("TLSv1")
|
||||
// should be available in any device; see reference of supported protocols in
|
||||
// http://developer.android.com/reference/javax/net/ssl/SSLSocket.html
|
||||
}
|
||||
}
|
||||
sslContext.init(null, arrayOf<TrustManager>(trustManager), null)
|
||||
conn.hostnameVerifier = HostnameVerifier { _, _ -> true } // Do not verify the host for now
|
||||
conn.sslSocketFactory = sslContext.socketFactory
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Could not setup SSL system")
|
||||
}
|
||||
} else {
|
||||
conn = URL(uri.toString()).openConnection() as HttpURLConnection
|
||||
}
|
||||
|
||||
return conn.apply {
|
||||
connectTimeout = CONNECTION_TIMEOUT_MS
|
||||
readTimeout = READ_TIMEOUT_MS
|
||||
instanceFollowRedirects = false
|
||||
}
|
||||
}
|
||||
}
|
@ -1,94 +0,0 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* Copyright (C) 2017 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.authentication.oauth;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
public class OwnCloudOAuth2Provider implements OAuth2Provider {
|
||||
|
||||
public static final String NAME = OAuth2Provider.class.getName();
|
||||
|
||||
public static final String ACCESS_TOKEN_ENDPOINT_PATH = "index.php/apps/oauth2/api/v1/token";
|
||||
private static final String AUTHORIZATION_CODE_ENDPOINT_PATH = "index.php/apps/oauth2/authorize";
|
||||
|
||||
private String mAuthorizationServerUrl = "";
|
||||
private String mAccessTokenEndpointPath = ACCESS_TOKEN_ENDPOINT_PATH;
|
||||
private String mAuthorizationCodeEndpointPath = AUTHORIZATION_CODE_ENDPOINT_PATH;
|
||||
|
||||
private OAuth2ClientConfiguration mClientConfiguration;
|
||||
|
||||
@Override
|
||||
public OAuth2RequestBuilder getOperationBuilder() {
|
||||
return new OwnCloudOAuth2RequestBuilder(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2ClientConfiguration getClientConfiguration() {
|
||||
return mClientConfiguration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClientConfiguration(OAuth2ClientConfiguration oAuth2ClientConfiguration) {
|
||||
mClientConfiguration = oAuth2ClientConfiguration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthorizationServerUri() {
|
||||
return mAuthorizationServerUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAuthorizationServerUri(String authorizationServerUri) {
|
||||
mAuthorizationServerUrl = authorizationServerUri;
|
||||
}
|
||||
|
||||
public String getAccessTokenEndpointPath() {
|
||||
return mAccessTokenEndpointPath;
|
||||
}
|
||||
|
||||
public void setAccessTokenEndpointPath(String accessTokenEndpointPath) {
|
||||
if (accessTokenEndpointPath == null || accessTokenEndpointPath.length() <= 0) {
|
||||
Timber.w("Setting invalid access token endpoint path, going on with default");
|
||||
mAccessTokenEndpointPath = ACCESS_TOKEN_ENDPOINT_PATH;
|
||||
} else {
|
||||
mAccessTokenEndpointPath = accessTokenEndpointPath;
|
||||
}
|
||||
}
|
||||
|
||||
public String getAuthorizationCodeEndpointPath() {
|
||||
return mAuthorizationCodeEndpointPath;
|
||||
}
|
||||
|
||||
public void setAuthorizationCodeEndpointPath(String authorizationCodeEndpointPath) {
|
||||
if (authorizationCodeEndpointPath == null || authorizationCodeEndpointPath.length() <= 0) {
|
||||
Timber.w("Setting invalid authorization code endpoint path, going on with default");
|
||||
mAuthorizationCodeEndpointPath = AUTHORIZATION_CODE_ENDPOINT_PATH;
|
||||
} else {
|
||||
mAuthorizationCodeEndpointPath = authorizationCodeEndpointPath;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,155 +0,0 @@
|
||||
/* ownCloud Android Library is available under MIT license
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* Copyright (C) 2017 ownCloud GmbH.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.lib.common.authentication.oauth;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||
|
||||
public class OwnCloudOAuth2RequestBuilder implements OAuth2RequestBuilder {
|
||||
|
||||
private OwnCloudOAuth2Provider mOAuth2Provider;
|
||||
|
||||
private OAuthRequest mRequest;
|
||||
private OAuth2GrantType mGrantType = OAuth2GrantType.AUTHORIZATION_CODE;
|
||||
private String mCode;
|
||||
private String mRefreshToken;
|
||||
|
||||
public OwnCloudOAuth2RequestBuilder(OwnCloudOAuth2Provider ownCloudOAuth2Provider) {
|
||||
mOAuth2Provider = ownCloudOAuth2Provider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRequest(OAuthRequest request) {
|
||||
mRequest = request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGrantType(OAuth2GrantType grantType) {
|
||||
mGrantType = grantType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAuthorizationCode(String code) {
|
||||
mCode = code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRefreshToken(String refreshToken) {
|
||||
mRefreshToken = refreshToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RemoteOperation buildOperation() {
|
||||
if (mGrantType != OAuth2GrantType.AUTHORIZATION_CODE &&
|
||||
mGrantType != OAuth2GrantType.REFRESH_TOKEN) {
|
||||
throw new UnsupportedOperationException(
|
||||
"Unsupported grant type. Only " +
|
||||
OAuth2GrantType.AUTHORIZATION_CODE.getValue() + " and " +
|
||||
OAuth2GrantType.REFRESH_TOKEN + " are supported"
|
||||
);
|
||||
}
|
||||
OAuth2ClientConfiguration clientConfiguration = mOAuth2Provider.getClientConfiguration();
|
||||
|
||||
switch (mRequest) {
|
||||
case CREATE_ACCESS_TOKEN:
|
||||
return new OAuth2GetAccessTokenOperation(
|
||||
mGrantType.getValue(),
|
||||
mCode,
|
||||
clientConfiguration.getClientId(),
|
||||
clientConfiguration.getClientSecret(),
|
||||
clientConfiguration.getRedirectUri(),
|
||||
mOAuth2Provider.getAccessTokenEndpointPath()
|
||||
);
|
||||
|
||||
case REFRESH_ACCESS_TOKEN:
|
||||
return new OAuth2RefreshAccessTokenOperation(
|
||||
clientConfiguration.getClientId(),
|
||||
clientConfiguration.getClientSecret(),
|
||||
mRefreshToken,
|
||||
mOAuth2Provider.getAccessTokenEndpointPath()
|
||||
);
|
||||
default:
|
||||
throw new UnsupportedOperationException(
|
||||
"Unsupported request"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildUri() {
|
||||
if (OAuth2GrantType.AUTHORIZATION_CODE != mGrantType) {
|
||||
throw new UnsupportedOperationException(
|
||||
"Unsupported grant type. Only " +
|
||||
OAuth2GrantType.AUTHORIZATION_CODE.getValue() + " is supported by this provider"
|
||||
);
|
||||
}
|
||||
OAuth2ClientConfiguration clientConfiguration = mOAuth2Provider.getClientConfiguration();
|
||||
Uri uri;
|
||||
Uri.Builder uriBuilder;
|
||||
switch (mRequest) {
|
||||
case GET_AUTHORIZATION_CODE:
|
||||
uri = Uri.parse(mOAuth2Provider.getAuthorizationServerUri());
|
||||
uriBuilder = uri.buildUpon();
|
||||
uriBuilder.appendEncodedPath(mOAuth2Provider.getAuthorizationCodeEndpointPath());
|
||||
uriBuilder.appendQueryParameter(
|
||||
OAuth2Constants.KEY_RESPONSE_TYPE, OAuth2Constants.OAUTH2_RESPONSE_TYPE_CODE
|
||||
);
|
||||
uriBuilder.appendQueryParameter(
|
||||
OAuth2Constants.KEY_REDIRECT_URI, clientConfiguration.getRedirectUri()
|
||||
);
|
||||
uriBuilder.appendQueryParameter(
|
||||
OAuth2Constants.KEY_CLIENT_ID, clientConfiguration.getClientId()
|
||||
);
|
||||
|
||||
uri = uriBuilder.build();
|
||||
return uri.toString();
|
||||
|
||||
case CREATE_ACCESS_TOKEN:
|
||||
uri = Uri.parse(mOAuth2Provider.getAuthorizationServerUri());
|
||||
uriBuilder = uri.buildUpon();
|
||||
uriBuilder.appendEncodedPath(mOAuth2Provider.getAccessTokenEndpointPath());
|
||||
uriBuilder.appendQueryParameter(
|
||||
OAuth2Constants.KEY_RESPONSE_TYPE, OAuth2Constants.OAUTH2_RESPONSE_TYPE_CODE
|
||||
);
|
||||
uriBuilder.appendQueryParameter(
|
||||
OAuth2Constants.KEY_REDIRECT_URI, clientConfiguration.getRedirectUri()
|
||||
);
|
||||
uriBuilder.appendQueryParameter(
|
||||
OAuth2Constants.KEY_CLIENT_ID, clientConfiguration.getClientId()
|
||||
);
|
||||
|
||||
uri = uriBuilder.build();
|
||||
return uri.toString();
|
||||
|
||||
default:
|
||||
throw new UnsupportedOperationException(
|
||||
"Unsupported request"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user