diff --git a/msal-python-conceptual/TOC.yml b/msal-python-conceptual/TOC.yml index ba41eef..35dd4c2 100644 --- a/msal-python-conceptual/TOC.yml +++ b/msal-python-conceptual/TOC.yml @@ -1,19 +1,17 @@ - name: Getting started href: index.md items: - - name: Why use MSAL Python - href: getting-started/why-use-msal-python.md - name: Register your app with Azure AD href: /azure/active-directory/develop/active-directory-integrating-applications - name: Client applications href: getting-started/client-applications.md - name: Acquiring tokens href: getting-started/acquiring-tokens.md - - name: Calling a protected API - href: getting-started/call-protected-web-api.md - name: Advanced topics items: + - name: Using MSAL Python with Web Account Manager + href: advanced/wam.md - name: Migrate to MSAL Python href: /azure/active-directory/develop/migrate-python-adal-msal - name: Logging diff --git a/msal-python-conceptual/advanced/wam.md b/msal-python-conceptual/advanced/wam.md new file mode 100644 index 0000000..249c229 --- /dev/null +++ b/msal-python-conceptual/advanced/wam.md @@ -0,0 +1,97 @@ +--- +title: Using MSAL Python with Web Account Manager +description: "If you are building a Windows application, you might consider simplifying how users authenticate with the help of an authentication broker - the Web Account Manager." +--- + +# Using MSAL Python with Web Account Manager + +If you are building a Windows application, you might consider simplifying how users authenticate with the help of an _authentication broker_ - the [Web Account Manager](/windows/uwp/security/web-account-manager) (WAM). + +>[!NOTE] +>WAM is only available on Windows 10 and above, as well as Windows Server 2019 and above. + +To learn more about the benefits of using an authentication broker, refer to [What is a broker](/entra/msal/dotnet/acquiring-tokens/desktop-mobile/wam#what-is-a-broker) in the MSAL.NET documentation. + +## Usage + +To use the broker, you will need to install the broker-related packages in addition to the core MSAL from PyPI: + +```bash +pip install msal[broker]>=1.20,<2 +``` + +>[!IMPORTANT] +>If broker-related packages are not installed and you will try to use the authentication broker, you will get an error: `ImportError: You need to install dependency by: pip install "msal[broker]>=1.20,<2"`. + +Next, you will need to instantiate a new [`PublicClientApplication`](xref:msal.application.PublicClientApplication) and set `allow_broker` to `True`. This will ensure that MSAL will try and communicate with WAM instead of popping up a new browser window. + +```python +from msal import PublicClientApplication + +app = PublicClientApplication( + "CLIENT_ID", + authority="https://login.microsoftonline.com/common", + allow_broker=True) +``` + +You can now acquire a token by calling [`acquire_token_interactive`](xref:msal.application.PublicClientApplication.acquire_token_interactive) and specifying a parent window handle through `parent_window_handle`: + +```python +result = app.acquire_token_interactive(["User.ReadBasic.All"], + parent_window_handle=app.CONSOLE_WINDOW_HANDLE) +``` + +A parent window handle is required by WAM to ensure that the dialog is shown correctly on top of the requesting window. MSAL does not infer this directly due to the fact that there are many variables that might influence what window WAM needs to bind to, and developers building applications are best suited to decide what window that should be. + +For console applications, MSAL makes it easy by offering an out-of-the-box solution to getting the window handle for the terminal - [`CONSOLE_WINDOW_HANDLE`](xref:msal.application.PublicClientApplication.CONSOLE_WINDOW_HANDLE). For desktop applications, additional work with the Windows API might be required to [get the window handle](/windows/apps/develop/ui-input/retrieve-hwnd). Helper packages, like [pywin32](https://pypi.org/project/pywin32/) can help with API calls. + +Before executing your application, make sure that you configure the redirect URL for the desktop app: + +>[!IMPORTANT] +>To use the Windows broker, your application needs to have the correct redirect URL configured in the Azure Portal, in the shape of: +> +>```bash +>ms-appx-web://microsoft.aad.brokerplugin/YOUR_CLIENT_ID +>``` +> +>If the redirect URL is not configured, you will get a `broker_error` similar to `(pii). Status: Response_Status.Status_ApiContractViolation, Error code: 3399614473, Tag: 557973642`. + +If configuration and instantiation was correct, once you run the application you should see the authentication broker kick in and allow the user to select the account they want to authenticate with. + +![Example of WAM being called from Python](../media/wam-python.gif) + +Worth noting that if you switch to using broker-based authentication, if the user was previously logged in and the signed-in state is still valid, calling [`acquire_token_interactive`](xref:msal.application.PublicClientApplication.acquire_token_interactive) will still result in a silent attempt to acquire a token, and only prompt when necessary. If you prefer to always prompt, you can use this optional parameter `prompt="select_account"`. + +## Broker experience differences + +Depending on the authority specified when instantiating [`PublicClientApplication`](xref:msal.application.PublicClientApplication), the broker user interface may be different. + +### `/consumers` + +Used for authenticating **only** with personal Microsoft accounts. + +![WAM UI for consumers](../media/wam-consumers.png) + +### `/common` + +Used for authenticating with personal Microsoft accounts as well as work and school accounts. + +![WAM UI for personal and work accounts](../media/wam-common.png) + +### `/organizations` + +Used for authenticating **only** with work and school accounts. + +![WAM UI for work accounts only](../media/wam-organizations.png) + +>[!NOTE] +>If `login_hint` is provided but the account is not yet registered in WAM, the hint will be automatically filled in the "Email or phone" field. + +### `/TENANT_ID` + +Used for authenticating **only** with work and school accounts within the specified tenant. + +![WAM UI for tenant-specific accounts](../media/wam-tenant-specific.png) + +>[!NOTE] +>If `login_hint` is provided but the account is not yet registered in WAM, the hint will be automatically filled in the "Email or phone" field. diff --git a/msal-python-conceptual/docfx.json b/msal-python-conceptual/docfx.json index aa8c444..7df17e3 100644 --- a/msal-python-conceptual/docfx.json +++ b/msal-python-conceptual/docfx.json @@ -25,7 +25,8 @@ { "files": [ "**/*.png", - "**/*.jpg" + "**/*.jpg", + "**/*.gif" ], "exclude": [ "**/obj/**", diff --git a/msal-python-conceptual/getting-started/acquiring-tokens.md b/msal-python-conceptual/getting-started/acquiring-tokens.md index 57f1225..4e49ad3 100644 --- a/msal-python-conceptual/getting-started/acquiring-tokens.md +++ b/msal-python-conceptual/getting-started/acquiring-tokens.md @@ -13,7 +13,7 @@ Before acquiring tokens with MSAL Python, make sure to instantiate a [client app ## Token acquisition methods -The approach to acquiring a token is different depending on the application type - public client applications (desktop and mobile) or confidential client application (web app, web API, or a daemon application like a Windows service). Each of the individual approaches is described below. +The approach to acquiring a token is different depending on the application type - public client applications (desktop and mobile) or confidential client application (web app, web API, or a daemon application like a Windows service). Each of the individual approaches is described below. ### Public client applications diff --git a/msal-python-conceptual/getting-started/call-protected-web-api.md b/msal-python-conceptual/getting-started/call-protected-web-api.md deleted file mode 100644 index 011575d..0000000 --- a/msal-python-conceptual/getting-started/call-protected-web-api.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: Call a protected web API -description: "Getting a token is not a goal per se. It's a necessary step to call a protected API. The token needs to be used to access a Web API." ---- - -# Call a protected web API - -## Using the token - -Getting a token is not a goal per se. It's a necessary step to call a protected API. The token needs to be used to access a Web API. The way to do it is by setting the Authorization header to be "Bearer", followed by a space, followed by the access token. - -## Using the access token to call a protected Web API - -Note that the code below shows how to call directly the web API with Requests. You can also use libraries which will only require the access token (DocumentDb for instance) and will take care of the headers details. In practice the code might change depending on the libraries you want to use. - -```python -endpoint = "url to the API" -http_headers = {'Authorization': 'Bearer ' + result['access_token'], - 'Accept': 'application/json', - 'Content-Type': 'application/json'} -data = requests.get(endpoint, headers=http_headers, stream=False).json() -``` diff --git a/msal-python-conceptual/getting-started/client-applications.md b/msal-python-conceptual/getting-started/client-applications.md index a3e198c..bf37c77 100644 --- a/msal-python-conceptual/getting-started/client-applications.md +++ b/msal-python-conceptual/getting-started/client-applications.md @@ -17,7 +17,7 @@ Before instantiating your app with MSAL Python: - The identity provider URL (the instance) and the sign-in audience for your application. These two parameters are collectively known as the **authority**. - If necessary, the tenant identifier (also a GUID) in case you are writing a line of business application scoped to just your organization (also known as a single-tenant application). - If you are building a confidential client app, you will need to create an application secret in the form of a string or certificate. - - For web applications, you'll have also set the redirect URL that Azure AD will use to return the code. + - For web applications, you'll have also set the redirect URL that Azure AD will use to return the code. For desktop applications you will need to add `http://localhost` if you're not relying on authentication brokers. ### Instantiating a public client application diff --git a/msal-python-conceptual/getting-started/why-use-msal-python.md b/msal-python-conceptual/getting-started/why-use-msal-python.md deleted file mode 100644 index 85b0522..0000000 --- a/msal-python-conceptual/getting-started/why-use-msal-python.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: Why use MSAL Python? -description: "MSAL Python (Microsoft Authentication Library for Python) enables developers to acquire tokens in order to call secured Web APIs**. These Web APIs can be the Microsoft Graph, other Microsoft APIS, 3rd party Web APIs, or your own Web API." ---- - -# Why use MSAL Python? - -MSAL Python ([Microsoft Authentication Library for Python](https://github.com/AzureAD/microsoft-authentication-library-for-python)) enables developers to [acquire tokens](./acquiring-tokens.md) in order to call secured Web APIs. These Web APIs can be Microsoft Graph, other Microsoft APIS, 3rd party Web APIs, or your own Web API. - -## MSAL Python Supports multiple application architectures - -MSAL Python supports all the possible application topologies including: - -- [native client](/azure/active-directory/develop/active-directory-dev-glossary#native-client) (desktop applications) calling the Microsoft Graph in the name of the user, -- daemons/services or [web clients](/azure/active-directory/develop/active-directory-dev-glossary#web-client) (Web Apps/ Web APIs) calling the Microsoft Graph in the name of a user, or without a user. - -With the exception of: - -- [User-agent based client](/azure/active-directory/develop/active-directory-dev-glossary#user-agent-based-client) which is only supported in JavaScript - -For details about the supported scenarios see [Scenarios](https://github.com/AzureAD/microsoft-authentication-library-for-python/wiki/Scenarios). - -## Added value by using MSAL Python over OAuth libraries or coding against the protocol - -MSAL Python is a token acquisition library. Depending on your scenario it provides you with various way of getting a token, with a consistent API for a number of platforms. -It also adds value by: - -- maintaining a **token cache** and **refreshes tokens** for you when they are close to expire. - > you don't need to handle expiration on your own. -- helping you specify which **audience** you want your application to sign-in (your org, several orgs, work and school and Microsoft personal accounts, Social identities with Azure AD B2C, users in sovereign and national clouds) -- **helping you troubleshoot** your app by exposing actionable exceptions, logging and telemetry. - -## MSAL Python is about acquiring tokens, not protecting an API - -MSAL Python is used to acquire tokens. It's not used to protect a Web API. If you are interested in protecting a Web API with Azure AD, you might want to check out: - -- [Validating tokens manually](/azure/active-directory/develop/access-tokens#validating-tokens) diff --git a/msal-python-conceptual/index.md b/msal-python-conceptual/index.md index 29244e6..e4febb5 100644 --- a/msal-python-conceptual/index.md +++ b/msal-python-conceptual/index.md @@ -22,28 +22,39 @@ pip install msal ## Setting up -Before using MSAL Python, make sure to [register your application](/azure/active-directory/develop/quickstart-v2-register-an-app) with the Microsoft identity platform. +Before using MSAL Python, make sure to [register your application](/azure/active-directory/develop/quickstart-v2-register-an-app) with the Microsoft identity platform. You will need to take note of your **client ID** and **tenant ID**. -## Usage +>[!IMPORTANT] +>When registering the application, make sure that you set up **redirect URLs** within the **Authentication** blade. Redirect URLs vary depending on the target platform. +> +>![Screenshot showing redirect URLs in Azure Portal](./media/redirect-urls.png) +> +>For desktop and mobile applications, make sure you add `http://localhost` as redirect URL if you do not rely on authentication brokers. + +## Basic usage Acquiring tokens with MSAL Python follows a three-step pattern. There will be some variations for different flows. If you would like to see them in action, download our [samples](https://github.com/AzureAD/microsoft-authentication-library-for-python/tree/dev/sample). 1. MSAL relies on a clean separation between [public client and confidential client applications](https://tools.ietf.org/html/rfc6749#section-2.1). Therefore, create either a [`PublicClientApplication`](xref:msal.application.PublicClientApplication) or a [`ConfidentialClientApplication`](xref:msal.application.ConfidentialClientApplication) instance and reuse it during the lifecycle of your application. For example, for a public client application, the initalization code might look like this: - ```python - from msal import PublicClientApplication - app = PublicClientApplication( - "your_client_id", - authority="https://login.microsoftonline.com/Enter_the_Tenant_Name_Here") - ``` + ```python + from msal import PublicClientApplication - Later, each time you would want an access token, you start by declaring a variable that will hold the token result: + app = PublicClientApplication( + "your_client_id", + authority="https://login.microsoftonline.com/common") + ``` - ```python - result = None # It is just an initial value. Please follow instructions below. - ``` + >[!NOTE] + >The authority is set to `/common` to allow sign ins with both organizaiton and personal Microsoft accounts. You can change it to `/organizations` to only allow sign ins with work and school accounts, `/consumers` to only allow personal Microsoft accounts, or with `/YOUR_TENANT_ID` to only allow sign ins from work and school accounts associated with your tenant. + + Instantiate a variable to hold the authentication result: + + ```python + result = None # It is just an initial value. Please follow instructions below. + ``` -2. The API model in MSAL provides you explicit control on how to utilize the token cache. While the caching part is technically optional, we highly recommend you to use it in your application. Using the cache you can ensure that you're not making any extra API calls and handle the token refresh automatically. +2. Try and obtain the tokens from the cache first. The API model in MSAL provides you explicit control on how to utilize the token cache. While the caching part is technically optional, we highly recommend you to use it in your application. Using the cache you can ensure that you're not making any extra API calls and handle the token refresh automatically. ```python # We now check the cache to see @@ -57,15 +68,15 @@ Acquiring tokens with MSAL Python follows a three-step pattern. There will be so # Assuming the end user chose this one chosen = accounts[0] # Now let's try to find a token in cache for this account - result = app.acquire_token_silent(["your_scope"], account=chosen) + result = app.acquire_token_silent(["User.Read"], account=chosen) ``` -3. If there is no suitable token in the cache or you've chosen to skip the previous step, send a request to Azure AD to get a token. There are different methods based on your client type and scenario. A sample flow can look like this: +3. If there is no suitable token in the cache or you've chosen to skip the previous step, send a request to Azure AD to get a token. There are different methods based on your client type and scenario, but for the purposes of the example we're showing how to use [`acquire_token_interactive`](xref:msal.application.PublicClientApplication.acquire_token_interactive) which will prompt the user to provide their credentials. ```python if not result: # So no suitable token exists in cache. Let's get a new one from Azure AD. - result = app.acquire_token_by_one_of_the_actual_method(..., scopes=["User.Read"]) + result = app.acquire_token_interactive(scopes=["User.Read"]) if "access_token" in result: print(result["access_token"]) # Yay! else: @@ -74,6 +85,18 @@ Acquiring tokens with MSAL Python follows a three-step pattern. There will be so print(result.get("correlation_id")) # You may need this when reporting a bug ``` +4. Save the code into a Python file locally, such as `msaltest.py`. +5. Run the code by executing `python .\msalpytest.py`. + +>[!NOTE] +>You can also download runnable samples from the [library repository](https://github.com/AzureAD/microsoft-authentication-library-for-python/blob/1.22.0/sample/interactive_sample.py). + +If the application was configured correctly, you should see a web browser window appear asking the user to sign in. + +![Example of an app prompting the user to sign in with their account](./media/basic-pca-app-prompt.gif) + +Once the authentication is completed and you closed the browser, you should be able to see the access token printed in the terminal. + ## Usage scenarios MSAL Python can be used by applications to acquire tokens to access protected APIs. Tokens can be acquired by different **application types**: desktop applications, web applications, web APIs, and applications running on devices that don't have a browser (such as IoT devices). In MSAL Python, applications are categorized as follows: @@ -95,4 +118,8 @@ Key scenarios supported by MSAL Python: - [Desktop/service daemon application calling Web API without a user](/azure/active-directory/develop/scenario-daemon-overview) - [Application without a browser, or IOT application calling an API in the name of the user](/azure/active-directory/develop/scenario-desktop-acquire-token?tabs=python#command-line-tool-without-web-browser) -Can't find the scenario you are looking for? Check out the [supported scenarios and platforms](/azure/active-directory/develop/authentication-flows-app-scenarios#scenarios-and-supported-platforms-and-languages) across MSAL libraries. \ No newline at end of file +Can't find the scenario you are looking for? Check out the [supported scenarios and platforms](/azure/active-directory/develop/authentication-flows-app-scenarios#scenarios-and-supported-platforms-and-languages) across MSAL libraries. + +## Releases + +Refer to [MSAL Python releases on GitHub](https://github.com/AzureAD/microsoft-authentication-library-for-python/releases). diff --git a/msal-python-conceptual/media/basic-pca-app-prompt.gif b/msal-python-conceptual/media/basic-pca-app-prompt.gif new file mode 100644 index 0000000..c52c927 Binary files /dev/null and b/msal-python-conceptual/media/basic-pca-app-prompt.gif differ diff --git a/msal-python-conceptual/media/redirect-urls.png b/msal-python-conceptual/media/redirect-urls.png new file mode 100644 index 0000000..bdfb9a3 Binary files /dev/null and b/msal-python-conceptual/media/redirect-urls.png differ diff --git a/msal-python-conceptual/media/wam-common.png b/msal-python-conceptual/media/wam-common.png new file mode 100644 index 0000000..7c79938 Binary files /dev/null and b/msal-python-conceptual/media/wam-common.png differ diff --git a/msal-python-conceptual/media/wam-consumers.png b/msal-python-conceptual/media/wam-consumers.png new file mode 100644 index 0000000..1a33da4 Binary files /dev/null and b/msal-python-conceptual/media/wam-consumers.png differ diff --git a/msal-python-conceptual/media/wam-organizations.png b/msal-python-conceptual/media/wam-organizations.png new file mode 100644 index 0000000..c130242 Binary files /dev/null and b/msal-python-conceptual/media/wam-organizations.png differ diff --git a/msal-python-conceptual/media/wam-python.gif b/msal-python-conceptual/media/wam-python.gif new file mode 100644 index 0000000..3e17185 Binary files /dev/null and b/msal-python-conceptual/media/wam-python.gif differ diff --git a/msal-python-conceptual/media/wam-tenant-specific.png b/msal-python-conceptual/media/wam-tenant-specific.png new file mode 100644 index 0000000..6bbcad0 Binary files /dev/null and b/msal-python-conceptual/media/wam-tenant-specific.png differ diff --git a/python/docfx.json b/python/docfx.json index a5ed63a..6fd1f17 100644 --- a/python/docfx.json +++ b/python/docfx.json @@ -54,7 +54,8 @@ { "files": [ "**/*.png", - "**/*.jpg" + "**/*.jpg", + "**/*.gif" ], "exclude": [ "**/obj/**",