Provided by: python3-msal_1.32.3-1_all 

NAME
msalpython - MSAL Python Documentation
You can find high level conceptual documentations in the project README.
SCENARIOS
There are many different application scenarios. MSAL Python supports some of them. The following
diagram serves as a map. Locate your application scenario on the map. If the corresponding icon is
clickable, it will bring you to an MSAL Python sample for that scenario.
• Most authentication scenarios acquire tokens representing the signed-in user.
• There are also daemon apps, who acquire tokens representing themselves, not a user.
• There are other less common samples, such for ADAL-to-MSAL migration, available inside the project code
base.
API REFERENCE
NOTE:
Only the contents inside this source file and their documented methods (unless otherwise marked as
deprecated) are MSAL Python public API, which are guaranteed to be backward-compatible until the next
major version.
Everything else, regardless of their naming, are all internal helpers, which could change at anytime
in the future, without prior notice.
The following section is the API Reference of MSAL Python. The API Reference is like a dictionary, which
is useful when:
• You already followed our sample(s) above and have your app up and running, but want to know more on how
you could tweak the authentication experience by using other optional parameters (there are plenty of
them!)
• Some important features have their in-depth documentations in the API Reference.
MSAL proposes a clean separation between public client applications and confidential client applications.
They are implemented as two separated classes, with different methods for different authentication
scenarios.
ClientApplication
class msal.ClientApplication(client_id, client_credential=None, authority=None, validate_authority=True,
token_cache=None, http_client=None, verify=True, proxies=None, timeout=None, client_claims=None,
app_name=None, app_version=None, client_capabilities=None, azure_region=None, exclude_scopes=None,
http_cache=None, instance_discovery=None, allow_broker=None, enable_pii_log=None, oidc_authority=None)
You do not usually directly use this class. Use its subclasses instead: PublicClientApplication
and ConfidentialClientApplication.
__init__(client_id, client_credential=None, authority=None, validate_authority=True,
token_cache=None, http_client=None, verify=True, proxies=None, timeout=None, client_claims=None,
app_name=None, app_version=None, client_capabilities=None, azure_region=None, exclude_scopes=None,
http_cache=None, instance_discovery=None, allow_broker=None, enable_pii_log=None,
oidc_authority=None)
Create an instance of application.
Parameters
• client_id (str) -- Your app has a client_id after you register it on Microsoft
Entra admin center.
• client_credential (Union[dict, str, None]) --
For PublicClientApplication, you use None here.
For ConfidentialClientApplication, it supports many different input formats for
different scenarios.
Support using a client secret.
Just feed in a string, such as "your client secret".
Support using a certificate in X.509 (.pem) format
Feed in a dict in this form:
{
"private_key": "...-----BEGIN PRIVATE KEY-----... in PEM format",
"thumbprint": "A1B2C3D4E5F6...",
"passphrase": "Passphrase if the private_key is encrypted (Optional. Added in version 1.6.0)",
}
MSAL Python requires a "private_key" in PEM format. If your cert is in PKCS12
(.pfx) format, you can convert it to X.509 (.pem) format, by openssl pkcs12 -in
file.pfx -out file.pem -nodes.
The thumbprint is available in your app's registration in Azure Portal.
Alternatively, you can calculate the thumbprint.
Support Subject Name/Issuer Auth with a cert in .pem
Subject Name/Issuer Auth is an approach to allow easier certificate
rotation.
Added in version 0.5.0:
{
"private_key": "...-----BEGIN PRIVATE KEY-----... in PEM format",
"thumbprint": "A1B2C3D4E5F6...",
"public_certificate": "...-----BEGIN CERTIFICATE-----...",
"passphrase": "Passphrase if the private_key is encrypted (Optional. Added in version 1.6.0)",
}
public_certificate (optional) is public key certificate which will be sent
through 'x5c' JWT header only for subject name and issuer authentication to
support cert auto rolls.
Per specs, "the certificate containing the public key corresponding to the key
used to digitally sign the JWS MUST be the first certificate. This MAY be
followed by additional certificates, with each subsequent certificate being the
one used to certify the previous one." However, your certificate's issuer may
use a different order. So, if your attempt ends up with an error AADSTS700027
- "The provided signature value did not match the expected signature value",
you may try use only the leaf cert (in PEM/str format) instead.
Supporting raw assertion obtained from elsewhere
Added in version 1.13.0: It can also be a completely pre-signed
assertion that you've assembled yourself. Simply pass a container
containing only the key "client_assertion", like this:
{
"client_assertion": "...a JWT with claims aud, exp, iss, jti, nbf, and sub..."
}
Supporting reading client cerficates from PFX files
Added in version 1.29.0: Feed in a dictionary containing the path to a
PFX file:
{
"private_key_pfx_path": "/path/to/your.pfx",
"passphrase": "Passphrase if the private_key is encrypted (Optional)",
}
The following command will generate a .pfx file from your .key and .pem file:
openssl pkcs12 -export -out certificate.pfx -inkey privateKey.key -in certificate.pem
Support Subject Name/Issuer Auth with a cert in .pfx
Added in version 1.30.0: If your .pfx file contains both the private key
and public cert, you can opt in for Subject Name/Issuer Auth like this:
{
"private_key_pfx_path": "/path/to/your.pfx",
"public_certificate": True,
"passphrase": "Passphrase if the private_key is encrypted (Optional)",
}
• client_claims (dict) --
Added in version 0.5.0: It is a dictionary of extra claims that would be signed by
by this ConfidentialClientApplication 's private key. For example, you can use
{"client_ip": "x.x.x.x"}. You may also override any of the following default
claims:
{
"aud": the_token_endpoint,
"iss": self.client_id,
"sub": same_as_issuer,
"exp": now + 10_min,
"iat": now,
"jti": a_random_uuid
}
• authority (str) --
A URL that identifies a token authority. It should be of the format
https://login.microsoftonline.com/your_tenant By default, we will use
https://login.microsoftonline.com/common
Changed in version 1.17: you can also use predefined constant and a builder like
this:
from msal.authority import (
AuthorityBuilder,
AZURE_US_GOVERNMENT, AZURE_CHINA, AZURE_PUBLIC)
my_authority = AuthorityBuilder(AZURE_PUBLIC, "contoso.onmicrosoft.com")
# Now you get an equivalent of
# "https://login.microsoftonline.com/contoso.onmicrosoft.com"
# You can feed such an authority to msal's ClientApplication
from msal import PublicClientApplication
app = PublicClientApplication("my_client_id", authority=my_authority, ...)
• validate_authority (bool) -- (optional) Turns authority validation on or off. This
parameter default to true.
• token_cache (TokenCache) -- Sets the token cache used by this ClientApplication
instance. By default, an in-memory cache will be created and used.
• http_client -- (optional) Your implementation of abstract class HttpClient
<msal.oauth2cli.http.http_client> Defaults to a requests session instance. Since
MSAL 1.11.0, the default session would be configured to attempt one retry on
connection error. If you are providing your own http_client, it will be your
http_client's duty to decide whether to perform retry.
• verify -- (optional) It will be passed to the verify parameter in the underlying
requests library This does not apply if you have chosen to pass your own Http
client
• proxies -- (optional) It will be passed to the proxies parameter in the underlying
requests library This does not apply if you have chosen to pass your own Http
client
• timeout -- (optional) It will be passed to the timeout parameter in the underlying
requests library This does not apply if you have chosen to pass your own Http
client
• app_name -- (optional) You can provide your application name for Microsoft
telemetry purposes. Default value is None, means it will not be passed to
Microsoft.
• app_version -- (optional) You can provide your application version for Microsoft
telemetry purposes. Default value is None, means it will not be passed to
Microsoft.
• client_capabilities (list[str]) --
(optional) Allows configuration of one or more client capabilities, e.g. ["CP1"].
Client capability is meant to inform the Microsoft identity platform (STS) what
this client is capable for, so STS can decide to turn on certain features. For
example, if client is capable to handle claims challenge, STS may issue Continuous
Access Evaluation (CAE) access tokens to resources, knowing that when the resource
emits a claims challenge the client will be able to handle those challenges.
Implementation details: Client capability is implemented using "claims" parameter
on the wire, for now. MSAL will combine them into claims parameter which you will
later provide via one of the acquire-token request.
• azure_region (str) --
(optional) Instructs MSAL to use the Entra regional token service. This legacy
feature is only available to first-party applications. Only
acquire_token_for_client() is supported.
Supports 4 values:
1. azure_region=None - This default value means no region is configured. MSAL
will use the region defined in env var MSAL_FORCE_REGION.
2. azure_region="some_region" - meaning the specified region is used.
3. azure_region=True - meaning MSAL will try to auto-detect the region. This is
not recommended.
4. azure_region=False - meaning MSAL will use no region.
NOTE:
Region auto-discovery has been tested on VMs and on Azure Functions. It is
unreliable. Applications using this option should configure a short timeout.
For more details and for the values of the region string
see ‐
https://learn.microsoft.com/entra/msal/dotnet/resources/region-discovery-troubleshooting
New in version 1.12.0.
• exclude_scopes (list[str]) -- (optional) Historically MSAL hardcodes
offline_access scope, which would allow your app to have prolonged access to
user's data. If that is unnecessary or undesirable for your app, now you can use
this parameter to supply an exclusion list of scopes, such as exclude_scopes =
["offline_access"].
• http_cache (dict) --
MSAL has long been caching tokens in the token_cache. Recently, MSAL also
introduced a concept of http_cache, by automatically caching some finite amount of
non-token http responses, so that long-lived PublicClientApplication and
ConfidentialClientApplication would be more performant and responsive in some
situations.
This http_cache parameter accepts any dict-like object. If not provided, MSAL
will use an in-memory dict.
If your app is a command-line app (CLI), you would want to persist your http_cache
across different CLI runs. The following recipe shows a way to do so:
# Just add the following lines at the beginning of your CLI script
import sys, atexit, pickle
http_cache_filename = sys.argv[0] + ".http_cache"
try:
with open(http_cache_filename, "rb") as f:
persisted_http_cache = pickle.load(f) # Take a snapshot
except (
FileNotFoundError, # Or IOError in Python 2
pickle.UnpicklingError, # A corrupted http cache file
AttributeError, # Cache created by a different version of MSAL
):
persisted_http_cache = {} # Recover by starting afresh
atexit.register(lambda: pickle.dump(
# When exit, flush it back to the file.
# It may occasionally overwrite another process's concurrent write,
# but that is fine. Subsequent runs will reach eventual consistency.
persisted_http_cache, open(http_cache_file, "wb")))
# And then you can implement your app as you normally would
app = msal.PublicClientApplication(
"your_client_id",
...,
http_cache=persisted_http_cache, # Utilize persisted_http_cache
...,
#token_cache=..., # You may combine the old token_cache trick
# Please refer to token_cache recipe at
# https://msal-python.readthedocs.io/en/latest/#msal.SerializableTokenCache
)
app.acquire_token_interactive(["your", "scope"], ...)
Content inside http_cache are cheap to obtain. There is no need to share them
among different apps.
Content inside http_cache will contain no tokens nor Personally Identifiable
Information (PII). Encryption is unnecessary.
New in version 1.16.0.
• instance_discovery (boolean) --
Historically, MSAL would connect to a central endpoint located at
https://login.microsoftonline.com to acquire some metadata, especially when using
an unfamiliar authority. This behavior is known as Instance Discovery.
This parameter defaults to None, which enables the Instance Discovery.
If you know some authorities which you allow MSAL to operate with as-is, without
involving any Instance Discovery, the recommended pattern is:
known_authorities = frozenset([ # Treat your known authorities as const
"https://contoso.com/adfs", "https://login.azs/foo"])
...
authority = "https://contoso.com/adfs" # Assuming your app will use this
app1 = PublicClientApplication(
"client_id",
authority=authority,
# Conditionally disable Instance Discovery for known authorities
instance_discovery=authority not in known_authorities,
)
If you do not know some authorities beforehand, yet still want MSAL to accept any
authority that you will provide, you can use a False to unconditionally disable
Instance Discovery.
New in version 1.19.0.
• allow_broker (boolean) -- Deprecated. Please use enable_broker_on_windows instead.
• enable_pii_log (boolean) --
When enabled, logs may include PII (Personal Identifiable Information). This can
be useful in troubleshooting broker behaviors. The default behavior is False.
New in version 1.24.0.
• oidc_authority (str) --
Added in version 1.28.0: It is a URL that identifies an OpenID Connect (OIDC)
authority of the format https://contoso.com/tenant. MSAL will append
".well-known/openid-configuration" to the authority and retrieve the OIDC metadata
from there, to figure out the endpoints.
Note: Broker will NOT be used for OIDC authority.
acquire_token_by_auth_code_flow(auth_code_flow, auth_response, scopes=None, **kwargs)
Validate the auth response being redirected back, and obtain tokens.
It automatically provides nonce protection.
Parameters
• auth_code_flow (dict) -- The same dict returned by initiate_auth_code_flow().
• auth_response (dict) -- A dict of the query string received from auth server.
• scopes (list[str]) --
Scopes requested to access a protected API (a resource).
Most of the time, you can leave it empty.
If you requested user consent for multiple resources, here you will need to
provide a subset of what you required in initiate_auth_code_flow().
OAuth2 was designed mostly for singleton services, where tokens are always meant
for the same resource and the only changes are in the scopes. In Microsoft Entra,
tokens can be issued for multiple 3rd party resources. You can ask authorization
code for multiple resources, but when you redeem it, the token is for only one
intended recipient, called audience. So the developer need to specify a scope so
that we can restrict the token to be issued for the corresponding audience.
Returns
• A dict containing "access_token" and/or "id_token", among others, depends on what
scope was used. (See https://tools.ietf.org/html/rfc6749#section-5.1)
• A dict containing "error", optionally "error_description", "error_uri". (It is
either this or that)
• Most client-side data error would result in ValueError exception. So the usage
pattern could be without any protocol details:
def authorize(): # A controller in a web app
try:
result = msal_app.acquire_token_by_auth_code_flow(
session.get("flow", {}), request.args)
if "error" in result:
return render_template("error.html", result)
use(result) # Token(s) are available in result and cache
except ValueError: # Usually caused by CSRF
pass # Simply ignore them
return redirect(url_for("index"))
acquire_token_by_authorization_code(code, scopes, redirect_uri=None, nonce=None,
claims_challenge=None, **kwargs)
The second half of the Authorization Code Grant.
Parameters
• code -- The authorization code returned from Authorization Server.
• scopes (list[str]) --
(Required) Scopes requested to access a protected API (a resource).
If you requested user consent for multiple resources, here you will typically want
to provide a subset of what you required in AuthCode.
OAuth2 was designed mostly for singleton services, where tokens are always meant
for the same resource and the only changes are in the scopes. In Microsoft Entra,
tokens can be issued for multiple 3rd party resources. You can ask authorization
code for multiple resources, but when you redeem it, the token is for only one
intended recipient, called audience. So the developer need to specify a scope so
that we can restrict the token to be issued for the corresponding audience.
• nonce -- If you provided a nonce when calling get_authorization_request_url(),
same nonce should also be provided here, so that we'll validate it. An exception
will be raised if the nonce in id token mismatches.
• claims_challenge -- The claims_challenge parameter requests specific claims
requested by the resource provider in the form of a claims_challenge directive in
the www-authenticate header to be returned from the UserInfo Endpoint and/or in
the ID Token and/or Access Token. It is a string of a JSON object which contains
lists of claims being requested from these locations.
Returns
A dict representing the json response from Microsoft Entra:
• A successful response would contain "access_token" key,
• an error response would contain "error" and usually "error_description".
acquire_token_by_refresh_token(refresh_token, scopes, **kwargs)
Acquire token(s) based on a refresh token (RT) obtained from elsewhere.
You use this method only when you have old RTs from elsewhere, and now you want to migrate
them into MSAL. Calling this method results in new tokens automatically storing into MSAL.
You do NOT need to use this method if you are already using MSAL. MSAL maintains RT
automatically inside its token cache, and an access token can be retrieved when you call
acquire_token_silent().
Parameters
• refresh_token (str) -- The old refresh token, as a string.
• scopes (list) -- The scopes associate with this old RT. Each scope needs to be in
the Microsoft identity platform (v2) format. See Scopes not resources.
Returns
• A dict contains "error" and some other keys, when error happened.
• A dict contains no "error" key means migration was successful.
acquire_token_by_username_password(username, password, scopes, claims_challenge=None,
auth_scheme=None, **kwargs)
Gets a token for a given resource via user credentials.
See this page for constraints of Username Password Flow. ‐
https://github.com/AzureAD/microsoft-authentication-library-for-python/wiki/Username-Password-Authentication
Parameters
• username (str) -- Typically a UPN in the form of an email address.
• password (str) -- The password.
• scopes (list[str]) -- Scopes requested to access a protected API (a resource).
• claims_challenge -- The claims_challenge parameter requests specific claims
requested by the resource provider in the form of a claims_challenge directive in
the www-authenticate header to be returned from the UserInfo Endpoint and/or in
the ID Token and/or Access Token. It is a string of a JSON object which contains
lists of claims being requested from these locations.
• auth_scheme (object) --
You can provide an msal.auth_scheme.PopAuthScheme object so that MSAL will get a
Proof-of-Possession (POP) token for you.
New in version 1.26.0.
Returns
A dict representing the json response from Microsoft Entra:
• A successful response would contain "access_token" key,
• an error response would contain "error" and usually "error_description".
acquire_token_silent(scopes, account, authority=None, force_refresh=False, claims_challenge=None,
auth_scheme=None, **kwargs)
Acquire an access token for given account, without user interaction.
It has same parameters as the acquire_token_silent_with_error(). The difference is the
behavior of the return value. This method will combine the cache empty and refresh error
into one return value, None. If your app does not care about the exact token refresh error
during token cache look-up, then this method is easier and recommended.
Returns
• A dict containing no "error" key, and typically contains an "access_token" key, if
cache lookup succeeded.
• None when cache lookup does not yield a token.
acquire_token_silent_with_error(scopes, account, authority=None, force_refresh=False,
claims_challenge=None, auth_scheme=None, **kwargs)
Acquire an access token for given account, without user interaction.
It is done either by finding a valid access token from cache, or by finding a valid refresh
token from cache and then automatically use it to redeem a new access token.
This method will differentiate cache empty from token refresh error. If your app cares the
exact token refresh error during token cache look-up, then this method is suitable.
Otherwise, the other method acquire_token_silent() is recommended.
Parameters
• scopes (list[str]) -- (Required) Scopes requested to access a protected API (a
resource).
• account -- (Required) One of the account object returned by get_accounts().
Starting from MSAL Python 1.23, a None input will become a NO-OP and always return
None.
• force_refresh -- If True, it will skip Access Token look-up, and try to find a
Refresh Token to obtain a new Access Token.
• claims_challenge -- The claims_challenge parameter requests specific claims
requested by the resource provider in the form of a claims_challenge directive in
the www-authenticate header to be returned from the UserInfo Endpoint and/or in
the ID Token and/or Access Token. It is a string of a JSON object which contains
lists of claims being requested from these locations.
• auth_scheme (object) --
You can provide an msal.auth_scheme.PopAuthScheme object so that MSAL will get a
Proof-of-Possession (POP) token for you.
New in version 1.26.0.
Returns
• A dict containing no "error" key, and typically contains an "access_token" key, if
cache lookup succeeded.
• None when there is simply no token in the cache.
• A dict containing an "error" key, when token refresh failed.
get_accounts(username=None)
Get a list of accounts which previously signed in, i.e. exists in cache.
An account can later be used in acquire_token_silent() to find its tokens.
Parameters
username -- Filter accounts with this username only. Case insensitive.
Returns
A list of account objects. Each account is a dict. For now, we only document its
"username" field. Your app can choose to display those information to end user, and
allow user to choose one of his/her accounts to proceed.
get_authorization_request_url(scopes, login_hint=None, state=None, redirect_uri=None,
response_type='code', prompt=None, nonce=None, domain_hint=None, claims_challenge=None, **kwargs)
Constructs a URL for you to start a Authorization Code Grant.
Parameters
• scopes (list[str]) -- (Required) Scopes requested to access a protected API (a
resource).
• state (str) -- Recommended by OAuth2 for CSRF protection.
• login_hint (str) -- Identifier of the user. Generally a User Principal Name (UPN).
• redirect_uri (str) -- Address to return to upon receiving a response from the
authority.
• response_type (str) --
Default value is "code" for an OAuth2 Authorization Code grant.
You could use other content such as "id_token" or "token", which would trigger an
Implicit Grant, but that is not recommended.
• prompt (str) -- By default, no prompt value will be sent, not even string "none".
You will have to specify a value explicitly. Its valid values are the constants
defined in Prompt.
• nonce -- A cryptographically random value used to mitigate replay attacks. See
also OIDC specs.
• domain_hint -- Can be one of "consumers" or "organizations" or your tenant domain
"contoso.com". If included, it will skip the email-based discovery process that
user goes through on the sign-in page, leading to a slightly more streamlined user
experience. More information on possible values available in Auth Code Flow doc
and domain_hint doc.
• claims_challenge -- The claims_challenge parameter requests specific claims
requested by the resource provider in the form of a claims_challenge directive in
the www-authenticate header to be returned from the UserInfo Endpoint and/or in
the ID Token and/or Access Token. It is a string of a JSON object which contains
lists of claims being requested from these locations.
Returns
The authorization url as a string.
initiate_auth_code_flow(scopes, redirect_uri=None, state=None, prompt=None, login_hint=None,
domain_hint=None, claims_challenge=None, max_age=None, response_mode=None)
Initiate an auth code flow.
Later when the response reaches your redirect_uri, you can use
acquire_token_by_auth_code_flow() to complete the authentication/authorization.
Parameters
• scopes (list) -- It is a list of case-sensitive strings.
• redirect_uri (str) -- Optional. If not specified, server will use the
pre-registered one.
• state (str) -- An opaque value used by the client to maintain state between the
request and callback. If absent, this library will automatically generate one
internally.
• prompt (str) -- By default, no prompt value will be sent, not even string "none".
You will have to specify a value explicitly. Its valid values are the constants
defined in Prompt.
• login_hint (str) -- Optional. Identifier of the user. Generally a User Principal
Name (UPN).
• domain_hint --
Can be one of "consumers" or "organizations" or your tenant domain "contoso.com".
If included, it will skip the email-based discovery process that user goes through
on the sign-in page, leading to a slightly more streamlined user experience. More
information on possible values available in Auth Code Flow doc and domain_hint
doc.
• max_age (int) --
OPTIONAL. Maximum Authentication Age. Specifies the allowable elapsed time in
seconds since the last time the End-User was actively authenticated. If the
elapsed time is greater than this value, Microsoft identity platform will actively
re-authenticate the End-User.
MSAL Python will also automatically validate the auth_time in ID token.
New in version 1.15.
• response_mode (str) -- OPTIONAL. Specifies the method with which response
parameters should be returned. The default value is equivalent to query, which is
still secure enough in MSAL Python (because MSAL Python does not transfer tokens
via query parameter in the first place). For even better security, we recommend
using the value form_post. In "form_post" mode, response parameters will be
encoded as HTML form values that are transmitted via the HTTP POST method and
encoded in the body using the application/x-www-form-urlencoded format. Valid
values can be either "form_post" for HTTP POST to callback URI or "query" (the
default) for HTTP GET with parameters encoded in query string. More information
on possible values here
<https://openid.net/specs/oauth-v2-multiple-response-types-1_0.html#ResponseModes>
and here
<https://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html#FormPostResponseMode>
Returns
The auth code flow. It is a dict in this form:
{
"auth_uri": "https://...", // Guide user to visit this
"state": "...", // You may choose to verify it by yourself,
// or just let acquire_token_by_auth_code_flow()
// do that for you.
"...": "...", // Everything else are reserved and internal
}
The caller is expected to:
1. somehow store this content, typically inside the current session,
2. guide the end user (i.e. resource owner) to visit that auth_uri,
3. and then relay this dict and subsequent auth response to
acquire_token_by_auth_code_flow().
is_pop_supported()
Returns True if this client supports Proof-of-Possession Access Token.
remove_account(account)
Sign me out and forget me from token cache
PublicClientApplication
class msal.PublicClientApplication(client_id, client_credential=None, *, enable_broker_on_windows=None,
enable_broker_on_mac=None, **kwargs)
CONSOLE_WINDOW_HANDLE = <object object>
__init__(client_id, client_credential=None, *, enable_broker_on_windows=None,
enable_broker_on_mac=None, **kwargs)
Same as ClientApplication.__init__(), except that client_credential parameter shall remain
None.
NOTE:
You may set enable_broker_on_windows and/or enable_broker_on_mac to True.
What is a broker, and why use it?
A broker is a component installed on your device. Broker implicitly gives your device
an identity. By using a broker, your device becomes a factor that can satisfy MFA
(Multi-factor authentication). This factor would become mandatory if a tenant's admin
enables a corresponding Conditional Access (CA) policy. The broker's presence allows
Microsoft identity platform to have higher confidence that the tokens are being issued
to your device, and that is more secure.
An additional benefit of broker is, it runs as a long-lived process with your device's
OS, and maintains its own cache, so that your broker-enabled apps (even a CLI) could
automatically SSO from a previously established signed-in session.
You shall only enable broker when your app:
1. is running on supported platforms, and already registered their corresponding
redirect_uri
• ms-appx-web://Microsoft.AAD.BrokerPlugin/your_client_id if your app is expected to
run on Windows 10+
• msauth.com.msauth.unsignedapp://auth if your app is expected to run on Mac
2. installed broker dependency, e.g. pip install msal[broker]>=1.31,<2.
3. tested with acquire_token_interactive() and acquire_token_silent().
The fallback behaviors of MSAL Python's broker support
MSAL will either error out, or silently fallback to non-broker flows.
1. MSAL will ignore the enable_broker_... and bypass broker on those auth flows that are
known to be NOT supported by broker. This includes ADFS, B2C, etc.. For other
"could-use-broker" scenarios, please see below.
2. MSAL errors out when app developer opted-in to use broker but a direct dependency
"mid-tier" package is not installed. Error message guides app developer to declare
the correct dependency msal[broker]. We error out here because the error is
actionable to app developers.
3. MSAL silently "deactivates" the broker and fallback to non-broker, when opted-in,
dependency installed yet failed to initialize. We anticipate this would happen on a
device whose OS is too old or the underlying broker component is somehow unavailable.
There is not much an app developer or the end user can do here. Eventually, the
conditional access policy shall force the user to switch to a different device.
4. MSAL errors out when broker is opted in, installed, initialized, but subsequent token
request(s) failed.
Parameters
• enable_broker_on_windows (boolean) --
This setting is only effective if your app is running on Windows 10+. This
parameter defaults to None, which means MSAL will not utilize a broker.
New in MSAL Python 1.25.0.
• enable_broker_on_mac (boolean) --
This setting is only effective if your app is running on Mac. This parameter
defaults to None, which means MSAL will not utilize a broker.
New in MSAL Python 1.31.0.
acquire_token_by_device_flow(flow, claims_challenge=None, **kwargs)
Obtain token by a device flow object, with customizable polling effect.
Parameters
• flow (dict) -- A dict previously generated by initiate_device_flow(). By default,
this method's polling effect will block current thread. You can abort the
polling loop at any time, by changing the value of the flow's "expires_at" key to
0.
• claims_challenge -- The claims_challenge parameter requests specific claims
requested by the resource provider in the form of a claims_challenge directive in
the www-authenticate header to be returned from the UserInfo Endpoint and/or in
the ID Token and/or Access Token. It is a string of a JSON object which contains
lists of claims being requested from these locations.
Returns
A dict representing the json response from Microsoft Entra:
• A successful response would contain "access_token" key,
• an error response would contain "error" and usually "error_description".
acquire_token_interactive(scopes, prompt=None, login_hint=None, domain_hint=None,
claims_challenge=None, timeout=None, port=None, extra_scopes_to_consent=None, max_age=None,
parent_window_handle=None, on_before_launching_ui=None, auth_scheme=None, **kwargs)
Acquire token interactively i.e. via a local browser.
Prerequisite: In Azure Portal, configure the Redirect URI of your "Mobile and Desktop
application" as http://localhost. If you opts in to use broker during
PublicClientApplication creation, your app also need this Redirect URI:
ms-appx-web://Microsoft.AAD.BrokerPlugin/YOUR_CLIENT_ID
Parameters
• scopes (list) -- It is a list of case-sensitive strings.
• prompt (str) -- By default, no prompt value will be sent, not even string "none".
You will have to specify a value explicitly. Its valid values are the constants
defined in Prompt.
• login_hint (str) -- Optional. Identifier of the user. Generally a User Principal
Name (UPN).
• domain_hint --
Can be one of "consumers" or "organizations" or your tenant domain "contoso.com".
If included, it will skip the email-based discovery process that user goes through
on the sign-in page, leading to a slightly more streamlined user experience. More
information on possible values available in Auth Code Flow doc and domain_hint
doc.
• claims_challenge -- The claims_challenge parameter requests specific claims
requested by the resource provider in the form of a claims_challenge directive in
the www-authenticate header to be returned from the UserInfo Endpoint and/or in
the ID Token and/or Access Token. It is a string of a JSON object which contains
lists of claims being requested from these locations.
• timeout (int) -- This method will block the current thread. This parameter
specifies the timeout value in seconds. Default value None means wait
indefinitely.
• port (int) -- The port to be used to listen to an incoming auth response. By
default we will use a system-allocated port. (The rest of the redirect_uri is
hard coded as http://localhost.)
• extra_scopes_to_consent (list) -- "Extra scopes to consent" is a concept only
available in Microsoft Entra. It refers to other resources you might want to
prompt to consent for, in the same interaction, but for which you won't get back a
token for in this particular operation.
• max_age (int) --
OPTIONAL. Maximum Authentication Age. Specifies the allowable elapsed time in
seconds since the last time the End-User was actively authenticated. If the
elapsed time is greater than this value, Microsoft identity platform will actively
re-authenticate the End-User.
MSAL Python will also automatically validate the auth_time in ID token.
New in version 1.15.
• parent_window_handle (int) --
OPTIONAL.
• If your app does not opt in to use broker, you do not need to provide a
parent_window_handle here.
• If your app opts in to use broker, parent_window_handle is required.
• If your app is a GUI app running on Windows or Mac system, you are required to
also provide its window handle, so that the sign-in window will pop up on top
of your window.
• If your app is a console app running on Windows or Mac system, you can use a
placeholder PublicClientApplication.CONSOLE_WINDOW_HANDLE.
Most Python scripts are console apps.
New in version 1.20.0.
• on_before_launching_ui (function) --
A callback with the form of lambda ui="xyz", **kwargs: print("A {} will be
launched".format(ui)), where ui will be either "browser" or "broker". You can use
it to inform your end user to expect a pop-up window.
New in version 1.20.0.
• auth_scheme (object) --
You can provide an msal.auth_scheme.PopAuthScheme object so that MSAL will get a
Proof-of-Possession (POP) token for you.
New in version 1.26.0.
Returns
• A dict containing no "error" key, and typically contains an "access_token" key.
• A dict containing an "error" key, when token refresh failed.
initiate_device_flow(scopes=None, **kwargs)
Initiate a Device Flow instance, which will be used in acquire_token_by_device_flow().
Parameters
scopes (list[str]) -- Scopes requested to access a protected API (a resource).
Returns
A dict representing a newly created Device Flow object.
• A successful response would contain "user_code" key, among others
• an error response would contain some other readable key/value pairs.
ConfidentialClientApplication
class msal.ConfidentialClientApplication(client_id, client_credential=None, authority=None,
validate_authority=True, token_cache=None, http_client=None, verify=True, proxies=None, timeout=None,
client_claims=None, app_name=None, app_version=None, client_capabilities=None, azure_region=None,
exclude_scopes=None, http_cache=None, instance_discovery=None, allow_broker=None, enable_pii_log=None,
oidc_authority=None)
Same as ClientApplication.__init__(), except that allow_broker parameter shall remain None.
acquire_token_for_client(scopes, claims_challenge=None, **kwargs)
Acquires token for the current confidential client, not for an end user.
Since MSAL Python 1.23, it will automatically look for token from cache, and only send
request to Identity Provider when cache misses.
Parameters
• scopes (list[str]) -- (Required) Scopes requested to access a protected API (a
resource).
• claims_challenge -- The claims_challenge parameter requests specific claims
requested by the resource provider in the form of a claims_challenge directive in
the www-authenticate header to be returned from the UserInfo Endpoint and/or in
the ID Token and/or Access Token. It is a string of a JSON object which contains
lists of claims being requested from these locations.
Returns
A dict representing the json response from Microsoft Entra:
• A successful response would contain "access_token" key,
• an error response would contain "error" and usually "error_description".
acquire_token_on_behalf_of(user_assertion, scopes, claims_challenge=None, **kwargs)
Acquires token using on-behalf-of (OBO) flow.
The current app is a middle-tier service which was called with a token representing an end
user. The current app can use such token (a.k.a. a user assertion) to request another
token to access downstream web API, on behalf of that user. See detail docs here .
The current middle-tier app has no user interaction to obtain consent. See how to gain
consent upfront for your middle-tier app from this article. ‐
https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow#gaining-consent-for-the-middle-tier-application
Parameters
• user_assertion (str) -- The incoming token already received by this app
• scopes (list[str]) -- Scopes required by downstream API (a resource).
• claims_challenge -- The claims_challenge parameter requests specific claims
requested by the resource provider in the form of a claims_challenge directive in
the www-authenticate header to be returned from the UserInfo Endpoint and/or in
the ID Token and/or Access Token. It is a string of a JSON object which contains
lists of claims being requested from these locations.
Returns
A dict representing the json response from Microsoft Entra:
• A successful response would contain "access_token" key,
• an error response would contain "error" and usually "error_description".
remove_tokens_for_client()
Remove all tokens that were previously acquired via acquire_token_for_client() for the
current client.
TokenCache
One of the parameters accepted by both PublicClientApplication and ConfidentialClientApplication is the
TokenCache.
class msal.TokenCache
This is considered as a base class containing minimal cache behavior.
Although it maintains tokens using unified schema across all MSAL libraries, this class does not
serialize/persist them. See subclass SerializableTokenCache for details on serialization.
add(event, now=None)
Handle a token obtaining event, and add tokens into cache.
find(credential_type, target=None, query=None, *, now=None)
Equivalent to list(search(...)).
search(credential_type, target=None, query=None, *, now=None)
Returns a generator of matching entries.
It is O(1) for AT hits, and O(n) for other types. Note that it holds a lock during the
entire search.
You can subclass it to add new behavior, such as, token serialization. See SerializableTokenCache for
example.
class msal.SerializableTokenCache
This serialization can be a starting point to implement your own persistence.
This class does NOT actually persist the cache on disk/db/etc.. Depending on your need, the
following simple recipe for file-based, unencrypted persistence may be sufficient:
import os, atexit, msal
cache_filename = os.path.join( # Persist cache into this file
os.getenv(
# Automatically wipe out the cache from Linux when user's ssh session ends.
# See also https://github.com/AzureAD/microsoft-authentication-library-for-python/issues/690
"XDG_RUNTIME_DIR", ""),
"my_cache.bin")
cache = msal.SerializableTokenCache()
if os.path.exists(cache_filename):
cache.deserialize(open(cache_filename, "r").read())
atexit.register(lambda:
open(cache_filename, "w").write(cache.serialize())
# Hint: The following optional line persists only when state changed
if cache.has_state_changed else None
)
app = msal.ClientApplication(..., token_cache=cache)
...
Alternatively, you may use a more sophisticated cache persistence library, MSAL Extensions, which
provides token cache persistence with encryption, and more.
Variables
has_state_changed (bool) -- Indicates whether the cache state in the memory has changed
since last serialize() or deserialize() call.
add(event, **kwargs)
Handle a token obtaining event, and add tokens into cache.
deserialize(state: str | None) -> None
Deserialize the cache from a state previously obtained by serialize()
serialize() -> str
Serialize the current cache state into a string.
Prompt
class msal.Prompt
This class defines the constant strings for prompt parameter.
The values are based on https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest
SELECT_ACCOUNT = 'select_account'
NONE = 'none'
CONSENT = 'consent'
LOGIN = 'login'
PopAuthScheme
This is used as the auth_scheme parameter in many of the acquire token methods to support for Proof of
Possession (PoP) tokens.
New in MSAL Python 1.26
class msal.PopAuthScheme(http_method=None, url=None, nonce=None)
HTTP_GET = 'GET'
HTTP_POST = 'POST'
HTTP_PUT = 'PUT'
HTTP_DELETE = 'DELETE'
HTTP_PATCH = 'PATCH'
__init__(http_method=None, url=None, nonce=None)
Create an auth scheme which is needed to obtain a Proof-of-Possession token.
Parameters
• http_method (str) -- Its value is an uppercase http verb, such as "GET" and
"POST".
• url (str) -- The url to be signed.
• nonce (str) -- The nonce came from resource's challenge.
Exceptions
These are exceptions that MSAL Python may raise. You should not need to create them directly. You may
want to catch them to provide a better error message to your end users.
class msal.IdTokenError(reason, now, claims)
In unlikely event of an ID token is malformed, this exception will be raised.
MANAGED IDENTITY
MSAL supports Managed Identity.
You can create one of these two kinds of managed identity configuration objects:
class msal.SystemAssignedManagedIdentity
Represent a system-assigned managed identity.
It is equivalent to a Python dict of:
{"ManagedIdentityIdType": "SystemAssigned", "Id": None}
or a JSON blob of:
{"ManagedIdentityIdType": "SystemAssigned", "Id": null}
class msal.UserAssignedManagedIdentity(*, client_id=None, resource_id=None, object_id=None)
Represent a user-assigned managed identity.
Depends on the id you provided, the outcome is equivalent to one of the below:
{"ManagedIdentityIdType": "ClientId", "Id": "foo"}
{"ManagedIdentityIdType": "ResourceId", "Id": "foo"}
{"ManagedIdentityIdType": "ObjectId", "Id": "foo"}
And then feed the configuration object into a ManagedIdentityClient object.
class msal.ManagedIdentityClient(managed_identity: dict | ManagedIdentity | SystemAssignedManagedIdentity
| UserAssignedManagedIdentity, *, http_client, token_cache=None, http_cache=None)
This API encapsulates multiple managed identity back-ends: VM, App Service, Azure Automation
(Runbooks), Azure Function, Service Fabric, and Azure Arc.
It also provides token cache support.
NOTE:
Cloud Shell support is NOT implemented in this class. Since MSAL Python 1.18 in May 2022, it
has been implemented in PublicClientApplication.acquire_token_interactive() via calling pattern
PublicClientApplication(...).acquire_token_interactive(scopes=[...], prompt="none"). That is
appropriate, because Cloud Shell yields a token with delegated permissions for the end user who
has signed in to the Azure Portal (like what a PublicClientApplication does), not a token with
application permissions for an app.
__init__(managed_identity: dict | ManagedIdentity | SystemAssignedManagedIdentity |
UserAssignedManagedIdentity, *, http_client, token_cache=None, http_cache=None)
Create a managed identity client.
Parameters
• managed_identity -- It accepts an instance of SystemAssignedManagedIdentity or
UserAssignedManagedIdentity. They are equivalent to a dict with a certain shape,
which may be loaded from a JSON configuration file or an env var.
• http_client --
An http client object. For example, you can use requests.Session(), optionally
with exponential backoff behavior demonstrated in this recipe:
import msal, requests
from requests.adapters import HTTPAdapter, Retry
s = requests.Session()
retries = Retry(total=3, backoff_factor=0.1, status_forcelist=[
429, 500, 501, 502, 503, 504])
s.mount('https://', HTTPAdapter(max_retries=retries))
managed_identity = ...
client = msal.ManagedIdentityClient(managed_identity, http_client=s)
• token_cache -- Optional. It accepts a msal.TokenCache instance to store tokens.
It will use an in-memory token cache by default.
• http_cache -- Optional. It has the same characteristics as the
msal.ClientApplication.http_cache.
Recipe 1: Hard code a managed identity for your app:
import msal, requests
client = msal.ManagedIdentityClient(
msal.UserAssignedManagedIdentity(client_id="foo"),
http_client=requests.Session(),
)
token = client.acquire_token_for_client("resource")
Recipe 2: Write once, run everywhere. If you use different managed identity on different
deployment, you may use an environment variable (such as MY_MANAGED_IDENTITY_CONFIG) to
store a json blob like {"ManagedIdentityIdType": "ClientId", "Id": "foo"} or
{"ManagedIdentityIdType": "SystemAssigned", "Id": null}. The following app can load
managed identity configuration dynamically:
import json, os, msal, requests
config = os.getenv("MY_MANAGED_IDENTITY_CONFIG")
assert config, "An ENV VAR with value should exist"
client = msal.ManagedIdentityClient(
json.loads(config),
http_client=requests.Session(),
)
token = client.acquire_token_for_client("resource")
acquire_token_for_client(*, resource: str, claims_challenge: str | None = None)
Acquire token for the managed identity.
The result will be automatically cached. Subsequent calls will automatically search from
cache first.
Parameters
• resource -- The resource for which the token is acquired.
• claims_challenge --
Optional. It is a string representation of a JSON object (which contains lists of
claims being requested).
The tenant admin may choose to revoke all Managed Identity tokens, and then a
claims challenge will be returned by the target resource, as a claims_challenge
directive in the www-authenticate header, even if the app developer did not opt in
for the "CP1" client capability. Upon receiving a claims_challenge, MSAL will
skip a token cache read, and will attempt to acquire a new token.
NOTE:
Known issue: When an Azure VM has only one user-assigned managed identity, and your app
specifies to use system-assigned managed identity, Azure VM may still return a token for
your user-assigned identity.
This is a service-side behavior that cannot be changed by this library. Azure VM docs
AUTHOR
Microsoft
COPYRIGHT
2025, Microsoft
1.32.3 Apr 28, 2025 MSALPYTHON(1)