-
Notifications
You must be signed in to change notification settings - Fork 202
Developing an AAD B2C app with MSAL Python
This page is currently a preview. The actual feature in MSAL Python has NOT been implemented yet.
You can use MSAL Python to sign-in users with social identities, acquire token, customize the sign-in experience, by using Azure AD B2C. AAD B2C is built around the notion of policies. In MSAL Python, specifying a policy translates to providing an authority.
- When you instantiate the client application, you need to specify the policy in authority as
https://{tenant_name}.b2clogin.com/{tenant_name}.onmicrosoft.com/{policy}
. And then every usualacquire_token_by_xyz(...)
would work with that policy. There is no API surface difference between B2C and non-B2C scenarios. - Some policies are essentially customized user experience, such as Edit Profile policy or Reset Password policy.
You create a
PublicClientApplication
with the authority containing that policy, and then call theget_authorization_request_url(...)
accordingly.
The authority to use is https://{tenant_name}.b2clogin.com/{tenant_name}.onmicrosoft.com/{policy}
where:
-
tenant_name
is the name of the Azure AD B2C tenant, such as "contoso" -
policy
the name of the policy to apply (for instance you might have "b2c_1_susi" for sign-in/sign-up).
When building the application, you need to provide, as usual, the authority, built as above
app = msal.PublicClientApplication( # Or ConfidentialClientApplication(...)
"your_client_id",
authority="https://contoso.b2clogin.com/contoso.onmicrosoft.com/b2c_1_susi",
...)
You may also use your own customized domain name, so that your authority would look like "https://contoso.com/{tenant_name}.onmicrosoft.com/{policy}". And, it would be you - not the Microsoft Identity platform - who would know such "contoso.com" is your valid domain, you will need to tell MSAL Python to skip a precaution check, by creating your MSAL app with an extra flag
msal.ClientApplication("my_client_id", authority="https://contoso.com/...", validate_authority=False)
. Don't worry. If you forget this one, MSAL Python will guide you, by emitting a meaningful exception.
Acquiring a token for an Azure AD B2C protected API, based on the policy already provided as part of the authority, are exactly the same as what you would do in non-B2C scenario.
There is no need to filter accounts by policy, if you are following a pattern of "create different msal app for different policy" (because the B2C policy is designed to behave like an isolated authority). In practice, this will NOT cause too many MSAL app instances. Because you will still typically reuse same MSAL app and its token cache for the SignIn policy, and only create new MSAL app on-the-fly when invoking EditProfile or ResetPassword policies, whose returned token (if any) would not be useful anyway.
- In your AzureAD B2C tenant, create a new user flow and select Sign in using ROPC. This will enable the ROPC policy for your tenant. See Configure the resource owner password credentials flow for more details.
- Once you create the msal instance with the authority which contains the ROPC policy,
the
acquire_token_by_username_password(...)
would work as usual. - Limitations: This only works for local accounts (where you register with B2C using an email or username). This flow does not work if federating to any of the IdPs supported by B2C (Facebook, Google, etc...).
- Normal caveats on ROPC flow still applies. Please see this wiki page.
MSAL Python token cache usage pattern starts with querying all existing accounts by
get_accounts(...)
, which supports a username
parameter as filter.
That username data is populated by a preferred_username
claim inside the ID Token.
By default, that claim is missing in many of the Azure AD B2C scenarios.
The customer impact is that when trying to display the accounts, their username field would be empty.
This may not bother you, if you are using Auth Code flow in your web app, and dealing with only one account per user.
But if you are using ROPC flow and feels you already know the end user's username,
accounts = app.get_accounts(username="john.doe@contoso.com")
would still give you an empty result,
because "john.doe@contoso.com"
won't match ""
.
The workaround is to customize your B2C policy to populate and return a preferred_username
claim,
or simply call your app.get_accounts()
without a specific username parameter.
Sample | Platform | Description |
---|---|---|
Microsoft Identity Python Web App | All platforms supporting Python | A web app showcasing how to use MSAL Python to authenticate users via Azure Active Directory B2C, and access a Web API with the resulting tokens. |