From 5ab1dc1f4393760688f32e5c3980b1224ad3bcb5 Mon Sep 17 00:00:00 2001 From: David Kocher Date: Fri, 17 Jan 2025 08:56:27 +0100 Subject: [PATCH] Allow OAuth configuration in connection profiles using WebDAV. --- .../core/owncloud/OwncloudSession.java | 29 ++----------------- webdav/pom.xml | 5 ++++ .../ch/cyberduck/core/dav/DAVSession.java | 23 +++++++++++++-- 3 files changed, 28 insertions(+), 29 deletions(-) diff --git a/owncloud/src/main/java/ch/cyberduck/core/owncloud/OwncloudSession.java b/owncloud/src/main/java/ch/cyberduck/core/owncloud/OwncloudSession.java index 57f97caf7cc..4eaa3e4ed50 100644 --- a/owncloud/src/main/java/ch/cyberduck/core/owncloud/OwncloudSession.java +++ b/owncloud/src/main/java/ch/cyberduck/core/owncloud/OwncloudSession.java @@ -28,7 +28,6 @@ import ch.cyberduck.core.dav.DAVSession; import ch.cyberduck.core.dav.DAVTouchFeature; import ch.cyberduck.core.exception.BackgroundException; -import ch.cyberduck.core.exception.ConnectionCanceledException; import ch.cyberduck.core.features.AttributesFinder; import ch.cyberduck.core.features.Delete; import ch.cyberduck.core.features.Directory; @@ -41,18 +40,13 @@ import ch.cyberduck.core.features.Upload; import ch.cyberduck.core.features.Versioning; import ch.cyberduck.core.features.Write; -import ch.cyberduck.core.http.CustomServiceUnavailableRetryStrategy; import ch.cyberduck.core.http.DefaultHttpResponseExceptionMappingService; -import ch.cyberduck.core.http.ExecutionCountServiceUnavailableRetryStrategy; import ch.cyberduck.core.http.HttpUploadFeature; import ch.cyberduck.core.nextcloud.NextcloudDeleteFeature; import ch.cyberduck.core.nextcloud.NextcloudListService; import ch.cyberduck.core.nextcloud.NextcloudShareFeature; import ch.cyberduck.core.nextcloud.NextcloudUrlProvider; import ch.cyberduck.core.nextcloud.NextcloudWriteFeature; -import ch.cyberduck.core.oauth.OAuth2AuthorizationService; -import ch.cyberduck.core.oauth.OAuth2ErrorResponseInterceptor; -import ch.cyberduck.core.oauth.OAuth2RequestInterceptor; import ch.cyberduck.core.ocs.OcsCapabilities; import ch.cyberduck.core.ocs.OcsCapabilitiesRequest; import ch.cyberduck.core.ocs.OcsCapabilitiesResponseHandler; @@ -70,7 +64,6 @@ import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.apache.http.client.HttpResponseException; -import org.apache.http.impl.client.HttpClientBuilder; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -84,8 +77,6 @@ public class OwncloudSession extends DAVSession { private static final Logger log = LogManager.getLogger(OwncloudSession.class); - private OAuth2RequestInterceptor authorizationService; - protected final TusCapabilities tus = new TusCapabilities(); protected final OcsCapabilities ocs = new OcsCapabilities(); @@ -110,26 +101,11 @@ protected DAVClient connect(final ProxyFinder proxy, final HostKeyCallback key, return client; } - @Override - protected HttpClientBuilder getConfiguration(final ProxyFinder proxy, final LoginCallback prompt) throws ConnectionCanceledException { - final HttpClientBuilder configuration = super.getConfiguration(proxy, prompt); - if(host.getProtocol().isOAuthConfigurable()) { - authorizationService = new OAuth2RequestInterceptor(configuration.build(), host, prompt) - .withRedirectUri(host.getProtocol().getOAuthRedirectUrl()); - if(host.getProtocol().getAuthorization() != null) { - authorizationService.withFlowType(OAuth2AuthorizationService.FlowType.valueOf(host.getProtocol().getAuthorization())); - } - configuration.addInterceptorLast(authorizationService); - configuration.setServiceUnavailableRetryStrategy(new CustomServiceUnavailableRetryStrategy(host, - new ExecutionCountServiceUnavailableRetryStrategy(new OAuth2ErrorResponseInterceptor(host, authorizationService)))); - } - return configuration; - } - @Override public void login(final LoginCallback prompt, final CancelCallback cancel) throws BackgroundException { + super.login(prompt, cancel); if(host.getProtocol().isOAuthConfigurable()) { - final Credentials credentials = authorizationService.validate(); + final Credentials credentials = host.getCredentials(); final OAuthTokens oauth = credentials.getOauth(); try { final String username = JWT.decode(oauth.getIdToken()).getClaim("preferred_username").asString(); @@ -141,7 +117,6 @@ public void login(final LoginCallback prompt, final CancelCallback cancel) throw log.warn("Failure {} decoding JWT {}", e, oauth.getIdToken()); } } - super.login(prompt, cancel); try { client.execute(new OcsCapabilitiesRequest(host), new OcsCapabilitiesResponseHandler(ocs)); } diff --git a/webdav/pom.xml b/webdav/pom.xml index fda059d8084..8afa76658f5 100644 --- a/webdav/pom.xml +++ b/webdav/pom.xml @@ -34,6 +34,11 @@ core ${project.version} + + ch.cyberduck + oauth + ${project.version} + ch.cyberduck test diff --git a/webdav/src/main/java/ch/cyberduck/core/dav/DAVSession.java b/webdav/src/main/java/ch/cyberduck/core/dav/DAVSession.java index 0dcea7bc935..fb9cd2508da 100644 --- a/webdav/src/main/java/ch/cyberduck/core/dav/DAVSession.java +++ b/webdav/src/main/java/ch/cyberduck/core/dav/DAVSession.java @@ -43,16 +43,20 @@ import ch.cyberduck.core.exception.ListCanceledException; import ch.cyberduck.core.exception.LoginCanceledException; import ch.cyberduck.core.features.*; +import ch.cyberduck.core.http.CustomServiceUnavailableRetryStrategy; +import ch.cyberduck.core.http.ExecutionCountServiceUnavailableRetryStrategy; import ch.cyberduck.core.http.HttpExceptionMappingService; import ch.cyberduck.core.http.HttpSession; import ch.cyberduck.core.http.PreferencesRedirectCallback; import ch.cyberduck.core.http.RedirectCallback; +import ch.cyberduck.core.oauth.OAuth2AuthorizationService; +import ch.cyberduck.core.oauth.OAuth2ErrorResponseInterceptor; +import ch.cyberduck.core.oauth.OAuth2RequestInterceptor; import ch.cyberduck.core.preferences.HostPreferences; import ch.cyberduck.core.preferences.PreferencesReader; import ch.cyberduck.core.proxy.ProxyFinder; import ch.cyberduck.core.shared.DefaultPathHomeFeature; import ch.cyberduck.core.shared.DelegatingHomeFeature; -import ch.cyberduck.core.shared.WorkdirHomeFeature; import ch.cyberduck.core.ssl.X509KeyManager; import ch.cyberduck.core.ssl.X509TrustManager; import ch.cyberduck.core.threading.CancelCallback; @@ -90,6 +94,8 @@ public class DAVSession extends HttpSession { private final PreferencesReader preferences = new HostPreferences(host); private final HttpCapabilities capabilities = new HttpCapabilities(preferences); + private OAuth2RequestInterceptor authorizationService; + public DAVSession(final Host host, final X509TrustManager trust, final X509KeyManager key) { this(host, trust, key, new PreferencesRedirectCallback()); } @@ -107,6 +113,16 @@ protected DAVClient connect(final ProxyFinder proxy, final HostKeyCallback key, protected HttpClientBuilder getConfiguration(final ProxyFinder proxy, final LoginCallback prompt) throws ConnectionCanceledException { final HttpClientBuilder configuration = builder.build(proxy, this, prompt); + if(host.getProtocol().isOAuthConfigurable()) { + authorizationService = new OAuth2RequestInterceptor(configuration.build(), host, prompt) + .withRedirectUri(host.getProtocol().getOAuthRedirectUrl()); + if(host.getProtocol().getAuthorization() != null) { + authorizationService.withFlowType(OAuth2AuthorizationService.FlowType.valueOf(host.getProtocol().getAuthorization())); + } + configuration.addInterceptorLast(authorizationService); + configuration.setServiceUnavailableRetryStrategy(new CustomServiceUnavailableRetryStrategy(host, + new ExecutionCountServiceUnavailableRetryStrategy(new OAuth2ErrorResponseInterceptor(host, authorizationService)))); + } configuration.setRedirectStrategy(new DAVRedirectStrategy(redirect)); configuration.addInterceptorLast(new MicrosoftIISPersistentAuthResponseInterceptor()); return configuration; @@ -124,8 +140,11 @@ protected void logout() throws BackgroundException { @Override public void login(final LoginCallback prompt, final CancelCallback cancel) throws BackgroundException { - final Credentials credentials = host.getCredentials(); + if(host.getProtocol().isOAuthConfigurable()) { + authorizationService.validate(); + } if(host.getProtocol().isPasswordConfigurable()) { + final Credentials credentials = host.getCredentials(); final String domain, username; if(credentials.getUsername().contains("\\")) { domain = StringUtils.substringBefore(credentials.getUsername(), "\\");