Skip to content

Commit 69d4812

Browse files
authored
Use auth code flow rather than acquire_token_interactive (#32539)
* We moved WAM features into broker package, no need to use `acquire_token_interactive` * update * update changelog * update
1 parent 9c402ea commit 69d4812

File tree

2 files changed

+47
-64
lines changed

2 files changed

+47
-64
lines changed

sdk/identity/azure-identity/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
### Bugs Fixed
1010

11+
- Fixed issue InteractiveBrowserCredential does not hand over to next credential in chain if no browser is supported.([#32276](https://github.com/Azure/azure-sdk-for-python/pull/32276))
12+
1113
### Other Changes
1214

1315
## 1.15.0b2 (2023-10-12)

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

Lines changed: 45 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import subprocess
99
import webbrowser
1010
from urllib.parse import urlparse
11-
import msal
1211

1312
from azure.core.exceptions import ClientAuthenticationError
1413

@@ -81,77 +80,59 @@ def __init__(self, **kwargs: Any) -> None:
8180
super(InteractiveBrowserCredential, self).__init__(client_id=client_id, **kwargs)
8281

8382
@wrap_exceptions
84-
def _request_token(self, *scopes: str, **kwargs: Any) -> Dict:
85-
scopes = list(scopes) # type: ignore
86-
claims = kwargs.get("claims")
87-
app = self._get_app(**kwargs)
88-
if isinstance(app, msal.ConfidentialClientApplication):
89-
server = None
90-
if self._parsed_url:
83+
def _request_token(self, *scopes: str, **kwargs) -> Dict:
84+
85+
# start an HTTP server to receive the redirect
86+
server = None
87+
redirect_uri: str = ""
88+
if self._parsed_url:
89+
try:
9190
redirect_uri = "http://{}:{}".format(self._parsed_url.hostname, self._parsed_url.port)
91+
server = self._server_class(self._parsed_url.hostname, self._parsed_url.port, timeout=self._timeout)
92+
except socket.error as ex:
93+
raise CredentialUnavailableError(message="Couldn't start an HTTP server on " + redirect_uri) from ex
94+
else:
95+
for port in range(8400, 9000):
9296
try:
93-
server = self._server_class(self._parsed_url.hostname, self._parsed_url.port, timeout=self._timeout)
94-
except socket.error as ex:
95-
raise CredentialUnavailableError(message="Couldn't start an HTTP server on " + redirect_uri) from ex
96-
else:
97-
for port in range(8400, 9000):
98-
try:
99-
server = self._server_class("localhost", port, timeout=self._timeout)
100-
redirect_uri = "http://localhost:{}".format(port)
101-
break
102-
except socket.error:
103-
continue # keep looking for an open port
104-
105-
if not server:
106-
raise CredentialUnavailableError(message="Couldn't start an HTTP server on localhost")
107-
108-
flow = app.initiate_auth_code_flow(
109-
scopes,
110-
redirect_uri=redirect_uri,
111-
prompt="select_account",
112-
claims_challenge=claims,
113-
login_hint=self._login_hint,
114-
)
115-
if "auth_uri" not in flow:
116-
raise CredentialUnavailableError("Failed to begin authentication flow")
97+
server = self._server_class("localhost", port, timeout=self._timeout)
98+
redirect_uri = "http://localhost:{}".format(port)
99+
break
100+
except socket.error:
101+
continue # keep looking for an open port
117102

118-
if not _open_browser(flow["auth_uri"]):
119-
raise CredentialUnavailableError(message="Failed to open a browser")
103+
if not server:
104+
raise CredentialUnavailableError(message="Couldn't start an HTTP server on localhost")
120105

121-
# block until the server times out or receives the post-authentication redirect
122-
response = server.wait_for_redirect()
123-
if not response:
124-
raise ClientAuthenticationError(
106+
# get the url the user must visit to authenticate
107+
scopes = list(scopes) # type: ignore
108+
claims = kwargs.get("claims")
109+
app = self._get_app(**kwargs)
110+
flow = app.initiate_auth_code_flow(
111+
scopes,
112+
redirect_uri=redirect_uri,
113+
prompt="select_account",
114+
claims_challenge=claims,
115+
login_hint=self._login_hint,
116+
)
117+
if "auth_uri" not in flow:
118+
raise CredentialUnavailableError("Failed to begin authentication flow")
119+
120+
if not _open_browser(flow["auth_uri"]):
121+
raise CredentialUnavailableError(message="Failed to open a browser")
122+
123+
# block until the server times out or receives the post-authentication redirect
124+
response = server.wait_for_redirect()
125+
if not response:
126+
if within_dac.get():
127+
raise CredentialUnavailableError(
125128
message="Timed out after waiting {} seconds for the user to authenticate".format(self._timeout)
126129
)
127-
128-
# redeem the authorization code for a token
129-
return app.acquire_token_by_auth_code_flow(flow, response, scopes=scopes, claims_challenge=claims)
130-
131-
port = self._parsed_url.port if self._parsed_url else None
132-
133-
try:
134-
result = app.acquire_token_interactive(
135-
scopes=scopes,
136-
login_hint=self._login_hint,
137-
claims_challenge=claims,
138-
timeout=self._timeout,
139-
prompt="select_account",
140-
port=port,
130+
raise ClientAuthenticationError(
131+
message="Timed out after waiting {} seconds for the user to authenticate".format(self._timeout)
141132
)
142-
except socket.error as ex:
143-
raise CredentialUnavailableError(message="Couldn't start an HTTP server.") from ex
144-
if "access_token" not in result and "error_description" in result:
145-
if within_dac.get():
146-
raise CredentialUnavailableError(message=result["error_description"])
147-
raise ClientAuthenticationError(message=result.get("error_description"))
148-
if "access_token" not in result:
149-
if within_dac.get():
150-
raise CredentialUnavailableError(message="Failed to authenticate user")
151-
raise ClientAuthenticationError(message="Failed to authenticate user")
152133

153-
# base class will raise for other errors
154-
return result
134+
# redeem the authorization code for a token
135+
return app.acquire_token_by_auth_code_flow(flow, response, scopes=scopes, claims_challenge=claims)
155136

156137

157138
def _open_browser(url):

0 commit comments

Comments
 (0)