无法获取有效输入的 ValidationTechnicalProfile

发布于 2025-01-11 10:25:52 字数 7868 浏览 0 评论 0 原文

我正在尝试在 Azure B2C 自定义策略上设置使用一次性密码 (OTP)。我有一组工作Orchestration 步骤,从 URL 中提供的声明令牌中提取电子邮件,然后将随机生成的代码邮寄到该电子邮件。我知道有“VerifyCode”和“GenerateCode”技术配置文件可用,但它们依赖于用户首先在显示字段中输入电子邮件,这是我想避免的。

我无法触发 ValidationTechnicalProfile 以便它可以对两个声明值执行 ClaimsTransformation。这些是邮寄给用户的生成的 OTP 以及从 TechnicalProvider 收集的输入,该技术使用 SelfAssertedAttributeProvider 来显示带有 ContentDefinition 的输入字段。

我的代码基于这篇文章还有关于ValidationTechnicalProfiles

请有人解释为什么 ValidationTechnicalProfile 似乎被跳过或未能 工作?

声明

<ClaimType Id="Otp">
  <DisplayName>One-time password</DisplayName>
  <DataType>string</DataType>
</ClaimType>
<ClaimType Id="VerificationCode">
  <DisplayName>Secondary Verification Code</DisplayName>
  <DataType>string</DataType>
  <UserHelpText>Enter your verification code</UserHelpText>
  <UserInputType>TextBox</UserInputType>
</ClaimType>

编排步骤

<OrchestrationStep Order="4" Type="ClaimsExchange">
   <ClaimsExchanges>
      <ClaimsExchange Id="SelfAsserted-OTP-Exchange" TechnicalProfileReferenceId="SelfAsserted-EnterOTP" />
   </ClaimsExchanges>
</OrchestrationStep>

技术简介

使用 api.page.codeinput 内容定义来收集 VerificationCode 声明的值在输入框中。收集后,它应该将 Self-AssertedOTPCompare TechnicalProfile 作为 ValidationTechnicalProfile 触发

<TechnicalProfile Id="SelfAsserted-EnterOTP">
 <DisplayName>Enter OTP</DisplayName>
 <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
 <Metadata>
   <Item Key="ContentDefinitionReferenceId">api.page.codeinput</Item>
   <Item Key="UserMessageIfClaimsTransformationStringsAreNotEqual">Invalid OTP Code</Item>
 </Metadata>
 <OutputClaims>
   <OutputClaim ClaimTypeReferenceId="VerificationCode" Required="true" />
 </OutputClaims>
 <ValidationTechnicalProfiles>
    <ValidationTechnicalProfile ReferenceId="Self-AssertedOTPCompare" />
 </ValidationTechnicalProfiles>
</TechnicalProfile>

Validation Technical Profile

执行 AssertSuppliedAndGenerateOTPAreEqual ClaimsTransformation

<TechnicalProfile Id="Self-AssertedOTPCompare">
  <DisplayName>Returns the result from comparing the generated OTP with the supplied on</DisplayName>
  <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.ClaimsTransformationProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
  <OutputClaims>
    <OutputClaim ClaimTypeReferenceId="VerificationCode" />
  </OutputClaims>
  <OutputClaimsTransformations>
    <OutputClaimsTransformation ReferenceId="AssertSuppliedAndGeneratedOTPAreEqual" />
  </OutputClaimsTransformations>
</TechnicalProfile>

Claims Transformation

应该比较两个声明并提出一个如果代码不同,则异常以阻止用户继续。

<ClaimsTransformation Id="AssertSuppliedAndGeneratedOTPAreEqual" TransformationMethod="AssertStringClaimsAreEqual">
  <InputClaims>
    <InputClaim ClaimTypeReferenceId="Otp" TransformationClaimType="inputClaim1" />
    <InputClaim ClaimTypeReferenceId="VerificationCode" TransformationClaimType="inputClaim2" />
  </InputClaims>
  <InputParameters>
    <InputParameter Id="stringComparison" DataType="string" Value="ordinalIgnoreCase" />
  </InputParameters>
</ClaimsTransformation>

使用 AppInsights 进行日志记录 我认为它已经达到了技术要求,但控制权似乎又回到了编排上。如果我从 SelfAsserted-EnterOTP 技术配置文件中删除 ValidationTechnicalProfiles 部分,流程将停止在用户输入代码的页面上。

 {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true,
      "RecorderRecord": {
        "Values": [
          {
            "Key": "InitiatingClaimsExchange",
            "Value": {
              "ProtocolType": "Identity Experience Engine API",
              "TargetEntity": "Generate-OTP",
              "TechnicalProfileId": "SelfAsserted-EnterOTP",
              "ProtocolProviderType": "SelfAssertedAttributeProvider"
            }
          }
        ]
      },
      "PredicateResult": "True"
    }
  }, 
  {
    "Kind": "Action",
    "Content": "Web.TPEngine.StateMachineHandlers.SwitchToApiOrchestrationHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true
    }
  },
  {
    "Kind": "Transition",
    "Content": {
      "EventName": "SELFASSERTED",
      "StateName": "AwaitingNextStep"
    }
  },

