Browse Source

Add query to redirection to provide more context in the frontend (#1973)

Co-authored-by: Sebastian Stenzel <sebastian.stenzel@gmail.com>
Armin Schrenk 3 năm trước cách đây
mục cha
commit
921dd8fe67

+ 2 - 2
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);
 	}
 

+ 5 - 0
src/main/java/org/cryptomator/ui/keyloading/hub/AuthFlowContext.java

@@ -0,0 +1,5 @@
+package org.cryptomator.ui.keyloading.hub;
+
+record AuthFlowContext(String deviceId) {
+
+}

+ 4 - 2
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<String> tokenRef;
 	private final UserInteractionLock<HubKeyLoadingModule.HubLoadingResult> 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<String> tokenRef, UserInteractionLock<HubKeyLoadingModule.HubLoadingResult> result, @FxmlScene(FxmlFile.HUB_RECEIVE_KEY) Lazy<Scene> receiveKeyScene, ErrorComponent.Builder errorComponent) {
+	public AuthFlowController(Application application, @KeyLoading Stage window, ExecutorService executor, @Named("deviceId") String deviceId, HubConfig hubConfig, @Named("bearerToken") AtomicReference<String> tokenRef, UserInteractionLock<HubKeyLoadingModule.HubLoadingResult> result, @FxmlScene(FxmlFile.HUB_RECEIVE_KEY) Lazy<Scene> 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);

+ 12 - 10
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> 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));

+ 4 - 2
src/main/java/org/cryptomator/ui/keyloading/hub/AuthFlowTask.java

@@ -7,6 +7,7 @@ import java.util.function.Consumer;
 
 class AuthFlowTask extends Task<String> {
 
+	private final AuthFlowContext authFlowContext;
 	private final Consumer<URI> redirectUriConsumer;
 
 	/**
@@ -15,14 +16,15 @@ class AuthFlowTask extends Task<String> {
 	 * @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<URI> redirectUriConsumer) {
+	public AuthFlowTask(HubConfig hubConfig, AuthFlowContext authFlowContext, Consumer<URI> 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)));
 		}
 	}

+ 13 - 2
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

+ 3 - 10
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<JWEObject> jweRef;
 	private final UserInteractionLock<HubKeyLoadingModule.HubLoadingResult> 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<String> tokenRef, AtomicReference<JWEObject> jweRef, UserInteractionLock<HubKeyLoadingModule.HubLoadingResult> result, @FxmlScene(FxmlFile.HUB_REGISTER_DEVICE) Lazy<Scene> registerDeviceScene, @FxmlScene(FxmlFile.HUB_UNAUTHORIZED_DEVICE) Lazy<Scene> unauthorizedScene, ErrorComponent.Builder errorComponent) {
+	public ReceiveKeyController(@KeyLoading Vault vault, ExecutorService executor, @KeyLoading Stage window, @Named("deviceId") String deviceId, @Named("bearerToken") AtomicReference<String> tokenRef, AtomicReference<JWEObject> jweRef, UserInteractionLock<HubKeyLoadingModule.HubLoadingResult> result, @FxmlScene(FxmlFile.HUB_REGISTER_DEVICE) Lazy<Scene> registerDeviceScene, @FxmlScene(FxmlFile.HUB_UNAUTHORIZED_DEVICE) Lazy<Scene> 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) //

+ 3 - 5
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);
 			});