I'm implementing a custom policy (ContactSignUp.xml) in Azure AD B2C that calls a REST API (ValidateInvite
in InviteController
) when a user clicks an email link to sign up. The inviteToken
is passed as input. The API is configured via the REST-GetEmailFromInviteToken
technical profile.
However, during execution, I get the error:
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>
This could be caused by a few things. I would start with checking the following:
Network connectivity - Azure B2C requires your ServiceUrl to be publicly accessible. Test this using curl, like so:
curl -X POST https://api7267.ngrok.io/api/invite/ValidateInvite -H "Content-Type: application/json" -d '{"inviteToken":"test123"}'
If this is not working, make sure your NGrok tunnel is up and there are no IP-restrictions configured.
SSL certificate - Azure B2C requires you use a valid and trusted SSL certificate on your API. A self-signed certificate will not work. Also check SSL certificate expiry date.