Skip to content

Commit

Permalink
[Identity] Align samples with other languages (Azure#20966)
Browse files Browse the repository at this point in the history
  • Loading branch information
mccoyp committed Oct 1, 2021
1 parent 5ed3bcc commit fc95f8d
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 3 deletions.
4 changes: 2 additions & 2 deletions sdk/identity/azure-identity/samples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@ pip install azure-identity azure-keyvault-certificates azure-keyvault-secrets
| File | Description |
|-------------|-------------|
| control_interactive_prompts.py | demonstrates controlling when interactive credentials prompt for user interaction |
| custom_credentials.py | demonstrates custom credential implementation |
| custom_credentials.py | demonstrates custom credential implementations using existing access tokens and an MSAL client |
| key_vault_cert.py | demonstrates authenticating with a Key Vault certificate |
| user_authentication.py | demonstrates user authentication API for applications |
| user_authentication.py | demonstrates user authentication and token cache persistence API for applications |
27 changes: 26 additions & 1 deletion sdk/identity/azure-identity/samples/custom_credentials.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
# ------------------------------------
"""Demonstrates custom credential implementation"""
"""Demonstrates custom credential implementations using existing access tokens and an MSAL client"""

import time
from typing import TYPE_CHECKING

from azure.core.credentials import AccessToken
from azure.identity import AuthenticationRequiredError, AzureAuthorityHosts
import msal

if TYPE_CHECKING:
from typing import Any, Union
Expand All @@ -32,3 +35,25 @@ def get_token(self, *scopes, **kwargs):
"""get_token is the only method a credential must implement"""

return self._token


class MsalTokenCredential(object):
"""Uses an MSAL client directly to obtain access tokens with an interactive flow."""
def __init__(self, tenant_id, client_id):
# type: (str, str) -> None
self._app = msal.PublicClientApplication(
client_id=client_id, authority="https://{}/{}".format(AzureAuthorityHosts.AZURE_PUBLIC_CLOUD, tenant_id)
)

def get_token(self, *scopes, **kwargs):
# type: (*str, **Any) -> AccessToken
"""get_token is the only method a credential must implement"""

now = int(time.time())
result = self._app.acquire_token_interactive(list(scopes), **kwargs)

try:
return AccessToken(result["access_token"], now + int(result["expires_in"]))
except:
print("\nFailed to get a valid access token")
raise AuthenticationRequiredError(scopes)
13 changes: 13 additions & 0 deletions sdk/identity/azure-identity/samples/user_authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
# The 'authenticate' method begins interactive authentication. Call it whenever it's convenient
# for your application to authenticate a user. It returns a record of the authentication.
record = credential.authenticate()
print("\nAuthenticated first credential")

# The record contains no authentication secrets. You can serialize it to JSON for storage.
record_json = record.serialize()
Expand All @@ -33,6 +34,7 @@
# without prompting for authentication again.
client = SecretClient(VAULT_URL, credential)
secret_names = [s.name for s in client.list_properties_of_secrets()]
print("\nCompleted request with first credential")

# An authentication record stored by your application enables other credentials to access data from
# past authentications. If the cache contains sufficient data, this eliminates the need for your
Expand All @@ -45,3 +47,14 @@
# This request should also succeed without prompting for authentication.
client = SecretClient(VAULT_URL, new_credential)
secret_names = [s.name for s in client.list_properties_of_secrets()]
print("\nCompleted request with credential using shared cache")

# To isolate the token cache from other applications, you can provide a cache name to TokenCachePersistenceOptions.
separate_cache_credential = InteractiveBrowserCredential(
cache_persistence_options=TokenCachePersistenceOptions(name="my_app"), authentication_record=deserialized_record
)

# This request should prompt for authentication since the credential is using a separate cache.
client = SecretClient(VAULT_URL, separate_cache_credential)
secret_names = [s.name for s in client.list_properties_of_secrets()]
print("\nCompleted request with credential using separate cache")

0 comments on commit fc95f8d

Please sign in to comment.