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

Azure AD B2C自定义策略调用REST API报错:RestfulProvider加载失败

Azure AD B2C自定义策略调用REST API报错:Error loading dynamic type: Web.TPEngine.Providers.RestfulProvider

问题场景

我在Azure AD B2C中实现自定义策略ContactSignUp.xml,用户点击邮件注册链接时,策略会调用InviteController的ValidateInvite REST API,传入inviteToken作为参数,通过REST-GetEmailFromInviteToken技术配置实现。但执行时出现以下错误:

Error loading dynamic type: [Web.TPEngine.Providers.RestfulProvider]; Diagnostics=. The REST API appears unreachable from the B2C policy.

相关配置代码:

<BuildingBlocks>
  <ClaimsSchema>
    <ClaimType Id="email">
      <DisplayName>Email Address</DisplayName>
      <DataType>string</DataType>
      <DefaultPartnerClaimTypes>
        <Protocol Name="OAuth2" PartnerClaimType="email"/>
      </DefaultPartnerClaimTypes>
    </ClaimType>
    <ClaimType Id="inviteToken">
      <DisplayName>Invite Token</DisplayName>
      <DataType>string</DataType>
      <DefaultPartnerClaimTypes>
        <Protocol Name="OAuth2" PartnerClaimType="extension_inviteToken"/>
      </DefaultPartnerClaimTypes>
    </ClaimType>
    <ClaimType Id="accountName">
      <DisplayName>Account Name</DisplayName>
      <DataType>string</DataType>
    </ClaimType>
    <ClaimType Id="contactName">
      <DisplayName>Contact Name</DisplayName>
      <DataType>string</DataType>
    </ClaimType>
    <ClaimType Id="newPassword">
      <DisplayName>New Password</DisplayName>
      <DataType>string</DataType>
    </ClaimType>
    <ClaimType Id="reenterPassword">
      <DisplayName>Reenter Password</DisplayName>
      <DataType>string</DataType>
    </ClaimType>
    <ClaimType Id="objectId">
      <DisplayName>Object Id</DisplayName>
      <DataType>string</DataType>
    </ClaimType>
    <ClaimType Id="tenantId">
      <DisplayName>Tenant Id</DisplayName>
      <DataType>string</DataType>
    </ClaimType>
  </ClaimsSchema>
</BuildingBlocks>
<ClaimsProviders>
  <ClaimsProvider>
    <DisplayName>REST API</DisplayName>
    <TechnicalProfiles>
      <TechnicalProfile Id="REST-GetEmailFromInviteToken">
        <DisplayName>Get Email From Invite Token</DisplayName>
        <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.RestfulProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
        <Metadata>
          <Item Key="ServiceUrl">https://api7267.ngrok.io/api/invite/ValidateInvite</Item>
          <Item Key="SendClaimsIn">Body</Item>
          <Item Key="AuthenticationType">None</Item>
        </Metadata>
        <InputClaims>
          <InputClaim ClaimTypeReferenceId="inviteToken" Required="true"/>
        </InputClaims>
        <OutputClaims>
          <OutputClaim ClaimTypeReferenceId="email"/>
          <OutputClaim ClaimTypeReferenceId="accountName"/>
          <OutputClaim ClaimTypeReferenceId="contactName"/>
        </OutputClaims>
      </TechnicalProfile>
    </TechnicalProfiles>
  </ClaimsProvider>
  <ClaimsProvider>
    <DisplayName>Self Asserted</DisplayName>
    <TechnicalProfiles>
      <TechnicalProfile Id="SelfAsserted-LocalAccountSignUp-ReadOnlyEmail">
        <DisplayName>Local Account Sign Up (ReadOnly Email)</DisplayName>
        <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider"/>
        <Metadata>
          <Item Key="ContentDefinitionReferenceId">api.localaccountsignup</Item>
          <Item Key="ReadOnlyClaimNames">email,accountName,contactName</Item>
        </Metadata>
        <InputClaims>
          <InputClaim ClaimTypeReferenceId="email"/>
          <InputClaim ClaimTypeReferenceId="inviteToken"/>
          <InputClaim ClaimTypeReferenceId="accountName"/>
          <InputClaim ClaimTypeReferenceId="contactName"/>
        </InputClaims>
        <OutputClaims>
          <OutputClaim ClaimTypeReferenceId="email" Required="true"/>
          <OutputClaim ClaimTypeReferenceId="newPassword" Required="true"/>
          <OutputClaim ClaimTypeReferenceId="reenterPassword" Required="true"/>
          <OutputClaim ClaimTypeReferenceId="inviteToken"/>
          <OutputClaim ClaimTypeReferenceId="accountName"/>
          <OutputClaim ClaimTypeReferenceId="contactName"/>
        </OutputClaims>
      </TechnicalProfile>
    </TechnicalProfiles>
  </ClaimsProvider>
  <ClaimsProvider>
    <DisplayName>Azure Active Directory</DisplayName>
    <TechnicalProfiles>
      <TechnicalProfile Id="AAD-UserWriteUsingLogonEmail">
        <Metadata>
          <Item Key="Operation">Write</Item>
          <Item Key="RaiseErrorIfClaimsPrincipalAlreadyExists">true</Item>
        </Metadata>
        <InputClaims>
          <InputClaim ClaimTypeReferenceId="email" PartnerClaimType="signInName" Required="true"/>
          <InputClaim ClaimTypeReferenceId="newPassword" Required="true"/>
        </InputClaims>
        <PersistedClaims>
          <PersistedClaim ClaimTypeReferenceId="email" PartnerClaimType="signInName"/>
          <PersistedClaim ClaimTypeReferenceId="newPassword"/>
        </PersistedClaims>
        <OutputClaims>
          <OutputClaim ClaimTypeReferenceId="objectId"/>
          <OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="signInName"/>
        </OutputClaims>
        <IncludeTechnicalProfile ReferenceId="AAD-Common"/>
      </TechnicalProfile>
      <TechnicalProfile Id="AAD-Common">
        <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.AadBackendProvider"/>
      </TechnicalProfile>
    </TechnicalProfiles>
  </ClaimsProvider>