其他

上面的原始实现导致进程永远不会显示从用户收集 OTP 的输入字段 - jas-suri-msft 表明这是因为 ValidationTechnicalProvider 不会引发异常。

如果是这种情况,文档似乎是错误的:

AssertStringClaimsAreEqual 声明转换始终是 从由调用的验证技术配置文件执行 自称的技术配置文件,或 DisplayControl。这 UserMessageIfClaimsTransformationStringsAreNotEqual 的元数据 自断言的技术配置文件控制错误消息 呈现给用户。

我尝试按照建议将 ValidationTechnicalProfiles 更改为 OutputClaimsTransformations 节点。

我将其替换

 <ValidationTechnicalProfiles>
    <ValidationTechnicalProfile ReferenceId="Self-AssertedOTPCompare" />
 </ValidationTechnicalProfiles>

为:

<OutputClaimsTransformations>
  <OutputClaimsTransformation 
 ReferenceId="AssertSuppliedAndGeneratedOTPAreEqual" />
</OutputClaimsTransformations>

这会导致显示 OTP 收集屏幕,但如果代码错误并且不再继续,则页面不会显示错误消息。尽管在元数据中设置了UserMessageIfClaimsTransformationStringsAreNotEqual,但是输入正确的代码可以让步骤继续进行。

那么如何让页面显示异常信息呢?

解决方案

正如评论中提到的,我无法从 ValidationTechnicalProfile 中删除 OutputClaims,因为该策略不会验证。但是,将 OutputClaim 更改为 DisplayClaim 可以解决该问题。

<TechnicalProfile Id="SelfAsserted-EnterOTP">
  <DisplayName>Enter OTP</DisplayName>
  <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
  <Metadata>
    <Item Key="ContentDefinitionReferenceId">api.page.codeinput</Item>
    <Item Key="UserMessageIfClaimsTransformationStringsAreNotEqual">Invalid OTP Code</Item>
  </Metadata>
  <DisplayClaims>
    <DisplayClaim ClaimTypeReferenceId="suppliedOTP" Required="true" />
  </DisplayClaims>
  <ValidationTechnicalProfiles>
    <ValidationTechnicalProfile ReferenceId="Self-AssertedOTPCompare" />
  </ValidationTechnicalProfiles>
</TechnicalProfile>

I am trying to setup the use of a one time pass code (OTP) on an Azure B2C Custom Policy. I have a working set of Orchestration steps that extract an email from a claims token supplied in the URL and then mail a randomly generated code to that email. I know there are "VerifyCode" and "GenerateCode" technical profiles available, but they rely on the user entering the email into a display field first, which I want to avoid.

I am unable get a ValidationTechnicalProfile to fire so that it can execute a ClaimsTransformation to the two claims values. These are the generated OTP mailed to the user and the input collected from a TechnicalProvider that uses a SelfAssertedAttributeProvider to display the input field with a ContentDefinition.

I am basing my code on this article and also a walkthrough with regard to ValidationTechnicalProfiles

Please could someone explain why the ValidationTechnicalProfile appears to either be skipped or is failing to work?

Claims

<ClaimType Id="Otp">
  <DisplayName>One-time password</DisplayName>
  <DataType>string</DataType>
</ClaimType>
<ClaimType Id="VerificationCode">
  <DisplayName>Secondary Verification Code</DisplayName>
  <DataType>string</DataType>
  <UserHelpText>Enter your verification code</UserHelpText>
  <UserInputType>TextBox</UserInputType>
</ClaimType>

Orchestration Step

<OrchestrationStep Order="4" Type="ClaimsExchange">
   <ClaimsExchanges>
      <ClaimsExchange Id="SelfAsserted-OTP-Exchange" TechnicalProfileReferenceId="SelfAsserted-EnterOTP" />
   </ClaimsExchanges>
</OrchestrationStep>

Technical Profile

Uses the api.page.codeinput content definition to collect the value of the VerificationCode claim in an input box. Once collected, it should fire the Self-AssertedOTPCompare TechnicalProfile as a ValidationTechnicalProfile

<TechnicalProfile Id="SelfAsserted-EnterOTP">
 <DisplayName>Enter OTP</DisplayName>
 <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
 <Metadata>
   <Item Key="ContentDefinitionReferenceId">api.page.codeinput</Item>
   <Item Key="UserMessageIfClaimsTransformationStringsAreNotEqual">Invalid OTP Code</Item>
 </Metadata>
 <OutputClaims>
   <OutputClaim ClaimTypeReferenceId="VerificationCode" Required="true" />
 </OutputClaims>
 <ValidationTechnicalProfiles>
    <ValidationTechnicalProfile ReferenceId="Self-AssertedOTPCompare" />
 </ValidationTechnicalProfiles>
</TechnicalProfile>

Validation Technical Profile

Executes the AssertSuppliedAndGeneratedOTPAreEqual ClaimsTransformation

