I am modifying an existing custom policy's behavior and have not yet been able to find guidance on what I a trying to do.
Backgound
I have a custom signup/signin policy with a terms & conditions page. The general workflow is:
Sign up / Sign in
Terms & conditions acceptance
Send the claims back to the web application, which signs the user in
Goal
I have been asked to modify the policy so that rather than redirecting back to the web application on sign in, it displays a custom HTML "pending verification page".
What I've done
Created and deployed the custom HTML content.
Created a ContentDefinition that points to that HTML page:
<ContentDefinition Id="api.selfasserted.pendingverification">
<LoadUri>[redacted]/pending-verification.html</LoadUri>
<RecoveryUri>~/common/default_page_error.html</RecoveryUri>
<DataUri>urn:com:microsoft:aad:b2c:elements:contract:selfasserted:1.2.0</DataUri>
<Metadata>
<Item Key="DisplayName">Pending Verification</Item>
</Metadata>
</ContentDefinition>
Created a TechnicalProfile that uses that content definition:
<TechnicalProfile Id="SelfAsserted-PendingVerification">
<DisplayName>Pending Verification</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.selfasserted.pendingverification</Item>
</Metadata>
<IncludeInSso>false</IncludeInSso>
</TechnicalProfile>
Added an OrchestrationStep that references the TechnicalProfile:
<OrchestrationStep Order="6" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="ShowPendingVerificationPage" TechnicalProfileReferenceId="SelfAsserted-PendingVerification" />
</ClaimsExchanges>
</OrchestrationStep>
Doublechecked that the order of the steps is what I'd expect and no steps are sharing the same order number in the orchestration.
Challenge
Despite these steps, the pending verification page seems to be skipped each time, and the next step (which returns the claims) appears to be executed.
Question
Is my understanding of how to create and refer to a static page above correct?
Is a technical profile with no input or output claims skipped by default?
What is the correct way to show a static HTML file in this manner without continuing on to the next step in the orchestration?
You are correct. A ClaimsExchange Orchestration Step will be skipped if there are no claims specified.
Of the examples I have seen, many people achieve this with a Claim that has a UserInputType of Readonly.
I am not aware of anything else, sans a more complicated Javascript to move content in and out.
Related
I need to develop a RESTful technical profile that is able to pass a JSON response such as:
{
"somekey.withadot": "Some value"
}
My technical profile is as follows:
<TechnicalProfile Id="SomeId">
<DisplayName>Some displayname</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.RestfulProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="SendClaimsIn">Url</Item>
<Item Key="ServiceUrl">https://someurl.com</Item>
<Item Key="AuthenticationType">Bearer</Item>
<Item Key="UseClaimAsBearerToken">identityProviderAccessToken</Item>
</Metadata>
<InputClaims>
<InputClaim ClaimTypeReferenceId="identityProviderAccessToken" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="somekey" PartnerClaimType="somekey.withadot"/>
</OutputClaims>
</TechnicalProfile>
However, Azure AD B2C tries parsing the JSON as a nested body due to their dot notation. Has anybody come up with a solution to this?
Set ResolveJsonPathsInJsonTokens metadata item to false.
https://learn.microsoft.com/en-us/azure/active-directory-b2c/restful-technical-profile#metadata
Key
Required
Description
ResolveJsonPathsInJsonTokens
No
Indicates whether the technical profile resolves JSON paths. Possible values: true, or false (default). Use this metadata to read data from a nested JSON element. In an OutputClaim, set the PartnerClaimType to the JSON path element you want to output. For example: firstName.localized, or data[0].to[0].email.
Update: I have been in contact with Azure. The engineers from the engineering team who have been investigating it did some additional testing and the conclusion was: if JSON parameter name contains a dot (example: somekey.withadot) then the claim cannot be passed regardless of whether ResoveJsonPathsInJsonTokens is set to true or false. The expectation is that the JSON property name does not contain a dot.
The team does not consider this a bug because the JSON property is not expected to contain a dot, but the team will submit this as a feature and also update the public document on ResoveJsonPathsInJsonTokens.
Update: It has been added as a feature request: https://feedback.azure.com/d365community/idea/23e6ae2b-4fdb-ec11-a81b-0022484ee92d
UPDATE
I used split email verification and sign up for my sign up process.
On the 4th page I added a button to allow changing the email address.
How to allow user to reset email validation (picture 1) when he clicks on the change email button, knowing that at this step of process, the input "email" and the button for sending code "email_ver_but_send" are not hidden but not exist when inspecting the page?
Those are my pages for signing up :
1-Validation email
2- Validate code
3- Change email
4- Create account
My questions are :
1- How to hide continue and cancel buttons in steps 1-2-3 and only display them in the 4th step of the process?
2- After checking the code (step 2), how to go directly to step 4?
Thanks for help
There is a metadata setting called setting.showCancelButton that can be added to the self asserted technical profile. This has the possible value of true for showing the button and false for not showing the button.
Here is an example
<TechnicalProfile Id="SelfAsserted-Page">
<DisplayName>Self Asserted Page</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="setting.showCancelButton">false</Item>
</Metadata>
<InputClaims>
</InputClaims>
<OutputClaims>
</OutputClaims>
</TechnicalProfile>
More information about the metadata keys for self-asserted technical profiles can be found on the Microsoft documentation website.
I followed the sample in the documentation to integrate custom email through DisplayControl on the signin and signup flow. This flow works as described.
I am also using the reset password flow. It should use the same custom email so I tried to transfer the changes from the signin/up flow to the password reset flow.
The VerificationDisplayControl is not rendered on the page!
What I changed: In TechnicalProfile LocalAccountDiscoveryUsingEmailAddress I added
<DisplayClaims>
<DisplayClaim DisplayControlReferenceId="emailVerificationControl" />
</DisplayClaims>
reusing the already present configuration.
What did I miss? Any suggestions?
Make sure you updated the content definition page contract version for that technical profile which supports display controls.
<Item Key="ContentDefinitionReferenceId">api.localaccountpasswordreset</Item>
<ContentDefinition Id="api.localaccountpasswordreset">
<LoadUri>~/tenant/templates/AzureBlue/selfAsserted.cshtml</LoadUri>
<RecoveryUri>~/common/default_page_error.html</RecoveryUri>
<DataUri>urn:com:microsoft:aad:b2c:elements:contract:selfasserted:2.0.0</DataUri>
<Metadata>
<Item Key="DisplayName">Local account change password page</Item>
</Metadata>
</ContentDefinition>
We are currently evaluating the new feature (currently public preview) to do custom e-mail verification in AAD B2C
Our initial testing with this feature was very positive. However, we fear that some of our users may not fully understand that they are receiving an e-mail and have to check their inbox. The "default" verification mechanism shows a message (key: "ver_info_msg") like this:
Verification code has been sent to your inbox. Please copy it to the input box below.
The example shows no dedicated message to the user, it only shows the new controls.
Is there a way to get a localized message to the user for this? Localization via the usual mechanisms would be great. I understand that it is probably not trivial, since the one-time-password provider can be used in a number of ways - not only for custom e-mails - but it would be great to have the ability to give the user some feedback.
Are there some more UserMessages available for this? My current workaround is to localize the description and the placeholder for the "Verification Code" field, but this is less visible for the user.
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.OneTimePasswordProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="Operation">VerifyCode</Item>
<Item Key="UserMessage.VerificationHasExpired">You have exceed the maximum time allowed.</Item>
<Item Key="UserMessage.MaxRetryAttemped">You have exceed the number of retries allowed.</Item>
<Item Key="UserMessage.InvalidCode">You have entered the wrong code.</Item>
<Item Key="UserMessage.ServerError">Cannot verify the code, please try again later.</Item>
The feature has been added in the meantime. It works just like the old verification message. Localization can be done via the string id verification_control_code_sent
If this can be done through configuration great.
I'd also accept customising the UI to hide the buttons that refer to SMS if possible.
It is possible in built-in policies (user flows) using a custom page UI which hides the SMS button.
It is possible in custom policies using metadata as follows.
The phone factor provider provides supports the following metadata:
setting.authenticationMode: Possible values: mixed, phone, or sms. The mixed value indicates both the "call" and "text" options are presented. The phone value indicates only the "call" option is presented. The sms value indicates only the "text" option is presented.
setting.autodial: Possible values: true or false. If setting.authenticationMode is set to call or sms and this is set to true, then the phone number is dialled or messaged automatically without any user interaction.
Example:
<ClaimsProvider>
<DisplayName>PhoneFactor</DisplayName>
<TechnicalProfiles>
<TechnicalProfile Id="PhoneFactor-InputOrVerify">
<DisplayName>PhoneFactor</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.PhoneFactorProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="setting.authenticationMode">phone</Item>
<Item Key="setting.autodial">true</Item>
</Metadata>
...
</TechnicalProfile>
</TechnicalProfiles>
</ClaimsProvider>