Skip to content

Commit

Permalink
handle tenant_id (Azure#23172)
Browse files Browse the repository at this point in the history
* handle tenant_id

* update

* Update sdk/identity/azure-identity/azure/identity/_internal/aad_client.py

Co-authored-by: McCoy Patiño <39780829+mccoyp@users.noreply.github.com>

* Update CHANGELOG.md

* Update sdk/identity/azure-identity/CHANGELOG.md

Co-authored-by: McCoy Patiño <39780829+mccoyp@users.noreply.github.com>

Co-authored-by: McCoy Patiño <39780829+mccoyp@users.noreply.github.com>
  • Loading branch information
xiangyan99 and mccoyp authored Feb 24, 2022
1 parent 4cd4660 commit 486beca
Show file tree
Hide file tree
Showing 32 changed files with 1,330 additions and 21 deletions.
14 changes: 14 additions & 0 deletions sdk/identity/azure-identity/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,20 @@

### Bugs Fixed

- Handle injected "tenant_id" and "claims" ([#23138](https://github.com/Azure/azure-sdk-for-python/issues/23138))

"tenant_id" argument in get_token() method is only supported by:

- `AuthorizationCodeCredential`
- `AzureCliCredential`
- `AzurePowerShellCredential`
- `InteractiveBrowserCredential`
- `DeviceCodeCredential`
- `EnvironmentCredential`
- `UsernamePasswordCredential`

it is ignored by other types of credentials.

### Other Changes

## 1.8.0b1 (2022-02-08)
Expand Down
30 changes: 15 additions & 15 deletions sdk/identity/azure-identity/azure/identity/_internal/aad_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from typing import Any, Iterable, Optional, Union
from azure.core.credentials import AccessToken
from azure.core.pipeline import Pipeline
from azure.core.pipeline.transport import HttpRequest
from .._internal import AadClientCertificate


Expand All @@ -33,37 +34,27 @@ def obtain_token_by_authorization_code(self, scopes, code, redirect_uri, client_
request = self._get_auth_code_request(
scopes=scopes, code=code, redirect_uri=redirect_uri, client_secret=client_secret, **kwargs
)
now = int(time.time())
response = self._pipeline.run(request, stream=False, retry_on_methods=self._POST, **kwargs)
return self._process_response(response, now)
return self._run_pipeline(request, **kwargs)

def obtain_token_by_client_certificate(self, scopes, certificate, **kwargs):
# type: (Iterable[str], AadClientCertificate, **Any) -> AccessToken
request = self._get_client_certificate_request(scopes, certificate, **kwargs)
now = int(time.time())
response = self._pipeline.run(request, stream=False, retry_on_methods=self._POST, **kwargs)
return self._process_response(response, now)
return self._run_pipeline(request, **kwargs)

def obtain_token_by_client_secret(self, scopes, secret, **kwargs):
# type: (Iterable[str], str, **Any) -> AccessToken
request = self._get_client_secret_request(scopes, secret, **kwargs)
now = int(time.time())
response = self._pipeline.run(request, stream=False, retry_on_methods=self._POST, **kwargs)
return self._process_response(response, now)
return self._run_pipeline(request, **kwargs)

def obtain_token_by_jwt_assertion(self, scopes, assertion, **kwargs):
# type: (Iterable[str], str, **Any) -> AccessToken
request = self._get_jwt_assertion_request(scopes, assertion)
now = int(time.time())
response = self._pipeline.run(request, stream=False, retry_on_methods=self._POST, **kwargs)
return self._process_response(response, now)
return self._run_pipeline(request, **kwargs)

def obtain_token_by_refresh_token(self, scopes, refresh_token, **kwargs):
# type: (Iterable[str], str, **Any) -> AccessToken
request = self._get_refresh_token_request(scopes, refresh_token, **kwargs)
now = int(time.time())
response = self._pipeline.run(request, stream=False, retry_on_methods=self._POST, **kwargs)
return self._process_response(response, now)
return self._run_pipeline(request, **kwargs)

def obtain_token_on_behalf_of(self, scopes, client_credential, user_assertion, **kwargs):
# type: (Iterable[str], Union[str, AadClientCertificate], str, **Any) -> AccessToken
Expand All @@ -74,3 +65,12 @@ def obtain_token_on_behalf_of(self, scopes, client_credential, user_assertion, *
def _build_pipeline(self, **kwargs):
# type: (**Any) -> Pipeline
return build_pipeline(**kwargs)

def _run_pipeline(self, request: "HttpRequest", **kwargs: "Any") -> "AccessToken":
# remove tenant_id and claims kwarg that could have been passed from credential's get_token method
# tenant_id is already part of `request` at this point
kwargs.pop("tenant_id", None)
kwargs.pop("claims", None)
now = int(time.time())
response = self._pipeline.run(request, retry_on_methods=self._POST, **kwargs)
return self._process_response(response, now)
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ def request_token(self, *scopes, **kwargs):
# type: (*str, **Any) -> AccessToken
resource = _scopes_to_resource(*scopes)
request = self._request_factory(resource, self._identity_config)
kwargs.pop("tenant_id", None)
kwargs.pop("claims", None)
request_time = int(time.time())
response = self._pipeline.run(request, retry_on_methods=[request.method], **kwargs)
token = self._process_response(response, request_time)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,10 @@ def _build_pipeline(self, **kwargs: "Any") -> "AsyncPipeline":
return build_async_pipeline(**kwargs)

async def _run_pipeline(self, request: "HttpRequest", **kwargs: "Any") -> "AccessToken":
# remove tenant_id kwarg that could have been passed from credential's get_token method
# remove tenant_id and claims kwarg that could have been passed from credential's get_token method
# tenant_id is already part of `request` at this point
kwargs.pop("tenant_id", None)
kwargs.pop("claims", None)
now = int(time.time())
response = await self._pipeline.run(request, retry_on_methods=self._POST, **kwargs)
return self._process_response(response, now)
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ async def request_token(self, *scopes: str, **kwargs: "Any") -> "AccessToken":
# pylint:disable=invalid-overridden-method
resource = _scopes_to_resource(*scopes)
request = self._request_factory(resource, self._identity_config)
kwargs.pop("tenant_id", None)
kwargs.pop("claims", None)
request_time = int(time.time())
response = await self._pipeline.run(request, retry_on_methods=[request.method], **kwargs)
token = self._process_response(response, request_time)
Expand Down
4 changes: 3 additions & 1 deletion sdk/identity/azure-identity/tests/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,9 @@ def validating_transport(requests, responses):
sessions = zip(requests, responses)
sessions = (s for s in sessions) # 2.7's zip returns a list, and nesting a generator doesn't break it for 3.x

def validate_request(request, **_):
def validate_request(request, **kwargs):
assert "tenant_id" not in kwargs
assert "claims" not in kwargs
try:
expected_request, response = next(sessions)
except StopIteration:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
interactions:
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
User-Agent:
- azsdk-python-identity/1.6.0b4 Python/3.8.6 (Linux-4.15.0-135-generic-x86_64-with-glibc2.2.5)
secret:
- redacted
method: GET
uri: https://msi-endpoint/token?api-version=2017-09-01&resource=https://management.azure.com
response:
body:
string: '{"access_token": "redacted", "expires_on": "05/22/2021 17:14:33 +00:00",
"resource": "https://management.azure.com", "token_type": "Bearer", "client_id":
"6d807b1c-2a6f-41a0-b428-d0e3a08382a0"}'
headers:
content-type:
- application/json; charset=utf-8
date:
- Fri, 21 May 2021 17:14:34 GMT
server:
- Kestrel
transfer-encoding:
- chunked
status:
code: 200
message: OK
version: 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
interactions:
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
User-Agent:
- azsdk-python-identity/1.6.0b4 Python/3.8.6 (Linux-4.15.0-135-generic-x86_64-with-glibc2.2.5)
secret:
- redacted
method: GET
uri: https://msi-endpoint/token?api-version=2017-09-01&resource=https://management.azure.com&clientid=client-id
response:
body:
string: '{"access_token": "redacted", "expires_on": "05/22/2021 17:18:21 +00:00",
"resource": "https://management.azure.com", "token_type": "Bearer", "client_id":
"client-id"}'
headers:
content-type:
- application/json; charset=utf-8
date:
- Fri, 21 May 2021 17:18:35 GMT
server:
- Kestrel
transfer-encoding:
- chunked
status:
code: 200
message: OK
version: 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
interactions:
- request:
body: null
headers:
User-Agent:
- azsdk-python-identity/1.6.0b4 Python/3.8.6 (Linux-4.15.0-135-generic-x86_64-with-glibc2.2.5)
secret:
- redacted
method: GET
uri: https://msi-endpoint/token?api-version=2017-09-01&resource=https://management.azure.com
response:
body:
string: '{"access_token": "redacted", "expires_on": "05/22/2021 17:18:20 +00:00",
"resource": "https://management.azure.com", "token_type": "Bearer", "client_id":
"6d807b1c-2a6f-41a0-b428-d0e3a08382a0"}'
headers:
content-type: application/json; charset=utf-8
date: Fri, 21 May 2021 17:18:35 GMT
server: Kestrel
transfer-encoding: chunked
status:
code: 200
message: OK
url: http://172.16.7.2:8081/msi/token?api-version=2017-09-01&resource=https://management.azure.com
version: 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
interactions:
- request:
body: null
headers:
User-Agent:
- azsdk-python-identity/1.6.0b4 Python/3.8.6 (Linux-4.15.0-135-generic-x86_64-with-glibc2.2.5)
secret:
- redacted
method: GET
uri: https://msi-endpoint/token?api-version=2017-09-01&resource=https://management.azure.com&clientid=client-id
response:
body:
string: '{"access_token": "redacted", "expires_on": "05/22/2021 17:18:21 +00:00",
"resource": "https://management.azure.com", "token_type": "Bearer", "client_id":
"client-id"}'
headers:
content-type: application/json; charset=utf-8
date: Fri, 21 May 2021 17:18:35 GMT
server: Kestrel
transfer-encoding: chunked
status:
code: 200
message: OK
url: http://172.16.7.2:8081/msi/token?api-version=2017-09-01&resource=https://management.azure.com&clientid=b48ae5dc-70d0-488a-8ef5-f30d905cd5ec
version: 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
interactions:
- request:
body: null
headers:
Accept: ['*/*']
Accept-Encoding: ['gzip, deflate']
Connection: [keep-alive]
User-Agent: [azsdk-python-identity/1.6.0b4 Python/3.6.9 (Linux-5.4.0-1046-azure-x86_64-with-Ubuntu-18.04-bionic)]
method: GET
uri: http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com
response:
body: {string: '{"error": "invalid_request", "error_description": "Required metadata
header not specified"}'}
headers:
content-length: ['88']
content-type: [application/json; charset=utf-8]
date: ['Mon, 26 Apr 2021 22:13:41 GMT']
server: [IMDS/150.870.65.492]
status: {code: 400, message: Bad Request}
- request:
body: null
headers:
Accept: ['*/*']
Accept-Encoding: ['gzip, deflate']
Connection: [keep-alive]
Metadata: ['true']
User-Agent: [azsdk-python-identity/1.6.0b4 Python/3.6.9 (Linux-5.4.0-1046-azure-x86_64-with-Ubuntu-18.04-bionic)]
method: GET
uri: http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com
response:
body: {string: '{"access_token": "redacted", "client_id": "e15dd129-090a-41d4-add5-bb4b16b2b1a9",
"expires_in": "86104", "expires_on": "1619561325", "ext_expires_in": "86399",
"not_before": "1619474625", "resource": "https://management.azure.com", "token_type":
"Bearer"}'}
headers:
content-length: ['1692']
content-type: [application/json; charset=utf-8]
date: ['Mon, 26 Apr 2021 22:13:41 GMT']
server: [IMDS/150.870.65.492]
status: {code: 200, message: OK}
version: 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
interactions:
- request:
body: null
headers:
Accept: ['*/*']
Accept-Encoding: ['gzip, deflate']
Connection: [keep-alive]
User-Agent: [azsdk-python-identity/1.6.0b4 Python/3.6.9 (Linux-5.4.0-1046-azure-x86_64-with-Ubuntu-18.04-bionic)]
method: GET
uri: http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com&client_id=client-id
response:
body: {string: '{"error": "invalid_request", "error_description": "Required metadata
header not specified"}'}
headers:
content-length: ['88']
content-type: [application/json; charset=utf-8]
date: ['Mon, 26 Apr 2021 22:13:41 GMT']
server: [IMDS/150.870.65.492]
status: {code: 400, message: Bad Request}
- request:
body: null
headers:
Accept: ['*/*']
Accept-Encoding: ['gzip, deflate']
Connection: [keep-alive]
Metadata: ['true']
User-Agent: [azsdk-python-identity/1.6.0b4 Python/3.6.9 (Linux-5.4.0-1046-azure-x86_64-with-Ubuntu-18.04-bionic)]
method: GET
uri: http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com&client_id=client-id
response:
body: {string: '{"access_token": "redacted", "client_id": "client-id",
"expires_in": "86400", "expires_on": "1619561622", "ext_expires_in": "86399",
"not_before": "1619474922", "resource": "https://management.azure.com", "token_type":
"Bearer"}'}
headers:
content-length: ['1712']
content-type: [application/json; charset=utf-8]
date: ['Mon, 26 Apr 2021 22:13:41 GMT']
server: [IMDS/150.870.65.492]
status: {code: 200, message: OK}
version: 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
interactions:
- request:
body: null
headers:
User-Agent: [azsdk-python-identity/1.6.0b4 Python/3.6.9 (Linux-5.4.0-1046-azure-x86_64-with-Ubuntu-18.04-bionic)]
method: GET
uri: http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com
response:
body: {string: '{"error": "invalid_request", "error_description": "Required metadata
header not specified"}'}
headers: {content-length: '88', content-type: application/json; charset=utf-8,
date: 'Mon, 26 Apr 2021 22:13:42 GMT', server: IMDS/150.870.65.492}
status: {code: 400, message: Bad Request}
url: http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com
- request:
body: null
headers:
Metadata: ['true']
User-Agent: [azsdk-python-identity/1.6.0b4 Python/3.6.9 (Linux-5.4.0-1046-azure-x86_64-with-Ubuntu-18.04-bionic)]
method: GET
uri: http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com
response:
body: {string: '{"access_token": "redacted", "client_id": "e15dd129-090a-41d4-add5-bb4b16b2b1a9",
"expires_in": "86102", "expires_on": "1619561325", "ext_expires_in": "86399",
"not_before": "1619474625", "resource": "https://management.azure.com", "token_type":
"Bearer"}'}
headers: {content-length: '1692', content-type: application/json; charset=utf-8,
date: 'Mon, 26 Apr 2021 22:13:42 GMT', server: IMDS/150.870.65.492}
status: {code: 200, message: OK}
url: http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com
version: 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
interactions:
- request:
body: null
headers:
User-Agent: [azsdk-python-identity/1.6.0b4 Python/3.6.9 (Linux-5.4.0-1046-azure-x86_64-with-Ubuntu-18.04-bionic)]
method: GET
uri: http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com&client_id=client-id
response:
body: {string: '{"error": "invalid_request", "error_description": "Required metadata
header not specified"}'}
headers: {content-length: '88', content-type: application/json; charset=utf-8,
date: 'Mon, 26 Apr 2021 22:13:42 GMT', server: IMDS/150.870.65.492}
status: {code: 400, message: Bad Request}
url: http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com&client_id=b48ae5dc-70d0-488a-8ef5-f30d905cd5ec
- request:
body: null
headers:
Metadata: ['true']
User-Agent: [azsdk-python-identity/1.6.0b4 Python/3.6.9 (Linux-5.4.0-1046-azure-x86_64-with-Ubuntu-18.04-bionic)]
method: GET
uri: http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com&client_id=client-id
response:
body: {string: '{"access_token": "redacted", "client_id": "client-id",
"expires_in": "86399", "expires_on": "1619561622", "ext_expires_in": "86399",
"not_before": "1619474922", "resource": "https://management.azure.com", "token_type":
"Bearer"}'}
headers: {content-length: '1712', content-type: application/json; charset=utf-8,
date: 'Mon, 26 Apr 2021 22:13:42 GMT', server: IMDS/150.870.65.492}
status: {code: 200, message: OK}
url: http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com&client_id=b48ae5dc-70d0-488a-8ef5-f30d905cd5ec
version: 1
Loading

0 comments on commit 486beca

Please sign in to comment.