From 921dd8fe677428b0de450bd7f361ad375c4e4581 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Fri, 10 Dec 2021 13:42:37 +0100 Subject: [PATCH] Add query to redirection to provide more context in the frontend (#1973) Co-authored-by: Sebastian Stenzel --- .../ui/keyloading/hub/AuthFlow.java | 4 ++-- .../ui/keyloading/hub/AuthFlowContext.java | 5 +++++ .../ui/keyloading/hub/AuthFlowController.java | 6 +++-- .../ui/keyloading/hub/AuthFlowReceiver.java | 22 ++++++++++--------- .../ui/keyloading/hub/AuthFlowTask.java | 6 +++-- .../keyloading/hub/HubKeyLoadingModule.java | 15 +++++++++++-- .../keyloading/hub/ReceiveKeyController.java | 13 +++-------- .../hub/AuthFlowIntegrationTest.java | 8 +++---- 8 files changed, 46 insertions(+), 33 deletions(-) create mode 100644 src/main/java/org/cryptomator/ui/keyloading/hub/AuthFlowContext.java diff --git a/src/main/java/org/cryptomator/ui/keyloading/hub/AuthFlow.java b/src/main/java/org/cryptomator/ui/keyloading/hub/AuthFlow.java index 11ef34301..a4a55e78c 100644 --- a/src/main/java/org/cryptomator/ui/keyloading/hub/AuthFlow.java +++ b/src/main/java/org/cryptomator/ui/keyloading/hub/AuthFlow.java @@ -60,8 +60,8 @@ class AuthFlow implements AutoCloseable { * @return An authorization flow * @throws Exception In case of any problems starting the server */ - public static AuthFlow init(HubConfig hubConfig) throws Exception { - var receiver = AuthFlowReceiver.start(hubConfig); + public static AuthFlow init(HubConfig hubConfig, AuthFlowContext authFlowContext) throws Exception { + var receiver = AuthFlowReceiver.start(hubConfig, authFlowContext); return new AuthFlow(receiver, hubConfig); } diff --git a/src/main/java/org/cryptomator/ui/keyloading/hub/AuthFlowContext.java b/src/main/java/org/cryptomator/ui/keyloading/hub/AuthFlowContext.java new file mode 100644 index 000000000..3ee2b55eb --- /dev/null +++ b/src/main/java/org/cryptomator/ui/keyloading/hub/AuthFlowContext.java @@ -0,0 +1,5 @@ +package org.cryptomator.ui.keyloading.hub; + +record AuthFlowContext(String deviceId) { + +} diff --git a/src/main/java/org/cryptomator/ui/keyloading/hub/AuthFlowController.java b/src/main/java/org/cryptomator/ui/keyloading/hub/AuthFlowController.java index 436516fca..65c9a0df7 100644 --- a/src/main/java/org/cryptomator/ui/keyloading/hub/AuthFlowController.java +++ b/src/main/java/org/cryptomator/ui/keyloading/hub/AuthFlowController.java @@ -35,6 +35,7 @@ public class AuthFlowController implements FxController { private final Application application; private final Stage window; private final ExecutorService executor; + private final String deviceId; private final HubConfig hubConfig; private final AtomicReference tokenRef; private final UserInteractionLock result; @@ -45,10 +46,11 @@ public class AuthFlowController implements FxController { private AuthFlowTask task; @Inject - public AuthFlowController(Application application, @KeyLoading Stage window, ExecutorService executor, HubConfig hubConfig, @Named("bearerToken") AtomicReference tokenRef, UserInteractionLock result, @FxmlScene(FxmlFile.HUB_RECEIVE_KEY) Lazy receiveKeyScene, ErrorComponent.Builder errorComponent) { + public AuthFlowController(Application application, @KeyLoading Stage window, ExecutorService executor, @Named("deviceId") String deviceId, HubConfig hubConfig, @Named("bearerToken") AtomicReference tokenRef, UserInteractionLock result, @FxmlScene(FxmlFile.HUB_RECEIVE_KEY) Lazy receiveKeyScene, ErrorComponent.Builder errorComponent) { this.application = application; this.window = window; this.executor = executor; + this.deviceId = deviceId; this.hubConfig = hubConfig; this.tokenRef = tokenRef; this.result = result; @@ -62,7 +64,7 @@ public class AuthFlowController implements FxController { @FXML public void initialize() { assert task == null; - task = new AuthFlowTask(hubConfig, this::setAuthUri);; + task = new AuthFlowTask(hubConfig, new AuthFlowContext(deviceId), this::setAuthUri);; task.setOnFailed(this::authFailed); task.setOnSucceeded(this::authSucceeded); executor.submit(task); diff --git a/src/main/java/org/cryptomator/ui/keyloading/hub/AuthFlowReceiver.java b/src/main/java/org/cryptomator/ui/keyloading/hub/AuthFlowReceiver.java index d2995b0f8..dc84c450c 100644 --- a/src/main/java/org/cryptomator/ui/keyloading/hub/AuthFlowReceiver.java +++ b/src/main/java/org/cryptomator/ui/keyloading/hub/AuthFlowReceiver.java @@ -30,20 +30,18 @@ class AuthFlowReceiver implements AutoCloseable { private final Server server; private final ServerConnector connector; private final CallbackServlet servlet; - private final HubConfig hubConfig; - private AuthFlowReceiver(Server server, ServerConnector connector, CallbackServlet servlet, HubConfig hubConfig) { + private AuthFlowReceiver(Server server, ServerConnector connector, CallbackServlet servlet) { this.server = server; this.connector = connector; this.servlet = servlet; - this.hubConfig = hubConfig; } - public static AuthFlowReceiver start(HubConfig hubConfig) throws Exception { + public static AuthFlowReceiver start(HubConfig hubConfig, AuthFlowContext authFlowContext) throws Exception { var server = new Server(); var context = new ServletContextHandler(); - var servlet = new CallbackServlet(hubConfig); + var servlet = new CallbackServlet(hubConfig, authFlowContext); context.addServlet(new ServletHolder(servlet), CALLBACK_PATH); var connector = new ServerConnector(server); @@ -52,7 +50,7 @@ class AuthFlowReceiver implements AutoCloseable { server.setConnectors(new Connector[]{connector}); server.setHandler(context); server.start(); - return new AuthFlowReceiver(server, connector, servlet, hubConfig); + return new AuthFlowReceiver(server, connector, servlet); } public String getRedirectUri() { @@ -68,15 +66,19 @@ class AuthFlowReceiver implements AutoCloseable { server.stop(); } - public static record Callback(String error, String code, String state){} + public static record Callback(String error, String code, String state) { + + } private static class CallbackServlet extends HttpServlet { private final BlockingQueue callback = new LinkedBlockingQueue<>(); private final HubConfig hubConfig; + private final AuthFlowContext authFlowContext; - public CallbackServlet(HubConfig hubConfig) { + public CallbackServlet(HubConfig hubConfig, AuthFlowContext authFlowContext) { this.hubConfig = hubConfig; + this.authFlowContext = authFlowContext; } @Override @@ -87,9 +89,9 @@ class AuthFlowReceiver implements AutoCloseable { res.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY); if (error == null && code != null) { - res.setHeader("Location", hubConfig.authSuccessUrl); + res.setHeader("Location", hubConfig.authSuccessUrl + "&device=" + authFlowContext.deviceId()); } else { - res.setHeader("Location", hubConfig.authErrorUrl); + res.setHeader("Location", hubConfig.authErrorUrl + "&device=" + authFlowContext.deviceId()); } callback.add(new Callback(error, code, state)); diff --git a/src/main/java/org/cryptomator/ui/keyloading/hub/AuthFlowTask.java b/src/main/java/org/cryptomator/ui/keyloading/hub/AuthFlowTask.java index 901c7acc7..be41df2dd 100644 --- a/src/main/java/org/cryptomator/ui/keyloading/hub/AuthFlowTask.java +++ b/src/main/java/org/cryptomator/ui/keyloading/hub/AuthFlowTask.java @@ -7,6 +7,7 @@ import java.util.function.Consumer; class AuthFlowTask extends Task { + private final AuthFlowContext authFlowContext; private final Consumer redirectUriConsumer; /** @@ -15,14 +16,15 @@ class AuthFlowTask extends Task { * @param hubConfig Configuration object holding parameters required by {@link AuthFlow} * @param redirectUriConsumer A callback invoked with the redirectUri, as soon as the server has started */ - public AuthFlowTask(HubConfig hubConfig, Consumer redirectUriConsumer) { + public AuthFlowTask(HubConfig hubConfig, AuthFlowContext authFlowContext, Consumer redirectUriConsumer) { this.hubConfig = hubConfig; + this.authFlowContext = authFlowContext; this.redirectUriConsumer = redirectUriConsumer; } @Override protected String call() throws Exception { - try (var authFlow = AuthFlow.init(hubConfig)) { + try (var authFlow = AuthFlow.init(hubConfig, authFlowContext)) { return authFlow.run(uri -> Platform.runLater(() -> redirectUriConsumer.accept(uri))); } } diff --git a/src/main/java/org/cryptomator/ui/keyloading/hub/HubKeyLoadingModule.java b/src/main/java/org/cryptomator/ui/keyloading/hub/HubKeyLoadingModule.java index bf2cb10d5..04faa1493 100644 --- a/src/main/java/org/cryptomator/ui/keyloading/hub/HubKeyLoadingModule.java +++ b/src/main/java/org/cryptomator/ui/keyloading/hub/HubKeyLoadingModule.java @@ -1,12 +1,15 @@ package org.cryptomator.ui.keyloading.hub; +import com.google.common.io.BaseEncoding; import com.nimbusds.jose.JWEObject; import dagger.Binds; import dagger.Module; import dagger.Provides; import dagger.multibindings.IntoMap; import dagger.multibindings.StringKey; +import org.cryptomator.common.settings.DeviceKey; import org.cryptomator.common.vaults.Vault; +import org.cryptomator.cryptolib.common.MessageDigestSupplier; import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.FxControllerKey; import org.cryptomator.ui.common.FxmlFile; @@ -23,8 +26,7 @@ import javax.inject.Named; import javafx.scene.Scene; import java.io.IOException; import java.io.UncheckedIOException; -import java.net.URI; -import java.security.KeyPair; +import java.util.Objects; import java.util.ResourceBundle; import java.util.concurrent.atomic.AtomicReference; @@ -47,6 +49,15 @@ public abstract class HubKeyLoadingModule { } } + @Provides + @KeyLoadingScoped + @Named("deviceId") + static String provideDeviceId(DeviceKey deviceKey) { + var publicKey = Objects.requireNonNull(deviceKey.get()).getPublic().getEncoded(); + var hashedKey = MessageDigestSupplier.SHA256.get().digest(publicKey); + return BaseEncoding.base16().encode(hashedKey); + } + @Provides @Named("bearerToken") @KeyLoadingScoped diff --git a/src/main/java/org/cryptomator/ui/keyloading/hub/ReceiveKeyController.java b/src/main/java/org/cryptomator/ui/keyloading/hub/ReceiveKeyController.java index 7514730cd..90efc6abc 100644 --- a/src/main/java/org/cryptomator/ui/keyloading/hub/ReceiveKeyController.java +++ b/src/main/java/org/cryptomator/ui/keyloading/hub/ReceiveKeyController.java @@ -1,12 +1,8 @@ package org.cryptomator.ui.keyloading.hub; -import com.google.common.io.BaseEncoding; import com.nimbusds.jose.JWEObject; import dagger.Lazy; -import org.cryptomator.common.settings.DeviceKey; import org.cryptomator.common.vaults.Vault; -import org.cryptomator.cryptolib.common.MessageDigestSupplier; -import org.cryptomator.cryptolib.common.P384KeyPair; import org.cryptomator.ui.common.ErrorComponent; import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.FxmlFile; @@ -44,7 +40,7 @@ public class ReceiveKeyController implements FxController { private static final String SCHEME_PREFIX = "hub+"; private final Stage window; - private final P384KeyPair keyPair; + private final String deviceId; private final String bearerToken; private final AtomicReference jweRef; private final UserInteractionLock result; @@ -55,9 +51,9 @@ public class ReceiveKeyController implements FxController { private final HttpClient httpClient; @Inject - public ReceiveKeyController(@KeyLoading Vault vault, ExecutorService executor, @KeyLoading Stage window, DeviceKey deviceKey, @Named("bearerToken") AtomicReference tokenRef, AtomicReference jweRef, UserInteractionLock result, @FxmlScene(FxmlFile.HUB_REGISTER_DEVICE) Lazy registerDeviceScene, @FxmlScene(FxmlFile.HUB_UNAUTHORIZED_DEVICE) Lazy unauthorizedScene, ErrorComponent.Builder errorComponent) { + public ReceiveKeyController(@KeyLoading Vault vault, ExecutorService executor, @KeyLoading Stage window, @Named("deviceId") String deviceId, @Named("bearerToken") AtomicReference tokenRef, AtomicReference jweRef, UserInteractionLock result, @FxmlScene(FxmlFile.HUB_REGISTER_DEVICE) Lazy registerDeviceScene, @FxmlScene(FxmlFile.HUB_UNAUTHORIZED_DEVICE) Lazy unauthorizedScene, ErrorComponent.Builder errorComponent) { this.window = window; - this.keyPair = Objects.requireNonNull(deviceKey.get()); + this.deviceId = deviceId; this.bearerToken = Objects.requireNonNull(tokenRef.get()); this.jweRef = jweRef; this.result = result; @@ -71,9 +67,6 @@ public class ReceiveKeyController implements FxController { @FXML public void initialize() { - var deviceKey = keyPair.getPublic().getEncoded(); - var hashedKey = MessageDigestSupplier.SHA256.get().digest(deviceKey); - var deviceId = BaseEncoding.base16().encode(hashedKey); var keyUri = appendPath(vaultBaseUri, "/keys/" + deviceId); var request = HttpRequest.newBuilder(keyUri) // .header("Authorization", "Bearer " + bearerToken) // diff --git a/src/test/java/org/cryptomator/ui/keyloading/hub/AuthFlowIntegrationTest.java b/src/test/java/org/cryptomator/ui/keyloading/hub/AuthFlowIntegrationTest.java index 1c875365a..f2b9e9cd5 100644 --- a/src/test/java/org/cryptomator/ui/keyloading/hub/AuthFlowIntegrationTest.java +++ b/src/test/java/org/cryptomator/ui/keyloading/hub/AuthFlowIntegrationTest.java @@ -6,8 +6,6 @@ import org.junit.jupiter.api.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.net.URI; - public class AuthFlowIntegrationTest { static { @@ -23,10 +21,10 @@ public class AuthFlowIntegrationTest { hubConfig.authEndpoint = "http://localhost:8080/auth/realms/cryptomator/protocol/openid-connect/auth"; hubConfig.tokenEndpoint = "http://localhost:8080/auth/realms/cryptomator/protocol/openid-connect/token"; hubConfig.clientId = "cryptomator-hub"; - hubConfig.authSuccessUrl = "http://localhost:3000/#/unlock-success"; - hubConfig.authErrorUrl = "http://localhost:3000/#/unlock-error"; + hubConfig.authSuccessUrl = "http://localhost:3000/#/unlock-success?vault=vaultId"; + hubConfig.authErrorUrl = "http://localhost:3000/#/unlock-error?vault=vaultId"; - try (var authFlow = AuthFlow.init(hubConfig)) { + try (var authFlow = AuthFlow.init(hubConfig, new AuthFlowContext("deviceId"))) { var token = authFlow.run(uri -> { LOG.info("Visit {} to authenticate", uri); });