Configure Password Expiration Policy in Azure AD B2C Using Organization Password Policy

Introduction:

By default, local accounts in Azure AD B2C are often configured with the DisablePasswordExpiration policy, which prevents passwords from expiring. While this behavior simplifies user experience, many organizations require periodic password rotation to align with internal security standards and compliance requirements.

One common requirement is to force users to reset their passwords every 90 days.

There are two primary approaches to implementing password expiration in Azure AD B2C:

  1. Implementing custom password expiration logic using custom policies
  2. Using the built-in organization password policy configuration

In this article, we will explore both approaches, understand the differences, and implement the recommended approach using the organization’s password policy settings with the Microsoft Graph API.

What We Are Going to Do

In this article, we will configure Azure AD B2C to:

  • Expire local account passwords after 90 days
  • Force users to reset their password once the password expires
  • Remove the DisablePasswordExpiration policy from user accounts
  • Configure the custom policy to allow password expiration
  • Use Microsoft Graph API to configure organization-level password settings

At the end of this article, your Azure AD B2C tenant will automatically enforce password expiration for local accounts.

Two Approaches for Password Expiration in Azure AD B2C

There are two ways to implement password expiration in Azure AD B2C.

Approach 1 – Implementing Custom Logic Through Custom Policies

One approach is to build the entire password expiration logic manually using Azure AD B2C custom policies.

A popular community sample is available here:

Azure AD B2C Force Password Reset After 90 Days Sample

This implementation works by:

  • Storing password reset timestamps
  • Comparing the current date and the password age
  • Triggering password reset journeys
  • Managing claims transformations and orchestration logic manually

Advantages

  • Fully customizable
  • Supports advanced business rules
  • Can implement custom warning messages
  • Supports application-specific password policies

Limitations

  • Requires significant custom policy logic
  • More complex maintenance
  • Relies on extension attributes and date calculations
  • Higher operational overhead
  • More difficult troubleshooting
  • Greater risk during future policy changes
Approach 2 – Using Organization Password Policy (Recommended)

Azure AD B2C also supports native password expiration policies through organization/domain settings.

This approach uses:

  • passwordValidityPeriodInDays
  • passwordNotificationWindowInDays

along with removing the DisablePasswordExpiration policy from user accounts.

Advantages

  • Native Microsoft-supported implementation
  • Simpler architecture
  • Easier maintenance
  • No custom date calculations
  • Centralized password policy management
  • Better long-term supportability
  • Cleaner custom policies
  • Reduced operational complexity
Why This Approach Is Recommended?

The organization’s password policy approach uses the built-in Microsoft Entra password expiration engine rather than implementing expiration logic manually.

Instead of calculating password age inside custom policies, Azure AD B2C automatically:

  • Tracks password age
  • Determines expiration
  • Forces password reset when required

This significantly reduces the complexity of custom policies, making the solution easier to manage in production environments.

For most enterprise scenarios, this is the preferred implementation approach.

Step-by-Step Implementation

Step 1 – Retrieve Existing Domain Configuration

Use the Microsoft Graph API to retrieve the current domain configuration.

Request

GET https://graph.microsoft.com/v1.0/domains/[your-domainname].onmicrosoft.com

Sample Response

{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#domains/$entity",
    "authenticationType": "Managed",
    "availabilityStatus": null,
    "id": "[your-domainname].onmicrosoft.com",
    "isAdminManaged": true,
    "isDefault": true,
    "isInitial": true,
    "isRoot": true,
    "isVerified": true,
    "supportedServices": [
        "Email",
        "OfficeCommunicationsOnline"
    ],
    "passwordValidityPeriodInDays": 90,
    "passwordNotificationWindowInDays": 15,
    "state": null
}
PropertyDescription
passwordValidityPeriodInDaysNumber of days before password expires
passwordNotificationWindowInDaysNumber of days before expiration to notify users
Step 2 – Update Domain Password Policy

Update the domain settings to enforce password expiration after 90 days.

Request

PATCH https://graph.microsoft.com/v1.0/domains/[your-domainname].onmicrosoft.com

Request Body

{
    "passwordValidityPeriodInDays": 90,
    "passwordNotificationWindowInDays": 15
}

Required Microsoft Graph Permissions

The API requires:

  • Domain.ReadWrite.All

You can perform this update using:

  • Graph Explorer
  • Postman
  • PowerShell
  • Custom automation scripts
Step 3 – Update the Azure AD B2C Custom Policy

Even after configuring the organization’s password policy, Azure AD B2C users may still have the DisablePasswordExpiration policy applied.

To allow password expiration, override the passwordPolicies claim in the Relying Party policy.

Update the Relying Party Technical Profile

Add the following configuration inside the Relying Party technical profile:

<InputClaims>
  <InputClaim ClaimTypeReferenceId=”passwordPolicies” DefaultValue=”None” />
</InputClaims>

Example:

<RelyingParty>
  <DefaultUserJourney ReferenceId="SignUpOrSignIn" />

  <TechnicalProfile Id="PolicyProfile">

    <DisplayName>PolicyProfile</DisplayName>

    <Protocol Name="OpenIdConnect" />

    <InputClaims>
      <InputClaim ClaimTypeReferenceId="passwordPolicies"
                  DefaultValue="None" />
    </InputClaims>

    <OutputClaims>
      <OutputClaim ClaimTypeReferenceId="displayName" />
      <OutputClaim ClaimTypeReferenceId="givenName" />
      <OutputClaim ClaimTypeReferenceId="surname" />
      <OutputClaim ClaimTypeReferenceId="email" />
      <OutputClaim ClaimTypeReferenceId="objectId"
                   PartnerClaimType="sub"/>
    </OutputClaims>

  </TechnicalProfile>
</RelyingParty>

The Relying Party policy injects the passwordPolicies=None value into the claims bag during policy execution.

When the downstream Azure AD write technical profile persists the passwordPolicies claim, Azure AD B2C updates the user object and removes the DisablePasswordExpiration flag.

As a result:

  • Password expiration becomes active
  • Users are forced to reset passwords after 90 days
  • Azure AD B2C handles expiration natively
Existing Users Password Policy Change Plan

Existing users who already contain: DisablePasswordExpiration

Must go through a flow that updates the user object, such as:

  • Password reset
  • Profile update
  • Sign-up/sign-in journey with persistence

Once updated, the policy changes take effect.

We can also use MS Graph API /Users to update the Password Policies for the users

Password Expired Message

Summary

In this article, we implemented password expiration in Azure AD B2C using the built-in organization password policy settings.

We compared two approaches:

  • Custom password expiration logic using custom policies
  • Native organization password policy configuration

While both approaches are valid, the organization password policy method is simpler, cleaner, and easier to maintain because it uses the built-in Microsoft Entra password expiration engine rather than implementing custom expiration calculations.

By configuring:

  • passwordValidityPeriodInDays
  • passwordNotificationWindowInDays

and removing:

  • DisablePasswordExpiration

Using user password policies, Azure AD B2C can automatically enforce password expiration and require users to reset their passwords after 90 days with minimal custom policy changes.

Categories:

Leave a Reply

Your email address will not be published. Required fields are marked *