|
| 1 | +--- |
| 2 | +title: ADAL to MSAL migration guide for Python | Azure |
| 3 | +description: Learn how to migrate your Azure Active Directory Authentication Library (ADAL) Python app to the Microsoft Authentication Library (MSAL) for Python. |
| 4 | +services: active-directory |
| 5 | +titleSuffix: Microsoft identity platform |
| 6 | +author: rayluo |
| 7 | +manager: henrikm |
| 8 | +editor: twhitney |
| 9 | + |
| 10 | +ms.service: active-directory |
| 11 | +ms.subservice: develop |
| 12 | +ms.devlang: na |
| 13 | +ms.topic: conceptual |
| 14 | +ms.tgt_pltfrm: Python |
| 15 | +ms.workload: identity |
| 16 | +ms.date: 11/11/2019 |
| 17 | +ms.author: rayluo |
| 18 | +ms.reviewer: |
| 19 | +ms.custom: aaddev |
| 20 | +#Customer intent: As a Python application developer, I want to learn how to migrate my v1 ADAL app to v2 MSAL. |
| 21 | +ms.collection: M365-identity-device-management |
| 22 | +--- |
| 23 | + |
| 24 | +# ADAL to MSAL migration guide for Python |
| 25 | + |
| 26 | +This article highlights changes you need to make to migrate an app that uses the Azure Active Directory Authentication Library (ADAL) to use the Microsoft Authentication Library (MSAL). |
| 27 | + |
| 28 | +## Difference highlights |
| 29 | + |
| 30 | +ADAL works with the Azure Active Directory v1.0 endpoint. The Microsoft Authentication Library (MSAL) works with the Microsoft identity platform--formerly known as the Azure Active Directory v2.0 endpoint. The Microsoft identity platform differs from Azure Active Directory v1.0 in that it: |
| 31 | + |
| 32 | +Supports: |
| 33 | + - Work and school accounts (Azure AD provisioned accounts) |
| 34 | + - Personal accounts (such as Outlook.com or Hotmail.com) |
| 35 | + - Your customers who bring their own email or social identity (such as LinkedIn, Facebook, Google) via the Azure AD B2C offering |
| 36 | + |
| 37 | +- Is standards compatible with: |
| 38 | + - OAuth v2.0 |
| 39 | + - OpenID Connect (OIDC) |
| 40 | + |
| 41 | +See [What's different about the Microsoft identity platform (v2.0) endpoint?](https://docs.microsoft.com/azure/active-directory/develop/azure-ad-endpoint-comparison) for more details. |
| 42 | + |
| 43 | +### Scopes not resources |
| 44 | + |
| 45 | +ADAL Python acquires tokens for resources, but MSAL Python acquires tokens for scopes. The API surface in MSAL Python does not have resource parameter anymore. You would need to provide scopes as a list of strings that declare the desired permissions and resources that are requested. To see some example of scopes, see [Microsoft Graph's scopes](https://docs.microsoft.com/graph/permissions-reference). |
| 46 | + |
| 47 | +### Error handling |
| 48 | + |
| 49 | +Azure Active Directory Authentication Library (ADAL) for Python uses the exception `AdalError` to indicate that there's been a problem. MSAL for Python typically uses error codes, instead. For more information, see [MSAL for Python error handling](msal-handling-exceptions.md#msal-for-python-error-handling). |
| 50 | + |
| 51 | +### API changes |
| 52 | + |
| 53 | +The following table lists an API in ADAL for Python, and the one to use in its place in MSAL for Python: |
| 54 | + |
| 55 | +| ADAL for Python API | MSAL for Python API | |
| 56 | +| ------------------- | ---------------------------------- | |
| 57 | +| [AuthenticationContext](https://adal-python.readthedocs.io/en/latest/#adal.AuthenticationContext) | [PublicClientApplication or ConfidentialClientApplication](https://msal-python.readthedocs.io/en/latest/#msal.ClientApplication.__init__) | |
| 58 | +| N/A | [get_authorization_request_url()](https://msal-python.readthedocs.io/en/latest/#msal.ClientApplication.get_authorization_request_url) | |
| 59 | +| [acquire_token_with_authorization_code()](https://adal-python.readthedocs.io/en/latest/#adal.AuthenticationContext.acquire_token_with_authorization_code) | [acquire_token_by_authorization_code()](https://msal-python.readthedocs.io/en/latest/#msal.ClientApplication.acquire_token_by_authorization_code) | |
| 60 | +| [acquire_token()](https://adal-python.readthedocs.io/en/latest/#adal.AuthenticationContext.acquire_token) | [acquire_token_silent()](https://msal-python.readthedocs.io/en/latest/#msal.ClientApplication.acquire_token_silent) | |
| 61 | +| [acquire_token_with_refresh_token()](https://adal-python.readthedocs.io/en/latest/#adal.AuthenticationContext.acquire_token_with_refresh_token) | N/A (See the section above) | |
| 62 | +| [acquire_user_code()](https://adal-python.readthedocs.io/en/latest/#adal.AuthenticationContext.acquire_user_code) | [initiate_device_flow()](https://msal-python.readthedocs.io/en/latest/#msal.PublicClientApplication.initiate_device_flow) | |
| 63 | +| [acquire_token_with_device_code()](https://adal-python.readthedocs.io/en/latest/#adal.AuthenticationContext.acquire_token_with_device_code) and [cancel_request_to_get_token_with_device_code()](https://adal-python.readthedocs.io/en/latest/#adal.AuthenticationContext.cancel_request_to_get_token_with_device_code) | [acquire_token_by_device_flow()](https://msal-python.readthedocs.io/en/latest/#msal.PublicClientApplication.acquire_token_by_device_flow) | |
| 64 | +| [acquire_token_with_username_password()](https://adal-python.readthedocs.io/en/latest/#adal.AuthenticationContext.acquire_token_with_username_password) | [acquire_token_by_username_password()](https://msal-python.readthedocs.io/en/latest/#msal.PublicClientApplication.acquire_token_by_username_password) | |
| 65 | +| [acquire_token_with_client_credentials()](https://adal-python.readthedocs.io/en/latest/#adal.AuthenticationContext.acquire_token_with_client_credentials) and [acquire_token_with_client_certificate()](https://adal-python.readthedocs.io/en/latest/#adal.AuthenticationContext.acquire_token_with_client_certificate) | [acquire_token_for_client()](https://msal-python.readthedocs.io/en/latest/#msal.ConfidentialClientApplication.acquire_token_for_client) | |
| 66 | +| N/A | [acquire_token_on_behalf_of()](https://msal-python.readthedocs.io/en/latest/#msal.ConfidentialClientApplication.acquire_token_on_behalf_of) | |
| 67 | +| [TokenCache()](https://adal-python.readthedocs.io/en/latest/#adal.TokenCache) | [SerializableTokenCache()](https://msal-python.readthedocs.io/en/latest/#msal.SerializableTokenCache) | |
| 68 | +| N/A | Cache with persistence, available from [MSAL Extensions](https://github.com/marstr/original-microsoft-authentication-extensions-for-python) | |
| 69 | + |
| 70 | +## Migrate existing refresh tokens for MSAL Python |
| 71 | + |
| 72 | +The Microsoft authentication library (MSAL) abstracts the concept of refresh tokens. MSAL Python provides an in-memory token cache by default so that you don't need to store, lookup, or update refresh tokens. Users will also see fewer sign-in prompts because refresh tokens can usually be updated without user intervention. For more information about the token cache, see [Custom token cache serialization in MSAL for Python](msal-python-token-cache-serialization.md). |
| 73 | + |
| 74 | +The following code will help you migrate your refresh tokens managed by another OAuth2 library (including but not limited to ADAL Python) to be managed by MSAL for Python. One reason for migrating those refresh tokens is to prevent existing users from needing to sign in again when you migrate your app to MSAL for Python. |
| 75 | + |
| 76 | +The method for migrating a refresh token is to use MSAL for Python to acquire a new access token using the previous refresh token. When the new refresh token is returned, MSAL for Python will store it in the cache. Here is an example of how to do it: |
| 77 | + |
| 78 | +```python |
| 79 | +from msal import PublicClientApplication |
| 80 | + |
| 81 | +def get_preexisting_rt_and_their_scopes_from_elsewhere(...): |
| 82 | + raise NotImplementedError("You will need to implement this by yourself") |
| 83 | + |
| 84 | +app = PublicClientApplication(..., token_cache=...) |
| 85 | + |
| 86 | +for old_rt, old_scope in get_preexisting_rt_and_their_scopes_from_elsewhere(...): |
| 87 | + # Assuming the old scope could be a space-delimited string. |
| 88 | + # MSAL expects a list, like ["scope1", "scope2"]. |
| 89 | + scopes = old_scope.split() |
| 90 | + # If your old refresh token came from ADAL for Python, which uses a resource rather than a scope, |
| 91 | + # you need to convert your v1 resource into v2 scopes |
| 92 | + # See https://docs.microsoft.com/azure/active-directory/develop/azure-ad-endpoint-comparison#scopes-not-resources |
| 93 | + # You may be able to append "/.default" to your v1 resource to form a scope |
| 94 | + # See https://docs.microsoft.com/azure/active-directory/develop/v2-permissions-and-consent#the-default-scope |
| 95 | + |
| 96 | + result = app.client.obtain_token_by_refresh_token(old_rt, scope=scopes) |
| 97 | + # When this call returns the new token(s), a new refresh token is issued by the Microsoft identity platform and MSAL for Python |
| 98 | + # stores it in the token cache. |
| 99 | +``` |
| 100 | + |
| 101 | +## Next steps |
| 102 | + |
| 103 | +For more information, refer to [v1.0 and v2.0 comparison](active-directory-v2-compare.md). |
0 commit comments