diff --git a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/AcquireTokenByInteractiveFlowSupplier.java b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/AcquireTokenByInteractiveFlowSupplier.java index f9dadf71..8029c5d8 100644 --- a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/AcquireTokenByInteractiveFlowSupplier.java +++ b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/AcquireTokenByInteractiveFlowSupplier.java @@ -7,17 +7,20 @@ import org.slf4j.LoggerFactory; import java.awt.*; +import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; +import java.util.Arrays; +import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; class AcquireTokenByInteractiveFlowSupplier extends AuthenticationResultSupplier { - private final static Logger LOG = LoggerFactory.getLogger(AcquireTokenByAuthorizationGrantSupplier.class); + private static final Logger LOG = LoggerFactory.getLogger(AcquireTokenByInteractiveFlowSupplier.class); private PublicClientApplication clientApplication; private InteractiveRequest interactiveRequest; @@ -25,6 +28,12 @@ class AcquireTokenByInteractiveFlowSupplier extends AuthenticationResultSupplier private BlockingQueue authorizationResultQueue; private HttpListener httpListener; + /**MSAL tried to open the browser on Linux using the xdg-open, gnome-open, or kfmclient tools, but failed. + Make sure you can open a page using xdg-open tool. See ... for details. */ + public static final String LINUX_XDG_OPEN = "linux_xdg_open_failed"; + + public static final String LINUX_OPEN_AS_SUDO_NOT_SUPPORTED = "Unable to open a web page using xdg-open, gnome-open, kfmclient or wslview tools in sudo mode. Please run the process as non-sudo user."; + AcquireTokenByInteractiveFlowSupplier(PublicClientApplication clientApplication, InteractiveRequest request) { super(clientApplication, request); @@ -106,8 +115,38 @@ private void updateRedirectUrl() { AuthenticationErrorCode.INVALID_REDIRECT_URI); } } + private static List getOpenToolsLinux() { + return Arrays.asList("xdg-open", "gnome-open", "kfmclient", "microsoft-edge", "wslview"); + } + + private static String getExecutablePath(String executable) { + String pathEnvVar = System.getenv("PATH"); + if (pathEnvVar != null) { + String[] paths = pathEnvVar.split(File + .pathSeparator); + for (String basePath : paths) { + String path = basePath + File.separator + executable; + if (new File(path).exists()) { + return path; + } + } + } + return null; + } + + private void openDefaultSystemBrowser(URL url){ + if (OSHelper.isWindows()) { //windows + openDefaultSystemBrowserInWindows(url); + } else if (OSHelper.isMac()) { // mac os + openDefaultSystemBrowserInMac(url); + } else if (OSHelper.isLinux()) { //linux or unix os + openDefaultSystemBrowserInLinux(url); + } else { + throw new UnsupportedOperationException(OSHelper.getOs() + "Operating system not supported exception."); + } + } - private void openDefaultSystemBrowser(URL url) { + private static void openDefaultSystemBrowserInWindows(URL url){ try { if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { Desktop.getDesktop().browse(url.toURI()); @@ -121,6 +160,41 @@ private void openDefaultSystemBrowser(URL url) { } } + private static void openDefaultSystemBrowserInMac(URL url){ + Runtime runtime = Runtime.getRuntime(); + try { + runtime.exec("open " + url); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private static void openDefaultSystemBrowserInLinux(URL url){ + String sudoUser = System.getenv("SUDO_USER"); + if (sudoUser != null && !sudoUser.isEmpty()) { + throw new MsalClientException(LINUX_XDG_OPEN, LINUX_OPEN_AS_SUDO_NOT_SUPPORTED); + } + + boolean opened = false; + List openTools = getOpenToolsLinux(); + for (String openTool : openTools) { + String openToolPath = getExecutablePath(openTool); + if (openToolPath != null) { + Runtime runtime = Runtime.getRuntime(); + try { + runtime.exec(openTool + url); + } catch (IOException e) { + throw new RuntimeException(e); + } + opened = true; + break; + } + } + if (!opened) { + throw new MsalClientException(LINUX_XDG_OPEN, LINUX_OPEN_AS_SUDO_NOT_SUPPORTED); + } + } + private AuthorizationResult getAuthorizationResultFromHttpListener() { AuthorizationResult result = null; try { diff --git a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/OSHelper.java b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/OSHelper.java new file mode 100644 index 00000000..b1609f5a --- /dev/null +++ b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/OSHelper.java @@ -0,0 +1,39 @@ +package com.microsoft.aad.msal4j; + +public class OSHelper { + enum OSType{ + MAC, + WINDOWS, + LINUX + } + + private static final String OS; + private static OSType osType; + + static{ + OS = System.getProperty("os.name").toLowerCase(); + if(OS.contains("windows")){ + osType = OSType.WINDOWS; + }else if (OS.contains("mac")){ + osType = OSType.MAC; + }else if (OS.contains("nux") || OS.contains("nix")){ + osType = OSType.LINUX; + } + } + + public static String getOs(){ + return OS; + } + + public static boolean isMac(){ + return OSType.MAC.equals(osType); + } + + public static boolean isWindows(){ + return OSType.WINDOWS.equals(osType); + } + + public static boolean isLinux(){ + return OSType.LINUX.equals(osType); + } +}