Skip to content

Commit eeb89c0

Browse files
authored
webbrowser.open returns False on failure (#8465)
1 parent 923dae9 commit eeb89c0

2 files changed

Lines changed: 22 additions & 9 deletions

File tree

sdk/identity/azure-identity/azure/identity/_credentials/browser.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ def _get_token_by_auth_code(self, scopes, **kwargs):
9797
auth_url = app.get_authorization_request_url(scopes, redirect_uri=redirect_uri, state=request_state, **kwargs)
9898

9999
# open browser to that url
100-
webbrowser.open(auth_url)
100+
if not webbrowser.open(auth_url):
101+
raise ClientAuthenticationError(message="Failed to open a browser")
101102

102103
# block until the server times out or receives the post-authentication redirect
103104
response = server.wait_for_redirect()

sdk/identity/azure-identity/tests/test_interactive_credential.py

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@
2121
from mock import Mock, patch # type: ignore
2222

2323

24-
@patch("azure.identity._credentials.browser.webbrowser.open") # prevent the credential opening a browser
24+
@patch("azure.identity._credentials.browser.webbrowser.open")
2525
def test_interactive_credential(mock_open):
26+
mock_open.return_value = True # the real webbrowser.open returns a bool
2627
oauth_state = "state"
2728
client_id = "client-id"
2829
expected_refresh_token = "refresh-token"
@@ -34,9 +35,7 @@ def test_interactive_credential(mock_open):
3435

3536
discovery_response = mock_response(
3637
json_payload={
37-
"authorization_endpoint": endpoint,
38-
"token_endpoint": endpoint,
39-
"tenant_discovery_endpoint": endpoint,
38+
name: endpoint for name in ("authorization_endpoint", "token_endpoint", "tenant_discovery_endpoint")
4039
}
4140
)
4241
transport = validating_transport(
@@ -88,7 +87,6 @@ def test_interactive_credential(mock_open):
8887
assert token.token == expected_token
8988
assert mock_open.call_count == 1
9089

91-
9290
# As of MSAL 1.0.0, applications build a new client every time they redeem a refresh token.
9391
# Here we patch the private method they use for the sake of test coverage.
9492
# TODO: this will probably break when this MSAL behavior changes
@@ -106,9 +104,7 @@ def test_interactive_credential(mock_open):
106104
assert transport.send.call_count == 4
107105

108106

109-
@patch(
110-
"azure.identity._credentials.browser.webbrowser.open", lambda _: None
111-
) # prevent the credential opening a browser
107+
@patch("azure.identity._credentials.browser.webbrowser.open", lambda _: True)
112108
def test_interactive_credential_timeout():
113109
# mock transport handles MSAL's tenant discovery
114110
transport = Mock(
@@ -159,3 +155,19 @@ def test_redirect_server():
159155

160156
assert response.code == 200
161157
assert server.query_params[expected_param] == [expected_value]
158+
159+
160+
@patch("azure.identity._credentials.browser.webbrowser.open", lambda _: False)
161+
def test_no_browser():
162+
discovery_response = mock_response(
163+
json_payload={
164+
name: "https://foo/bar"
165+
for name in ("authorization_endpoint", "token_endpoint", "tenant_discovery_endpoint")
166+
}
167+
)
168+
transport = validating_transport(requests=[Request()] * 2, responses=[discovery_response, discovery_response])
169+
credential = InteractiveBrowserCredential(
170+
client_id="client-id", client_secret="secret", server_class=Mock(), transport=transport
171+
)
172+
with pytest.raises(ClientAuthenticationError, match=r".*browser.*"):
173+
credential.get_token("scope")

0 commit comments

Comments
 (0)