|
9 | 9 | import sys
|
10 | 10 | import warnings
|
11 | 11 | from threading import Lock
|
| 12 | +import os |
12 | 13 |
|
13 | 14 | import requests
|
14 | 15 |
|
@@ -69,6 +70,46 @@ def _clean_up(result):
|
69 | 70 | return result
|
70 | 71 |
|
71 | 72 |
|
| 73 | +def _preferred_browser(): |
| 74 | + """Register Edge and return a name suitable for subsequent webbrowser.get(...) |
| 75 | + when appropriate. Otherwise return None. |
| 76 | + """ |
| 77 | + # On Linux, only Edge will provide device-based Conditional Access support |
| 78 | + if sys.platform != "linux": # On other platforms, we have no browser preference |
| 79 | + return None |
| 80 | + browser_path = "/usr/bin/microsoft-edge" # Use a full path owned by sys admin |
| 81 | + user_has_no_preference = "BROWSER" not in os.environ |
| 82 | + user_wont_mind_edge = "microsoft-edge" in os.environ.get("BROWSER", "") # Note: |
| 83 | + # BROWSER could contain "microsoft-edge" or "/path/to/microsoft-edge". |
| 84 | + # Python documentation (https://docs.python.org/3/library/webbrowser.html) |
| 85 | + # does not document the name being implicitly register, |
| 86 | + # so there is no public API to know whether the ENV VAR browser would work. |
| 87 | + # Therefore, we would not bother examine the env var browser's type. |
| 88 | + # We would just register our own Edge instance. |
| 89 | + if (user_has_no_preference or user_wont_mind_edge) and os.path.exists(browser_path): |
| 90 | + try: |
| 91 | + import webbrowser # Lazy import. Some distro may not have this. |
| 92 | + browser_name = "msal-edge" # Avoid popular name "microsoft-edge" |
| 93 | + # otherwise `BROWSER="microsoft-edge"; webbrowser.get("microsoft-edge")` |
| 94 | + # would return a GenericBrowser instance which won't work. |
| 95 | + try: |
| 96 | + registration_available = isinstance( |
| 97 | + webbrowser.get(browser_name), webbrowser.BackgroundBrowser) |
| 98 | + except webbrowser.Error: |
| 99 | + registration_available = False |
| 100 | + if not registration_available: |
| 101 | + logger.debug("Register %s with %s", browser_name, browser_path) |
| 102 | + # By registering our own browser instance with our own name, |
| 103 | + # rather than populating a process-wide BROWSER enn var, |
| 104 | + # this approach does not have side effect on non-MSAL code path. |
| 105 | + webbrowser.register( # Even double-register happens to work fine |
| 106 | + browser_name, None, webbrowser.BackgroundBrowser(browser_path)) |
| 107 | + return browser_name |
| 108 | + except ImportError: |
| 109 | + pass # We may still proceed |
| 110 | + return None |
| 111 | + |
| 112 | + |
72 | 113 | class ClientApplication(object):
|
73 | 114 |
|
74 | 115 | ACQUIRE_TOKEN_SILENT_ID = "84"
|
@@ -1393,6 +1434,7 @@ def acquire_token_interactive(
|
1393 | 1434 | },
|
1394 | 1435 | data=dict(kwargs.pop("data", {}), claims=claims),
|
1395 | 1436 | headers=telemetry_context.generate_headers(),
|
| 1437 | + browser_name=_preferred_browser(), |
1396 | 1438 | **kwargs))
|
1397 | 1439 | telemetry_context.update_telemetry(response)
|
1398 | 1440 | return response
|
|
0 commit comments