Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions sdk/identity/azure-identity/azure/identity/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
WorkloadIdentityCredential,
)
from ._persistent_cache import TokenCachePersistenceOptions
from ._bearer_token_provider import get_bearer_token_provider


__all__ = [
Expand Down Expand Up @@ -55,6 +56,7 @@
"UsernamePasswordCredential",
"VisualStudioCodeCredential",
"WorkloadIdentityCredential",
"get_bearer_token_provider",
]

from ._version import VERSION
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# ------------------------------------
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
# ------------------------------------
from typing import Callable

from azure.core.credentials import TokenCredential
from azure.core.pipeline.policies import BearerTokenCredentialPolicy
from azure.core.pipeline import PipelineRequest, PipelineContext
from azure.core.rest import HttpRequest


def _make_request() -> PipelineRequest[HttpRequest]:
return PipelineRequest(HttpRequest("CredentialWrapper", "https://fakeurl"), PipelineContext(None))


def get_bearer_token_provider(credential: TokenCredential, *scopes: str) -> Callable[[], str]:
"""Returns a callable that provides a bearer token.

It can be used for instance to write code like:

.. code-block:: python

from azure.identity import DefaultAzureCredential, get_bearer_token_provider

credential = DefaultAzureCredential()
bearer_token_provider = get_bearer_token_provider(credential, "https://storage.azure.com/.default")
Comment thread
lmazuel marked this conversation as resolved.
Outdated

# Usage
request.headers["Authorization"] = "Bearer " + bearer_token_provider()

:param credential: The credential used to authenticate the request.
:type credential: ~azure.core.credentials.TokenCredential
:param str scopes: The scopes required for the bearer token.
:rtype: callable
:return: A callable that returns a bearer token.
"""

policy = BearerTokenCredentialPolicy(credential, *scopes)

def wrapper() -> str:
request = _make_request()
policy.on_request(request)
return request.http_request.headers["Authorization"][len("Bearer ") :]

return wrapper
2 changes: 2 additions & 0 deletions sdk/identity/azure-identity/azure/identity/aio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
ClientAssertionCredential,
WorkloadIdentityCredential,
)
from ._bearer_token_provider import get_bearer_token_provider


__all__ = [
Expand All @@ -39,4 +40,5 @@
"VisualStudioCodeCredential",
"ClientAssertionCredential",
"WorkloadIdentityCredential",
"get_bearer_token_provider",
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# ------------------------------------
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
# ------------------------------------
from typing import Callable, Coroutine, Any

from azure.core.credentials_async import AsyncTokenCredential
from azure.core.pipeline.policies import AsyncBearerTokenCredentialPolicy
from azure.core.pipeline import PipelineRequest, PipelineContext
from azure.core.rest import HttpRequest


def _make_request() -> PipelineRequest[HttpRequest]:
return PipelineRequest(HttpRequest("CredentialWrapper", "https://fakeurl"), PipelineContext(None))


def get_bearer_token_provider(credential: AsyncTokenCredential, *scopes: str) -> Callable[[], Coroutine[Any, Any, str]]:
"""Returns a callable that provides a bearer token.

It can be used for instance to write code like:

.. code-block:: python

from azure.identity.aio import DefaultAzureCredential, get_bearer_token_provider

credential = DefaultAzureCredential()
bearer_token_provider = get_bearer_token_provider(credential, "https://storage.azure.com/.default")


# Usage
request.headers["Authorization"] = "Bearer " + await bearer_token_provider()

:param credential: The credential used to authenticate the request.
:type credential: ~azure.core.credentials.TokenCredential
Comment thread
lmazuel marked this conversation as resolved.
Outdated
:param str scopes: The scopes required for the bearer token.
:rtype: coroutine
:return: A coroutine that returns a bearer token.
"""

policy = AsyncBearerTokenCredentialPolicy(credential, *scopes)

async def wrapper() -> str:
request = _make_request()
await policy.on_request(request)
return request.http_request.headers["Authorization"][len("Bearer ") :]

return wrapper
3 changes: 2 additions & 1 deletion sdk/identity/azure-identity/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"License :: OSI Approved :: MIT License",
],
zip_safe=False,
Expand All @@ -59,7 +60,7 @@
),
python_requires=">=3.7",
install_requires=[
"azure-core<2.0.0,>=1.11.0",
"azure-core<2.0.0,>=1.23.0",
"cryptography>=2.5",
"msal<2.0.0,>=1.24.0",
"msal-extensions<2.0.0,>=0.3.0",
Expand Down
20 changes: 20 additions & 0 deletions sdk/identity/azure-identity/tests/test_bearer_token_provider.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# ------------------------------------
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
# ------------------------------------

from azure.core.credentials import AccessToken
from azure.identity import get_bearer_token_provider


class MockCredential:
def get_token(self, *scopes, **kwargs):
assert len(scopes) == 1
assert scopes[0] == "scope"
return AccessToken("mock_token", 42)


def test_get_bearer_token_provider():

func = get_bearer_token_provider(MockCredential(), "scope")
assert func() == "mock_token"
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# ------------------------------------
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
# ------------------------------------

from azure.core.credentials import AccessToken
from azure.identity.aio import get_bearer_token_provider

import pytest


class MockCredential:
async def get_token(self, *scopes, **kwargs):
assert len(scopes) == 1
assert scopes[0] == "scope"
return AccessToken("mock_token", 42)


@pytest.mark.asyncio
async def test_get_bearer_token_provider():

func = get_bearer_token_provider(MockCredential(), "scope")
assert await func() == "mock_token"