diff --git a/sdk/identity/azure-identity/CHANGELOG.md b/sdk/identity/azure-identity/CHANGELOG.md index 0938051e2af0..0b4cef2c0278 100644 --- a/sdk/identity/azure-identity/CHANGELOG.md +++ b/sdk/identity/azure-identity/CHANGELOG.md @@ -10,6 +10,8 @@ ### Other Changes +- Deprecated `UsernamePasswordCredential`, as it doesn't support multifactor authentication (MFA). MFA will soon be enforced on all Microsoft Entra tenants. For more details, see [Planning for mandatory MFA](https://aka.ms/mfaforazure). ([#39785](https://github.com/Azure/azure-sdk-for-python/pull/39785)) + ## 1.20.0 (2025-02-11) ### Features Added diff --git a/sdk/identity/azure-identity/README.md b/sdk/identity/azure-identity/README.md index c0d00fc0b975..0a2bc7419965 100644 --- a/sdk/identity/azure-identity/README.md +++ b/sdk/identity/azure-identity/README.md @@ -269,7 +269,7 @@ Not all credentials require this configuration. Credentials that authenticate th |[`DeviceCodeCredential`][device_code_cred_ref]| Interactively authenticates a user on devices with limited UI. | [Device code authentication](https://learn.microsoft.com/entra/identity-platform/v2-oauth2-device-code)| |[`InteractiveBrowserCredential`][interactive_cred_ref]| Interactively authenticates a user with the default system browser. | [OAuth2 authentication code](https://learn.microsoft.com/entra/identity-platform/v2-oauth2-auth-code-flow)| `InteractiveBrowserCredential` doesn't support GitHub Codespaces. As a workaround, use [`DeviceCodeCredential`][device_code_cred_ref]. |[`OnBehalfOfCredential`][obo_cred_ref]| Propagates the delegated user identity and permissions through the request chain. | [On-behalf-of authentication](https://learn.microsoft.com/entra/identity-platform/v2-oauth2-on-behalf-of-flow)| -|[`UsernamePasswordCredential`][userpass_cred_ref]| Authenticates a user with a username and password (doesn't support multifactor authentication). | [Username + password authentication](https://learn.microsoft.com/entra/identity-platform/v2-oauth-ropc)| +|[`UsernamePasswordCredential`][userpass_cred_ref]| **Deprecated** - Authenticates a user with a username and password (doesn't support multifactor authentication). | [Username + password authentication](https://learn.microsoft.com/entra/identity-platform/v2-oauth-ropc)| ### Authenticate via development tools @@ -305,6 +305,8 @@ variables: ### Username and password +> **Warning**: Username and password authentication doesn't support multifactor authentication (MFA) and is **deprecated**. For more details, see [Planning for mandatory MFA](https://aka.ms/azsdk/identity/mfa). + |Variable name|Value |-|- |`AZURE_CLIENT_ID`|ID of a Microsoft Entra application diff --git a/sdk/identity/azure-identity/TOKEN_CACHING.md b/sdk/identity/azure-identity/TOKEN_CACHING.md index 94517f1bc5da..a47ecf03039a 100644 --- a/sdk/identity/azure-identity/TOKEN_CACHING.md +++ b/sdk/identity/azure-identity/TOKEN_CACHING.md @@ -52,7 +52,7 @@ ClientSecretCredential( #### Persist user authentication record -When authenticating a user via `InteractiveBrowserCredential`, `DeviceCodeCredential`, or `UsernamePasswordCredential`, an `AuthenticationRecord` can be persisted as well. The authentication record is: +When authenticating a user via `InteractiveBrowserCredential` or `DeviceCodeCredential`, an `AuthenticationRecord` can be persisted as well. The authentication record is: - Returned from the `authenticate` API and contains data identifying an authenticated account. - Needed to identify the appropriate entry in the persisted token cache to silently authenticate on subsequent executions. @@ -68,7 +68,7 @@ record_json = record.serialize() #### Silently authenticating a user with AuthenticationRecord and TokenCachePersistenceOptions -Once an app has configured an `InteractiveBrowserCredential`, `DeviceCodeCredential`, or `UsernamePasswordCredential` to persist token data and an `AuthenticationRecord`, it's possible to silently authenticate. This example demonstrates an app setting the `TokenCachePersistenceOptions` and retrieving an `AuthenticationRecord` from the local file system to create an `InteractiveBrowserCredential` capable of silent authentication: +Once an app has configured an `InteractiveBrowserCredential` or `DeviceCodeCredential`, to persist token data and an `AuthenticationRecord`, it's possible to silently authenticate. This example demonstrates an app setting the `TokenCachePersistenceOptions` and retrieving an `AuthenticationRecord` from the local file system to create an `InteractiveBrowserCredential` capable of silent authentication: ```python deserialized_record = AuthenticationRecord.deserialize(record_json) @@ -101,5 +101,4 @@ The following table indicates the state of in-memory and persistent caching in e | `InteractiveBrowserCredential` | Supported | Supported | | `ManagedIdentityCredential` | Supported | Not Supported | | `OnBehalfOfCredential` | Supported | Supported | -| `UsernamePasswordCredential` | Supported | Supported | | `WorkloadIdentityCredential` | Supported | Not Supported | diff --git a/sdk/identity/azure-identity/azure/identity/_credentials/environment.py b/sdk/identity/azure-identity/azure/identity/_credentials/environment.py index 8f87a1d9ff97..d11fd00c1c68 100644 --- a/sdk/identity/azure-identity/azure/identity/_credentials/environment.py +++ b/sdk/identity/azure-identity/azure/identity/_credentials/environment.py @@ -46,6 +46,9 @@ class EnvironmentCredential: when no value is given. User with username and password: + **Deprecated**: Username and password authentication doesn't support multifactor authentication (MFA). + For more details on Microsoft Entra MFA enforcement, see https://aka.ms/azsdk/identity/mfa. + - **AZURE_CLIENT_ID**: the application's client ID - **AZURE_USERNAME**: a username (usually an email address) - **AZURE_PASSWORD**: that user's password diff --git a/sdk/identity/azure-identity/azure/identity/_credentials/user_password.py b/sdk/identity/azure-identity/azure/identity/_credentials/user_password.py index 5ca7a3efc418..cee3ad825766 100644 --- a/sdk/identity/azure-identity/azure/identity/_credentials/user_password.py +++ b/sdk/identity/azure-identity/azure/identity/_credentials/user_password.py @@ -3,6 +3,7 @@ # Licensed under the MIT License. # ------------------------------------ from typing import Any, Dict +import warnings from .._internal import InteractiveCredential, wrap_exceptions @@ -10,6 +11,9 @@ class UsernamePasswordCredential(InteractiveCredential): """Authenticates a user with a username and password. + **Deprecated**: This credential doesn't support multifactor authentication (MFA). + For more details on Microsoft Entra MFA enforcement, see https://aka.ms/azsdk/identity/mfa. + In general, Microsoft doesn't recommend this kind of authentication, because it's less secure than other authentication flows. @@ -59,6 +63,12 @@ class UsernamePasswordCredential(InteractiveCredential): """ def __init__(self, client_id: str, username: str, password: str, **kwargs: Any) -> None: + warnings.warn( + f"{self.__class__.__name__} is deprecated, as is it doesn't support multifactor " + "authentication (MFA). For more details, see https://aka.ms/azsdk/identity/mfa.", + category=DeprecationWarning, + stacklevel=2, + ) # The base class will accept an AuthenticationRecord, allowing this credential to authenticate silently the # first time it's asked for a token. However, we want to ensure this first authentication is not silent, to # validate the given password. This class therefore doesn't document the authentication_record argument, and we diff --git a/sdk/identity/azure-identity/samples/azure-aad-auth-with-redis-py.md b/sdk/identity/azure-identity/samples/azure-aad-auth-with-redis-py.md index 29baed01f08d..703a7cc37298 100644 --- a/sdk/identity/azure-identity/samples/azure-aad-auth-with-redis-py.md +++ b/sdk/identity/azure-identity/samples/azure-aad-auth-with-redis-py.md @@ -82,7 +82,6 @@ if __name__ == '__main__': - [Client Certificate Credential](https://aka.ms/azsdk/python/identity/certificatecredential) - [Client Secret Credential](https://aka.ms/azsdk/python/identity/clientsecretcredential) - [Managed Identity Credential](https://aka.ms/azsdk/python/identity/managedidentitycredential) -- [Username Password Credential](https://aka.ms/azsdk/python/identity/usernamepasswordcredential) - [Azure CLI Credential](https://aka.ms/azsdk/python/identity/azclicredential) - [Interactive Browser Credential](https://aka.ms/azsdk/python/identity/interactivebrowsercredential) - [Device Code Credential](https://aka.ms/azsdk/python/identity/devicecodecredential) @@ -188,7 +187,7 @@ To mitigate this error, navigate to your Azure Cache for Redis resource in the A ##### Managed Identity not working from Local Development Machine -Managed identity does not work from a local development machine. To use managed identity, your code must be running -in an Azure VM (or another type of resource in Azure). To run locally with Entra ID authentication, you'll need to +Managed identity does not work from a local development machine. To use managed identity, your code must be running +in an Azure VM (or another type of resource in Azure). To run locally with Entra ID authentication, you'll need to use a service principal or user account. This is a common source of confusion, so ensure that when developing locally, you configure your application to use a service principal or user credentials for authentication. diff --git a/sdk/identity/azure-identity/tests/test_username_password_credential.py b/sdk/identity/azure-identity/tests/test_username_password_credential.py index 3ce95488fc3b..dcf7b847957c 100644 --- a/sdk/identity/azure-identity/tests/test_username_password_credential.py +++ b/sdk/identity/azure-identity/tests/test_username_password_credential.py @@ -229,3 +229,8 @@ def test_claims_challenge(get_token_method): assert msal_app.acquire_token_silent_with_error.call_count == 1 args, kwargs = msal_app.acquire_token_silent_with_error.call_args assert kwargs["claims_challenge"] == expected_claims + + +def test_deprecation_warning(): + with pytest.deprecated_call(): + UsernamePasswordCredential("client-id", "username", "password")