<TechnicalProfile Id="Self-AssertedOTPCompare">
  <DisplayName>Returns the result from comparing the generated OTP with the supplied on</DisplayName>
  <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.ClaimsTransformationProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
  <OutputClaims>
    <OutputClaim ClaimTypeReferenceId="VerificationCode" />
  </OutputClaims>
  <OutputClaimsTransformations>
    <OutputClaimsTransformation ReferenceId="AssertSuppliedAndGeneratedOTPAreEqual" />
  </OutputClaimsTransformations>
</TechnicalProfile>

Claims Transformation

Should compare the two claims and raise an exception to prevent the user continuing if the codes are different.

<ClaimsTransformation Id="AssertSuppliedAndGeneratedOTPAreEqual" TransformationMethod="AssertStringClaimsAreEqual">
  <InputClaims>
    <InputClaim ClaimTypeReferenceId="Otp" TransformationClaimType="inputClaim1" />
    <InputClaim ClaimTypeReferenceId="VerificationCode" TransformationClaimType="inputClaim2" />
  </InputClaims>
  <InputParameters>
    <InputParameter Id="stringComparison" DataType="string" Value="ordinalIgnoreCase" />
  </InputParameters>
</ClaimsTransformation>

Logging with AppInsights I think it's hitting the technical profile but control appears to be returning to the orchestration. If I remove the ValidationTechnicalProfiles section from the SelfAsserted-EnterOTP technical profile, the flow stops at the page where the user would enter their code.

 {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true,
      "RecorderRecord": {
        "Values": [
          {
            "Key": "InitiatingClaimsExchange",
            "Value": {
              "ProtocolType": "Identity Experience Engine API",
              "TargetEntity": "Generate-OTP",
              "TechnicalProfileId": "SelfAsserted-EnterOTP",
              "ProtocolProviderType": "SelfAssertedAttributeProvider"
            }
          }
        ]
      },
      "PredicateResult": "True"
    }
  }, 
  {
    "Kind": "Action",
    "Content": "Web.TPEngine.StateMachineHandlers.SwitchToApiOrchestrationHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true
    }
  },
  {
    "Kind": "Transition",
    "Content": {
      "EventName": "SELFASSERTED",
      "StateName": "AwaitingNextStep"
    }
  },

Additional

The original implementation above caused the process to never show the input field to collect the OTP from the user - jas-suri-msft suggests this is because a ValidationTechnicalProvider does not bubble up exceptions.

If this is the case, the documentation appears to be wrong:

The AssertStringClaimsAreEqual claims transformation is always
executed from a validation technical profile that is called by a
self-asserted technical profile, or a DisplayControl. The
UserMessageIfClaimsTransformationStringsAreNotEqual metadata of a
self-asserted technical profile controls the error message that is
presented to the user.

I have tried changing the ValidationTechnicalProfiles to a OutputClaimsTransformations node as suggested.

I replaced this:

 <ValidationTechnicalProfiles>
    <ValidationTechnicalProfile ReferenceId="Self-AssertedOTPCompare" />
 </ValidationTechnicalProfiles>

with this:

<OutputClaimsTransformations>
  <OutputClaimsTransformation 
 ReferenceId="AssertSuppliedAndGeneratedOTPAreEqual" />
</OutputClaimsTransformations>

This caused the OTP collection screen to show but the page to show no error message if the code was wrong and go no further. This is despite setting UserMessageIfClaimsTransformationStringsAreNotEqual in the metadata However, entering the correct code allowed the steps to progress.

So how to do I get the page to show the exception message?

SOLUTION

As mentioned in the comments, I am unable to remove the OutputClaims from the ValidationTechnicalProfile as the policy will not validate. However, changing the OutputClaim to a DisplayClaim resolves the issue.

<TechnicalProfile Id="SelfAsserted-EnterOTP">
  <DisplayName>Enter OTP</DisplayName>
  <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
  <Metadata>
    <Item Key="ContentDefinitionReferenceId">api.page.codeinput</Item>
    <Item Key="UserMessageIfClaimsTransformationStringsAreNotEqual">Invalid OTP Code</Item>
  </Metadata>
  <DisplayClaims>
    <DisplayClaim ClaimTypeReferenceId="suppliedOTP" Required="true" />
  </DisplayClaims>
  <ValidationTechnicalProfiles>
    <ValidationTechnicalProfile ReferenceId="Self-AssertedOTPCompare" />
  </ValidationTechnicalProfiles>
</TechnicalProfile>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

作妖 2025-01-18 10:25:52

当您从验证技术配置文件部分调用声明转换技术配置文件时,错误不会像直接作为 OutputClaimsTransformation 调用时那样出现。因此,我怀疑您的观察结果是,输入的任何代码都可以工作并继续进行旅程的下一步。

相反,直接从 SelfAsserted-EnterOTP 调用 AssertSuppliedAndGenerateOTPAreEqual 作为 OutputClaimsTransformation

When you call a claims transformation technical profile from the validation technical profile section, the error is not bubbled up like when called directly as an OutputClaimsTransformation. So i suspect your observation is that, any code entered works and proceeds to the next step in the journey.

Instead, call AssertSuppliedAndGeneratedOTPAreEqual as an OutputClaimsTransformation directly from SelfAsserted-EnterOTP.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文