From 5741d94c5606f0787bdd5f5d74f60b0fe54d4640 Mon Sep 17 00:00:00 2001 From: Jiashuo Li Date: Mon, 29 Mar 2021 18:17:05 +0800 Subject: [PATCH 1/7] Support launching browser in WSL Ubuntu 18.04 --- msal/oauth2cli/authcode.py | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/msal/oauth2cli/authcode.py b/msal/oauth2cli/authcode.py index 71e3f07c..68f6dad2 100644 --- a/msal/oauth2cli/authcode.py +++ b/msal/oauth2cli/authcode.py @@ -33,9 +33,33 @@ def obtain_auth_code(listen_port, auth_uri=None): # Historically only used in t ).get("code") +def is_wsl(): + # "Official" way of detecting WSL: https://github.com/Microsoft/WSL/issues/423#issuecomment-221627364 + # Run `uname -a` to get 'release' without python + # - WSL 1: '4.4.0-19041-Microsoft' + # - WSL 2: '4.19.128-microsoft-standard' + import platform + uname = platform.uname() + platform_name = getattr(uname, 'system', None).lower() + release = getattr(uname, 'release', None).lower() + return platform_name == 'linux' and 'microsoft' in release + + def _browse(auth_uri): # throws ImportError, possibly webbrowser.Error in future import webbrowser # Lazy import. Some distro may not have this. - return webbrowser.open(auth_uri) # Use default browser. Customizable by $BROWSER + result = webbrowser.open(auth_uri) # Use default browser. Customizable by $BROWSER + + # In WSL which doesn't have www-browser, try launching browser with PowerShell + if not result and is_wsl(): + try: + import subprocess + # https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_powershell_exe + # Ampersand (&) should be quoted + exit_code = subprocess.call(['powershell.exe', '-Command', 'Start-Process "{}"'.format(auth_uri)]) + result = exit_code == 0 + except FileNotFoundError: # WSL might be too old + pass + return result def _qs2kv(qs): @@ -245,4 +269,3 @@ def __exit__(self, exc_type, exc_val, exc_tb): timeout=60, state=flow["state"], # Optional ), indent=4)) - From 31cc90c36d9ae4019ccae687336992f6ddeab4af Mon Sep 17 00:00:00 2001 From: Jiashuo Li Date: Mon, 29 Mar 2021 18:44:00 +0800 Subject: [PATCH 2/7] rename --- msal/oauth2cli/authcode.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/msal/oauth2cli/authcode.py b/msal/oauth2cli/authcode.py index 68f6dad2..cb12d276 100644 --- a/msal/oauth2cli/authcode.py +++ b/msal/oauth2cli/authcode.py @@ -47,19 +47,19 @@ def is_wsl(): def _browse(auth_uri): # throws ImportError, possibly webbrowser.Error in future import webbrowser # Lazy import. Some distro may not have this. - result = webbrowser.open(auth_uri) # Use default browser. Customizable by $BROWSER + browser_opened = webbrowser.open(auth_uri) # Use default browser. Customizable by $BROWSER # In WSL which doesn't have www-browser, try launching browser with PowerShell - if not result and is_wsl(): + if not browser_opened and is_wsl(): try: import subprocess # https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_powershell_exe # Ampersand (&) should be quoted exit_code = subprocess.call(['powershell.exe', '-Command', 'Start-Process "{}"'.format(auth_uri)]) - result = exit_code == 0 + browser_opened = exit_code == 0 except FileNotFoundError: # WSL might be too old pass - return result + return browser_opened def _qs2kv(qs): From 6911fd58581e4b05f80c2784af510e7c0d744703 Mon Sep 17 00:00:00 2001 From: Jiashuo Li Date: Mon, 29 Mar 2021 19:43:16 +0800 Subject: [PATCH 3/7] Add test --- tests/test_authcode.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 tests/test_authcode.py diff --git a/tests/test_authcode.py b/tests/test_authcode.py new file mode 100644 index 00000000..116fce22 --- /dev/null +++ b/tests/test_authcode.py @@ -0,0 +1,25 @@ +from msal.oauth2cli.authcode import _browse + +from tests import unittest +from unittest.mock import patch + + +class TestUtil(unittest.TestCase): + + def test_browse(self): + auth_uri = "https://example.com/" + + with patch("webbrowser.open", return_value=True): + self.assertTrue(_browse(auth_uri)) + + with patch("webbrowser.open", return_value=False): + with patch("msal.oauth2cli.authcode.is_wsl", return_value=False): + self.assertFalse(_browse(auth_uri)) + + with patch("msal.oauth2cli.authcode.is_wsl", return_value=True): + with patch("subprocess.call", return_value=0) as call_mock: + self.assertTrue(_browse(auth_uri)) + call_mock.assert_called_with(['powershell.exe', '-Command', 'Start-Process "https://example.com/"']) + + with patch("subprocess.call", return_value=1): + self.assertFalse(_browse(auth_uri)) From 47348aefaa93b59b308a5ddcff51b274694e248e Mon Sep 17 00:00:00 2001 From: Jiashuo Li Date: Mon, 29 Mar 2021 19:55:07 +0800 Subject: [PATCH 4/7] Add -NoProfile --- msal/oauth2cli/authcode.py | 3 ++- tests/test_authcode.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/msal/oauth2cli/authcode.py b/msal/oauth2cli/authcode.py index cb12d276..58d5baae 100644 --- a/msal/oauth2cli/authcode.py +++ b/msal/oauth2cli/authcode.py @@ -55,7 +55,8 @@ def _browse(auth_uri): # throws ImportError, possibly webbrowser.Error in futur import subprocess # https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_powershell_exe # Ampersand (&) should be quoted - exit_code = subprocess.call(['powershell.exe', '-Command', 'Start-Process "{}"'.format(auth_uri)]) + exit_code = subprocess.call( + ['powershell.exe', '-NoProfile', '-Command', 'Start-Process "{}"'.format(auth_uri)]) browser_opened = exit_code == 0 except FileNotFoundError: # WSL might be too old pass diff --git a/tests/test_authcode.py b/tests/test_authcode.py index 116fce22..9bc3f55a 100644 --- a/tests/test_authcode.py +++ b/tests/test_authcode.py @@ -19,7 +19,8 @@ def test_browse(self): with patch("msal.oauth2cli.authcode.is_wsl", return_value=True): with patch("subprocess.call", return_value=0) as call_mock: self.assertTrue(_browse(auth_uri)) - call_mock.assert_called_with(['powershell.exe', '-Command', 'Start-Process "https://example.com/"']) + call_mock.assert_called_with( + ['powershell.exe', '-NoProfile', '-Command', 'Start-Process "https://example.com/"']) with patch("subprocess.call", return_value=1): self.assertFalse(_browse(auth_uri)) From c935c605797db8c635bc7cf964ad4d625760d170 Mon Sep 17 00:00:00 2001 From: Jiashuo Li Date: Mon, 29 Mar 2021 19:59:09 +0800 Subject: [PATCH 5/7] sort import --- tests/test_authcode.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_authcode.py b/tests/test_authcode.py index 9bc3f55a..efd5c778 100644 --- a/tests/test_authcode.py +++ b/tests/test_authcode.py @@ -1,7 +1,7 @@ -from msal.oauth2cli.authcode import _browse +from unittest.mock import patch +from msal.oauth2cli.authcode import _browse from tests import unittest -from unittest.mock import patch class TestUtil(unittest.TestCase): From d3af0a388d2f8d822650d0c162692aa9bfb34139 Mon Sep 17 00:00:00 2001 From: Jiashuo Li Date: Tue, 30 Mar 2021 20:22:25 +0800 Subject: [PATCH 6/7] Apply suggestions from code review Co-authored-by: Ray Luo --- msal/oauth2cli/authcode.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/msal/oauth2cli/authcode.py b/msal/oauth2cli/authcode.py index 58d5baae..25c337c4 100644 --- a/msal/oauth2cli/authcode.py +++ b/msal/oauth2cli/authcode.py @@ -40,8 +40,8 @@ def is_wsl(): # - WSL 2: '4.19.128-microsoft-standard' import platform uname = platform.uname() - platform_name = getattr(uname, 'system', None).lower() - release = getattr(uname, 'release', None).lower() + platform_name = getattr(uname, 'system', uname[0]).lower() + release = getattr(uname, 'release', uname[2]).lower() return platform_name == 'linux' and 'microsoft' in release From aac5589395a01d86b518a859fe9a98ceb5882972 Mon Sep 17 00:00:00 2001 From: Jiashuo Li Date: Tue, 30 Mar 2021 20:22:54 +0800 Subject: [PATCH 7/7] Remove test_authcode.py --- tests/test_authcode.py | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 tests/test_authcode.py diff --git a/tests/test_authcode.py b/tests/test_authcode.py deleted file mode 100644 index efd5c778..00000000 --- a/tests/test_authcode.py +++ /dev/null @@ -1,26 +0,0 @@ -from unittest.mock import patch - -from msal.oauth2cli.authcode import _browse -from tests import unittest - - -class TestUtil(unittest.TestCase): - - def test_browse(self): - auth_uri = "https://example.com/" - - with patch("webbrowser.open", return_value=True): - self.assertTrue(_browse(auth_uri)) - - with patch("webbrowser.open", return_value=False): - with patch("msal.oauth2cli.authcode.is_wsl", return_value=False): - self.assertFalse(_browse(auth_uri)) - - with patch("msal.oauth2cli.authcode.is_wsl", return_value=True): - with patch("subprocess.call", return_value=0) as call_mock: - self.assertTrue(_browse(auth_uri)) - call_mock.assert_called_with( - ['powershell.exe', '-NoProfile', '-Command', 'Start-Process "https://example.com/"']) - - with patch("subprocess.call", return_value=1): - self.assertFalse(_browse(auth_uri))