You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure B2C自定义策略:实现超时强制MFA重验证及ClaimsTransformation执行异常排查

Hey Chris, let’s break down what’s happening with your Azure B2C custom policy and why removing that technical profile fixed your issue.

First, the Core Issue: Why MFAReadStoredMFATime Was Blocking Your Claims Transformation

The root problem likely stems from a missing input claim in your MFAReadStoredMFATime technical profile that’s required for the CompareTimetoLastMFATime transformation to run correctly.

Your DateTimeComparison transformation relies on two input claims:

  • LastMFATime (stored in your session)
  • systemDateTime (Azure B2C’s built-in claim for the current timestamp)

But your MFAReadStoredMFATime technical profile only includes LastMFATime in its <InputClaims> section. Without explicitly including systemDateTime, the transformation can’t access the current time to perform the comparison. When this happens, the transformation fails silently (which explains why your logs show step 16 ran but no transformation activity), and the isLastMFATimeGreaterThanWindow claim either isn’t generated or is set to an unexpected value.

This leads directly to your MFA step being skipped: the precondition checks if isLastMFATimeGreaterThanWindow is False, and if the claim is missing or invalid, the precondition behaves as if the condition is met, skipping the MFA verification.

When you removed the MFAReadStoredMFATime technical profile, the isLastMFATimeGreaterThanWindow claim no longer exists. Azure B2C’s precondition logic treats a missing claim as failing the ClaimEquals check, so it doesn’t skip the MFA step—and presumably, your transformation runs elsewhere (like within the MFA technical profile) where systemDateTime is available.

Fixing the MFAReadStoredMFATime Technical Profile

To get the transformation working correctly without removing the technical profile, simply add the systemDateTime input claim to MFAReadStoredMFATime:

<TechnicalProfile Id="MFAReadStoredMFATime">
  <DisplayName>Fix the session username issue</DisplayName>
  <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.ClaimsTransformationProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
  <InputClaims>
    <InputClaim ClaimTypeReferenceId="LastMFATime" DefaultValue="2018-10-01T15:00:00.0000000Z" />
    <!-- Add this line to include the current time claim -->
    <InputClaim ClaimTypeReferenceId="systemDateTime" />
  </InputClaims>
  <OutputClaims>
    <OutputClaim ClaimTypeReferenceId="isLastMFATimeGreaterThanWindow" />
  </OutputClaims>
  <OutputClaimsTransformations>
    <OutputClaimsTransformation ReferenceId="CompareTimetoLastMFATime" />
  </OutputClaimsTransformations>
</TechnicalProfile>

This ensures the DateTimeComparison transformation has both timestamps it needs to calculate whether the MFA window has expired.

Quick Note on max_age for MFA

As you explored, the max_age query parameter is primarily designed to control the overall session lifetime in Azure B2C, not to enforce re-authentication specifically for MFA based on the last MFA timestamp. Your current approach of storing the last MFA time (in session or user attributes) and using a claims transformation to compare timestamps is the right way to implement your per-application MFA revalidation requirement. If you need this to persist across user sessions, consider storing LastMFATime in a user extension attribute instead of the session.

内容的提问来源于stack exchange,提问作者Chris Clark

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 13:48:12