|
8 | 8 | import subprocess |
9 | 9 | import webbrowser |
10 | 10 | from urllib.parse import urlparse |
11 | | -import msal |
12 | 11 |
|
13 | 12 | from azure.core.exceptions import ClientAuthenticationError |
14 | 13 |
|
@@ -81,77 +80,59 @@ def __init__(self, **kwargs: Any) -> None: |
81 | 80 | super(InteractiveBrowserCredential, self).__init__(client_id=client_id, **kwargs) |
82 | 81 |
|
83 | 82 | @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: |
91 | 90 | 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): |
92 | 96 | 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 |
117 | 102 |
|
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") |
120 | 105 |
|
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( |
125 | 128 | message="Timed out after waiting {} seconds for the user to authenticate".format(self._timeout) |
126 | 129 | ) |
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) |
141 | 132 | ) |
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") |
152 | 133 |
|
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) |
155 | 136 |
|
156 | 137 |
|
157 | 138 | def _open_browser(url): |
|
0 commit comments