</ClaimsProviders>
<UserJourneys>
  <UserJourney Id="SignUpWithInviteToken">
    <OrchestrationSteps>
      <OrchestrationStep Order="1" Type="ClaimsExchange">
        <ClaimsExchanges>
          <ClaimsExchange Id="GetEmailFromInviteToken" TechnicalProfileReferenceId="REST-GetEmailFromInviteToken"/>
        </ClaimsExchanges>
      </OrchestrationStep>
      <OrchestrationStep Order="2" Type="ClaimsExchange">
        <ClaimsExchanges>
          <ClaimsExchange Id="SelfAssertedSignUp" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignUp-ReadOnlyEmail"/>
        </ClaimsExchanges>
      </OrchestrationStep>
      <OrchestrationStep Order="3" Type="ClaimsExchange">
        <ClaimsExchanges>
          <ClaimsExchange Id="CreateAADAccount" TechnicalProfileReferenceId="AAD-UserWriteUsingLogonEmail"/>
        </ClaimsExchanges>
      </OrchestrationStep>
      <OrchestrationStep Order="4" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer"/>
    </OrchestrationSteps>
  </UserJourney>
</UserJourneys>

排查与修复步骤

1. 修正REST Provider的Handler配置

当前配置中的PublicKeyToken值错误,Azure AD B2C官方RESTful Provider的正确程序集信息应为:

<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.RestfulProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />

错误的PublicKeyToken会导致B2C无法加载REST Provider组件,直接引发类型加载错误。

2. 验证API的公网可访问性

  • 确认ngrok隧道是否处于活跃状态,未过期或断开。
  • 用Postman/curl模拟B2C的请求方式:发送POST请求到API地址,Body中传入inviteToken参数,检查是否返回200状态码及预期的email、accountName、contactName数据。

3. 检查API的访问限制

  • 如果API设置了IP白名单,需将Azure AD B2C的出站IP范围加入允许列表。
  • 确认API没有防火墙或WAF规则拦截B2C的请求。

4. 确认inviteToken的传递有效性

  • 检查注册链接是否正确携带inviteToken参数。
  • 启用Azure AD B2C的Application Insights日志,查看第一步流程中inviteToken claim是否被正确获取并传递到REST API调用中。

5. 添加辅助元数据配置

在REST技术配置的Metadata中添加超时和错误处理参数,便于排查:

<Metadata>
  <Item Key="ServiceUrl">https://api7267.ngrok.io/api/invite/ValidateInvite</Item>
  <Item Key="SendClaimsIn">Body</Item>
  <Item Key="AuthenticationType">None</Item>
  <Item Key="TimeoutInSeconds">10</Item>
  <Item Key="AllowInsecureAuthInProduction">false</Item>
</Metadata>

内容的提问来源于stack exchange,提问作者Ret 2

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 21:44:50