Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
5 changes: 5 additions & 0 deletions sdk/formrecognizer/azure-ai-formrecognizer/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## 1.0.0b3 (Unreleased)

**New features**

- Authentication using `azure-identity` credentials now supported
- see the [Azure Identity documentation](https://github.com/Azure/azure-sdk-for-python/blob/master/sdk/identity/azure-identity/README.md) for more information


## 1.0.0b2 (2020-05-06)

Expand Down
67 changes: 51 additions & 16 deletions sdk/formrecognizer/azure-ai-formrecognizer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,24 +66,55 @@ az cognitiveservices account show --name "resource-name" --resource-group "resou
```

#### Types of credentials
The `credential` parameter may be provided as a [AzureKeyCredential][azure-key-credential] from [azure.core][azure_core].
The `credential` parameter may be provided as a [AzureKeyCredential][azure-key-credential] from [azure.core][azure_core],
or as a credential type from Azure Active Directory.
See the full details regarding [authentication][cognitive_authentication] of cognitive services.

To use an [API key][cognitive_authentication_api_key],
pass the key as a string into an instance of `AzureKeyCredential("<api_key>")`.
The API key can be found in the Azure Portal or by running the following Azure CLI command:

```az cognitiveservices account keys list --name "resource-name" --resource-group "resource-group-name"```

Use the key as the credential parameter to authenticate the client:
```python
from azure.ai.formrecognizer import FormRecognizerClient
from azure.core.credentials import AzureKeyCredential

endpoint = "https://<region>.api.cognitive.microsoft.com/"
credential = AzureKeyCredential("<api_key>")
form_recognizer_client = FormRecognizerClient(endpoint, credential)
```
1. To use an [API key][cognitive_authentication_api_key],
pass the key as a string into an instance of `AzureKeyCredential("<api_key>")`.
The API key can be found in the Azure Portal or by running the following Azure CLI command:

```az cognitiveservices account keys list --name "resource-name" --resource-group "resource-group-name"```

Use the key as the credential parameter to authenticate the client:
```python
from azure.ai.formrecognizer import FormRecognizerClient
from azure.core.credentials import AzureKeyCredential

endpoint = "https://<region>.api.cognitive.microsoft.com/"
credential = AzureKeyCredential("<api_key>")
form_recognizer_client = FormRecognizerClient(endpoint, credential)
```

2. To use an [Azure Active Directory (AAD) token credential][cognitive_authentication_aad],
provide an instance of the desired credential type obtained from the
[azure-identity][azure_identity_credentials] library.
Note that regional endpoints do not support AAD authentication. Create a [custom subdomain][custom_subdomain]
name for your resource in order to use this type of authentication.

Authentication with AAD requires some initial setup:
* [Install azure-identity][install_azure_identity]
* [Register a new AAD application][register_aad_app]
* [Grant access][grant_role_access] to Form Recognizer by assigning the `"Cognitive Services User"` role to your service principal.

After setup, you can choose which type of [credential][azure_identity_credentials] from azure.identity to use.
As an example, [DefaultAzureCredential][default_azure_credential]
can be used to authenticate the client:

Set the values of the client ID, tenant ID, and client secret of the AAD application as environment variables:
AZURE_CLIENT_ID, AZURE_TENANT_ID, AZURE_CLIENT_SECRET

Use the returned token credential to authenticate the client:
```python
from azure.identity import DefaultAzureCredential
from azure.ai.formrecognizer import FormRecognizerClient
token_credential = DefaultAzureCredential()

form_recognizer_client = FormRecognizerClient(
endpoint="https://<my-custom-subdomain>.cognitiveservices.azure.com/",
credential=token_credential
)
```

## Key concepts

Expand All @@ -102,6 +133,7 @@ form_recognizer_client = FormRecognizerClient(endpoint, credential)
- Managing models created in your account.

Please note that models can also be trained using a graphical user interface such as the [Form Recognizer Labeling Tool][fr-labeling-tool].

### Long-Running Operations
Long-running operations are operations which consist of an initial request sent to the service to start an operation,
followed by polling the service at intervals to determine whether the operation has completed or failed, and if it has
Expand Down Expand Up @@ -349,6 +381,7 @@ These code samples show common scenario operations with the Azure Form Recognize
The async versions of the samples (the python sample files appended with `_async`) show asynchronous operations
with Form Recognizer and require Python 3.5 or later.

* Client authentication: [sample_authentication.py][sample_authentication] ([async_version][sample_authentication_async])
* Recognize receipts: [sample_recognize_receipts.py][sample_recognize_receipts] ([async version][sample_recognize_receipts_async])
* Recognize receipts from a URL: [sample_recognize_receipts_from_url.py][sample_recognize_receipts_from_url] ([async version][sample_recognize_receipts_from_url_async])
* Recognize content: [sample_recognize_content.py][sample_recognize_content] ([async version][sample_recognize_content_async])
Expand Down Expand Up @@ -410,6 +443,8 @@ This project has adopted the [Microsoft Open Source Code of Conduct][code_of_con
[coc_faq]: https://opensource.microsoft.com/codeofconduct/faq/
[coc_contact]: mailto:opencode@microsoft.com

[sample_authentication]: https://github.com/Azure/azure-sdk-for-python/tree/master/sdk/formrecognizer/azure-ai-formrecognizer/samples/sample_authentication.py
[sample_authentication_async]: https://github.com/Azure/azure-sdk-for-python/tree/master/sdk/formrecognizer/azure-ai-formrecognizer/samples/async_samples/sample_authentication_async.py
[sample_manage_custom_models]: https://github.com/Azure/azure-sdk-for-python/tree/master/sdk/formrecognizer/azure-ai-formrecognizer/samples/sample_manage_custom_models.py
[sample_manage_custom_models_async]: https://github.com/Azure/azure-sdk-for-python/tree/master/sdk/formrecognizer/azure-ai-formrecognizer/samples/async_samples/sample_manage_custom_models_async.py
[sample_recognize_content]: https://github.com/Azure/azure-sdk-for-python/tree/master/sdk/formrecognizer/azure-ai-formrecognizer/samples/sample_recognize_content.py
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,24 @@
Any,
IO,
Union,
TYPE_CHECKING,
TYPE_CHECKING
)
from azure.core.tracing.decorator import distributed_trace
from azure.core.polling import LROPoller
from azure.core.polling.base_polling import LROBasePolling
from azure.core.pipeline.policies import AzureKeyCredentialPolicy
from ._generated._form_recognizer_client import FormRecognizerClient as FormRecognizer
from ._response_handlers import (
prepare_us_receipt,
prepare_content_result,
prepare_form_result
)
from ._generated.models import AnalyzeOperationResult
from ._helpers import get_content_type, error_map, POLLING_INTERVAL, COGNITIVE_KEY_HEADER
from ._helpers import get_content_type, get_authentication_policy, error_map, POLLING_INTERVAL
from ._user_agent import USER_AGENT
from ._polling import AnalyzePolling
from ._form_training_client import FormTrainingClient
if TYPE_CHECKING:
from azure.core.credentials import AzureKeyCredential
from azure.core.credentials import AzureKeyCredential, TokenCredential


class FormRecognizerClient(object):
Expand All @@ -40,28 +39,39 @@ class FormRecognizerClient(object):
:param str endpoint: Supported Cognitive Services endpoints (protocol and hostname,
for example: https://westus2.api.cognitive.microsoft.com).
:param credential: Credentials needed for the client to connect to Azure.
This is an instance of AzureKeyCredential if using an API key.
:type credential: ~azure.core.credentials.AzureKeyCredential
This is an instance of AzureKeyCredential if using an API key or a token
credential from :mod:`azure.identity`.
:type credential: :class:`~azure.core.credentials.AzureKeyCredential` or
:class:`~azure.core.credentials.TokenCredential`

.. admonition:: Example:

.. literalinclude:: ../samples/sample_get_bounding_boxes.py
:start-after: [START create_form_recognizer_client]
:end-before: [END create_form_recognizer_client]
.. literalinclude:: ../samples/sample_authentication.py
:start-after: [START create_fr_client_with_key]
:end-before: [END create_fr_client_with_key]
:language: python
:dedent: 8
:caption: Creating the FormRecognizerClient with an endpoint and API key.

.. literalinclude:: ../samples/sample_authentication.py
:start-after: [START create_fr_client_with_aad]
:end-before: [END create_fr_client_with_aad]
:language: python
:dedent: 8
:caption: Creating the FormRecognizerClient with a token credential.
"""

def __init__(self, endpoint, credential, **kwargs):
# type: (str, AzureKeyCredential, Any) -> None
# type: (str, Union[AzureKeyCredential, TokenCredential], Any) -> None
self._endpoint = endpoint
self._credential = credential

authentication_policy = get_authentication_policy(credential)
self._client = FormRecognizer(
endpoint=self._endpoint,
credential=self._credential,
sdk_moniker=USER_AGENT,
authentication_policy=AzureKeyCredentialPolicy(credential, COGNITIVE_KEY_HEADER),
authentication_policy=authentication_policy,
**kwargs
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@
Optional,
Any,
Iterable,
Union,
TYPE_CHECKING,
)
from azure.core.tracing.decorator import distributed_trace
from azure.core.polling import LROPoller
from azure.core.polling.base_polling import LROBasePolling
from azure.core.pipeline.policies import AzureKeyCredentialPolicy
from ._generated.models import Model
from ._generated._form_recognizer_client import FormRecognizerClient as FormRecognizer
from ._generated.models import TrainRequest, TrainSourceFilter
from ._helpers import error_map, POLLING_INTERVAL, COGNITIVE_KEY_HEADER
from ._helpers import error_map, get_authentication_policy, POLLING_INTERVAL
from ._models import (
CustomFormModelInfo,
AccountProperties,
Expand All @@ -28,7 +28,7 @@
from ._polling import TrainingPolling
from ._user_agent import USER_AGENT
if TYPE_CHECKING:
from azure.core.credentials import AzureKeyCredential
from azure.core.credentials import AzureKeyCredential, TokenCredential
from azure.core.pipeline.transport import HttpResponse
PipelineResponseType = HttpResponse

Expand All @@ -42,26 +42,37 @@ class FormTrainingClient(object):
:param str endpoint: Supported Cognitive Services endpoints (protocol and hostname,
for example: https://westus2.api.cognitive.microsoft.com).
:param credential: Credentials needed for the client to connect to Azure.
This is an instance of AzureKeyCredential if using an API key.
:type credential: ~azure.core.credentials.AzureKeyCredential
This is an instance of AzureKeyCredential if using an API key or a token
credential from :mod:`azure.identity`.
:type credential: :class:`~azure.core.credentials.AzureKeyCredential` or
:class:`~azure.core.credentials.TokenCredential`

.. admonition:: Example:

.. literalinclude:: ../samples/sample_train_model_with_labels.py
:start-after: [START create_form_training_client]
:end-before: [END create_form_training_client]
.. literalinclude:: ../samples/sample_authentication.py
:start-after: [START create_ft_client_with_key]
:end-before: [END create_ft_client_with_key]
:language: python
:dedent: 8
:caption: Creating the FormTrainingClient with an endpoint and API key.

.. literalinclude:: ../samples/sample_authentication.py
:start-after: [START create_ft_client_with_aad]
:end-before: [END create_ft_client_with_aad]
:language: python
:dedent: 8
:caption: Creating the FormTrainingClient with a token credential.
"""

def __init__(self, endpoint, credential, **kwargs):
# type: (str, AzureKeyCredential, Any) -> None
# type: (str, Union[AzureKeyCredential, TokenCredential], Any) -> None

authentication_policy = get_authentication_policy(credential)
self._client = FormRecognizer(
endpoint=endpoint,
credential=credential,
sdk_moniker=USER_AGENT,
authentication_policy=AzureKeyCredentialPolicy(credential, COGNITIVE_KEY_HEADER),
authentication_policy=authentication_policy,
**kwargs
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
# ------------------------------------

import six
from azure.core.credentials import AzureKeyCredential
from azure.core.pipeline.policies import AzureKeyCredentialPolicy
from azure.core.exceptions import (
ResourceNotFoundError,
ResourceExistsError,
Expand All @@ -22,6 +24,21 @@
}


def get_authentication_policy(credential):
authentication_policy = None
if credential is None:
raise ValueError("Parameter 'credential' must not be None.")
if isinstance(credential, AzureKeyCredential):
authentication_policy = AzureKeyCredentialPolicy(
name=COGNITIVE_KEY_HEADER, credential=credential
)
elif credential is not None and not hasattr(credential, "get_token"):
raise TypeError("Unsupported credential: {}. Use an instance of AzureKeyCredential "
"or a token credential from azure.identity".format(type(credential)))

return authentication_policy


def get_content_type(form):
"""Source: https://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_numbers_in_files
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
)
from azure.core.tracing.decorator_async import distributed_trace_async
from azure.core.polling.async_base_polling import AsyncLROBasePolling
from azure.core.pipeline.policies import AzureKeyCredentialPolicy
from ._form_training_client_async import FormTrainingClient
from .._generated.aio._form_recognizer_client_async import FormRecognizerClient as FormRecognizer
from .._response_handlers import (
Expand All @@ -24,11 +23,12 @@
prepare_form_result
)
from .._generated.models import AnalyzeOperationResult
from .._helpers import get_content_type, error_map, POLLING_INTERVAL, COGNITIVE_KEY_HEADER
from .._helpers import get_content_type, get_authentication_policy, error_map, POLLING_INTERVAL
from .._user_agent import USER_AGENT
from .._polling import AnalyzePolling
if TYPE_CHECKING:
from azure.core.credentials import AzureKeyCredential
from azure.core.credentials_async import AsyncTokenCredential
from .._models import (
USReceipt,
FormPage,
Expand All @@ -45,32 +45,43 @@ class FormRecognizerClient(object):
:param str endpoint: Supported Cognitive Services endpoints (protocol and hostname,
for example: https://westus2.api.cognitive.microsoft.com).
:param credential: Credentials needed for the client to connect to Azure.
This is an instance of AzureKeyCredential if using an API key.
:type credential: ~azure.core.credentials.AzureKeyCredential
This is an instance of AzureKeyCredential if using an API key or a token
credential from :mod:`azure.identity`.
:type credential: :class:`~azure.core.credentials.AzureKeyCredential`
or :class:`~azure.core.credentials_async.AsyncTokenCredential`

.. admonition:: Example:

.. literalinclude:: ../samples/async_samples/sample_get_bounding_boxes_async.py
:start-after: [START create_form_recognizer_client_async]
:end-before: [END create_form_recognizer_client_async]
.. literalinclude:: ../samples/async_samples/sample_authentication_async.py
:start-after: [START create_fr_client_with_key_async]
:end-before: [END create_fr_client_with_key_async]
:language: python
:dedent: 8
:caption: Creating the FormRecognizerClient with an endpoint and API key.

.. literalinclude:: ../samples/async_samples/sample_authentication_async.py
:start-after: [START create_fr_client_with_aad_async]
:end-before: [END create_fr_client_with_aad_async]
:language: python
:dedent: 8
:caption: Creating the FormRecognizerClient with a token credential.
"""

def __init__(
self,
endpoint: str,
credential: "AzureKeyCredential",
credential: Union["AzureKeyCredential", "AsyncTokenCredential"],
**kwargs: Any
) -> None:

authentication_policy = get_authentication_policy(credential)
self._endpoint = endpoint
self._credential = credential
self._client = FormRecognizer(
endpoint=self._endpoint,
credential=self._credential,
sdk_moniker=USER_AGENT,
authentication_policy=AzureKeyCredentialPolicy(credential, COGNITIVE_KEY_HEADER),
authentication_policy=authentication_policy,
**kwargs
)

Expand Down
Loading