Azure B2C Custom Reset Password Policy - azure-ad-b2c

I have a some custom policies in B2C that are working and I'm not trying to get the Reset Password to work. One of the issues I have is that I call a Restful API to check if the email address provided is a local user or if we are signing them in from a Microsoft AAD. This works fine, so the user is signed in via a Microsoft Organisation Identity if they are an SSO user, if not they are signed in locally via the B2C.
My issue is that I'm trying to do something similar with reset password. I use the following Technical Profile to get the email address
<TechnicalProfile Id="SelfAsserted-Signin-Email">
<DisplayName>Local Account Signin</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="DisplayName">Signin To Tax Systems</Item>
<Item Key="setting.operatingMode">Email</Item>
<Item Key="ContentDefinitionReferenceId">api.selfasserted</Item>
</Metadata>
<IncludeInSso>false</IncludeInSso>
<InputClaims>
<InputClaim ClaimTypeReferenceId="signInName" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="signInName" Required="true" />
</OutputClaims>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-AAD" />
</TechnicalProfile>
Once the email address is obtained, we call a rest api to check the email address. This check tells us if the user is a federated user, or a local user. If they are a federated user I want to error as they can't reset their password via B2C.
If they are a local user then we want to do the reset password. This is done via the following Technical Profile. The problem is that they have to enter their email address again, I want the email address to be pre-populated with the email address obtained previously.
<TechnicalProfile Id="LocalAccountDiscoveryUsingEmailAddress">
<DisplayName>Reset password using email address</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="IpAddressClaimReferenceId">IpAddress</Item>
<Item Key="ContentDefinitionReferenceId">api.localaccountpasswordreset</Item>
<Item Key="UserMessageIfClaimsTransformationBooleanValueIsNotEqual">Your account has been locked. Contact your support person to unlock it, then try again.</Item>
</Metadata>
<CryptographicKeys>
<Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" />
</CryptographicKeys>
<IncludeInSso>false</IncludeInSso>
<InputClaims>
<InputClaim ClaimTypeReferenceId="signInName" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="email" PartnerClaimType="Verified.Email" Required="true" />
<OutputClaim ClaimTypeReferenceId="objectId" />
<OutputClaim ClaimTypeReferenceId="userPrincipalName" />
<OutputClaim ClaimTypeReferenceId="authenticationSource" />
</OutputClaims>
<ValidationTechnicalProfiles>
<ValidationTechnicalProfile ReferenceId="AAD-UserReadUsingEmailAddress" />
</ValidationTechnicalProfiles>
</TechnicalProfile>
Any idea how I can do this? I can't seem to find much detail about api.localaccountpasswordreset in regards to the metadata etc.

Since you obtained the email in the claim signInName at step 1, in step 2, you can pre-populate it as follows:
<InputClaims>
<InputClaim ClaimTypeReferenceId="signInName" PartnerClaimType="email"/>
</InputClaims>
For the Email Verification buttons to appear, you must have the email claim as readOnly. Otherwise, AAD B2C will pre-populate the field assuming its already validated, and only show the Verify button if the email address is changed.
So a true solution would be:
<ClaimsSchema>
<!-- Sample: Read only email address to present to the user-->
<ClaimType Id="readonlyEmail">
<DisplayName>E-mail Address</DisplayName>
<DataType>string</DataType>
<UserInputType>Readonly</UserInputType>
</ClaimType>
</ClaimsSchema>
<TechnicalProfile Id="LocalAccountDiscoveryUsingEmailAddress">
<DisplayName>Reset password using email address</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="IpAddressClaimReferenceId">IpAddress</Item>
<Item Key="ContentDefinitionReferenceId">api.localaccountpasswordreset</Item>
<Item Key="UserMessageIfClaimsTransformationBooleanValueIsNotEqual">Your account has been locked. Contact your support person to unlock it, then try again.</Item>
</Metadata>
<CryptographicKeys>
<Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" />
</CryptographicKeys>
<IncludeInSso>false</IncludeInSso>
<InputClaims>
<InputClaim ClaimTypeReferenceId="signInName" PartnerClaimType="readonlyEmail"/>
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="readonlyEmail" PartnerClaimType="Verified.Email" Required="true" />
<OutputClaim ClaimTypeReferenceId="objectId" />
<OutputClaim ClaimTypeReferenceId="userPrincipalName" />
<OutputClaim ClaimTypeReferenceId="authenticationSource" />
</OutputClaims>
<ValidationTechnicalProfiles>
<ValidationTechnicalProfile ReferenceId="AAD-UserReadUsingEmailAddress" />
</ValidationTechnicalProfiles>
</TechnicalProfile>
You'd need to modify AAD-UserReadUsingEmailAddress such that its input claim is
<InputClaims>
<InputClaim ClaimTypeReferenceId="readonlyEmail" PartnerClaimType="signInNames.emailAddress" Required="true" />
</InputClaims>
I would copy the whole technical profile and give it a new Id with above modification.
And any further references to email in the joruney should be replaced with readOnlyEmail in the same way.

You need to add these:
<Metadata>
<Item Key="IncludeClaimResolvingInClaimsHandling">True</Item>
</Metadata>
<InputClaims>
<InputClaim ClaimTypeReferenceId="email" DefaultValue="{OAUTH-KV:email}" AlwaysUseDefaultValue="true"></InputClaim>
</InputClaims>
So you can set the email calling the policy authorize URL appending an email query param (&email=someemail#somedomain.com)

Did you get this working? I had a similar setup for one of my customers and fixed this issue by adding 2 validation profiles (https://learn.microsoft.com/en-us/azure/active-directory-b2c/validation-technical-profile) and changed the input claim:
Call the REST API as a Validation Technical Profile (https://learn.microsoft.com/en-us/azure/active-directory-b2c/restful-technical-profile) in your SelfAsserted-Signin-Email Technical Profile to check the Email address, display an error on the screen if the email address is not federated;
Call a ClaimsTransformation Validation Technical Profile (https://learn.microsoft.com/en-us/azure/active-directory-b2c/claims-transformation-technical-profile) that references a ClaimsTransformation to copy signInName to email (https://learn.microsoft.com/en-us/azure/active-directory-b2c/general-transformations#copyclaim);
Change the Input Claim in your LocalAccountDiscoveryUsingEmailAddress Technical Profile to email.
This provides a clean UI - an error is displayed on the first form if the user is federated and the second screen pre-populates the email field using the default claim.

Related

Azure B2C Custom Policy getting 500 Internal Server Error when trying to return alternativeSecurityIds in OutputClaims

I have a User Journey that is taking a user's email address and trying to check if the user is a federated user (as a means to obfuscate the list of all Identity Providers and directly sign a user in with the desired provider). We are calling AAD-UserReadUsingEmailAddress from a custom ValidationTechnicalProfile, and returning alternativeSecurityIds in the OutputClaims. However, when clicking "Continue", there is a 500 Internal Server Error occurring to which Application Insights and B2C Audit Logs are providing no additional information. As soon as alternativeSecurityIds, the ValidationTechnicalProfile will properly execute.
Additionally, clicking the continue button causes a 500 Internal Server Error, the ValidationTechnicalProfile still seems to execute and return some of the claims, although not the alternativeSecurityIds. Those are however included in a JWT token that is returned. Screenshots of the claims from App Insights (using the B2C plugin for VS Code) and the JWT, as well as the 500 error are included.
Per the Microsoft Documentation, alternativeSecurityIds is a valid output claim.
I have seen other posts which suggest using userIdentities (a userIdentityCollection), but this does not appear to be supported by B2C, and in fact, when trying to Persist the claim, causes a 400 error with the following message: "The provided user property value is invalid. Error returned was 400/Request_BadRequest: A value without a type name was found and no expected type is available."
Is there something missing (setup, authorization) that is required in order to properly retrieve the alternativeSecurityIds?
Below are code snippets:
<ClaimsSchema>
<ClaimType Id="alternativeSecurityIds">
<DataType>alternativeSecurityIdCollection</DataType>
<UserInputType>Readonly</UserInputType>
</ClaimType>
<ClaimType Id="identityProviders">
<DataType>stringCollection</DataType>
</ClaimType>
</ClaimsSchema>
<ContentDefinition Id="api.ssosignin">
<LoadUri>{Settings:AzureADB2CTemplateBaseUrl}sso.html</LoadUri>
<RecoveryUri>~/common/default_page_error.html</RecoveryUri>
<DataUri>urn:com:microsoft:aad:b2c:elements:contract:selfasserted:2.1.7</DataUri>
<Metadata>
<Item Key="DisplayName">SSO Sign In</Item>
</Metadata>
<LocalizedResourcesReferences MergeBehavior="Prepend">
<LocalizedResourcesReference Language="en" LocalizedResourcesReferenceId="api.ssosignin.en" />
</LocalizedResourcesReferences>
</ContentDefinition>
<TechnicalProfile Id="SelfAsserted-SsoEmailLookup">
<DisplayName>Lookup email address for SSO user</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="IpAddressClaimReferenceId">IpAddress</Item>
<Item Key="ContentDefinitionReferenceId">api.ssosignin</Item>
</Metadata>
<CryptographicKeys>
<Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenContainer" />
</CryptographicKeys>
<IncludeInSso>false</IncludeInSso>
<InputClaims>
<InputClaim ClaimTypeReferenceId="email" />
</InputClaims>
<DisplayClaims>
<DisplayClaim ClaimTypeReferenceId="email" Required="true" />
</DisplayClaims>
<OutputClaims>
<!-- Required claims -->
<OutputClaim ClaimTypeReferenceId="objectId" />
<!-- Optional claims -->
<OutputClaim ClaimTypeReferenceId="userPrincipalName" />
<OutputClaim ClaimTypeReferenceId="displayName" />
<OutputClaim ClaimTypeReferenceId="alternativeSecurityIds" />
</OutputClaims>
<ValidationTechnicalProfiles>
<ValidationTechnicalProfile ReferenceId="AAD-UserReadUsingEmailAddress-SsoUser" ContinueOnError="false" />
</ValidationTechnicalProfiles>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" />
</TechnicalProfile>
<TechnicalProfile Id="AAD-UserReadUsingEmailAddress-SsoUser">
<Metadata>
<Item Key="Operation">Read</Item>
<Item Key="RaiseErrorIfClaimsPrincipalDoesNotExist">true</Item>
<Item Key="UserMessageIfClaimsPrincipalDoesNotExist">An SSO account with that email was not found.</Item>
</Metadata>
<OutputClaims>
<!-- Required claims -->
<OutputClaim ClaimTypeReferenceId="alternativeSecurityIds" />
</OutputClaims>
<IncludeTechnicalProfile ReferenceId="AAD-UserReadUsingEmailAddress" />
</TechnicalProfile>

AAD B2C custom policy read without user interaction

Is it possible to make a read operation before any other in a TechnicalProfile? In a password reset scenario where users always login with a username, I'd like to read the email and display it right on the landing page of the user journey. Every sample I see uses a previous step in which we only display the username claim and, on the button click, in a ValidationProfile, the read occurs. So it's only in the next step that you see the email and can click to validate it. It's not optimal as it adds a useless step.
So to be clear, the policy receives the identifier (a 6 digits ID) via LoginHint and I would like to read the email from AAD (with an AzureActiveDirectoryProvider like AAD-Common profile) and show it in a Verified.Email claim right off the bat. No user interaction needed. Anyone have an idea on how could I do it?
The first step that I want to get rid of:
So that I could get right here at the start:
----------------UPDATE--------------------------
Basically, I would have to use a InputClaimsTransformations to
set the readOnlySignInName from OIDC:LoginHint
call “AAD-UserReadUsingUserNameAndGetStrongAuthenticationEmailAddress”
technical profile which uses AAD-Common
(AzureActiveDirectoryProvider) to read from AAD using the
readOnlySignInName claim.
So, I would need to “call” a “Claims transformation technical profile”. But such technical profiles seem to be available only for OutputClaimsTransformations (as specified here).
Here is the AAD-UserReadUsingUserNameAndGetStrongAuthenticationEmailAddress profile that reads from AAD to get the actual objectId and email for the LocalAccountDiscoveryUsingUserNameAndValidateStrongAuthenticationEmailAddressTest profile, which is the first step of the UserJourney :
<TechnicalProfile Id="AAD-UserReadUsingUserNameAndGetStrongAuthenticationEmailAddressTest">
<Metadata>
<Item Key="Operation">Read</Item>
<Item Key="RaiseErrorIfClaimsPrincipalDoesNotExist">true</Item>
<Item Key="IncludeClaimResolvingInClaimsHandling">true</Item>
</Metadata>
<InputClaims>
<InputClaim ClaimTypeReferenceId="readOnlySignInName" DefaultValue="{OIDC:LoginHint}" AlwaysUseDefaultValue="true" PartnerClaimType="signInNames.userName" Required="true" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="objectId" />
<OutputClaim ClaimTypeReferenceId="authenticationSource" DefaultValue="localAccountAuthentication" />
<OutputClaim ClaimTypeReferenceId="strongAuthenticationEmailAddress" />
</OutputClaims>
<IncludeTechnicalProfile ReferenceId="AAD-Common" />
</TechnicalProfile>
<TechnicalProfile Id="LocalAccountDiscoveryUsingUserNameAndValidateStrongAuthenticationEmailAddressTest">
<DisplayName>Reset password using username</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<!-- Other values maybe defined in localized api.selfasserted.fr and api.selfasserted.en -->
<Item Key="IpAddressClaimReferenceId">IpAddress</Item>
<Item Key="ContentDefinitionReferenceId">api.localaccountpasswordreset</Item>
<Item Key="AllowGenerationOfClaimsWithNullValues">true</Item>
<Item Key="UserMessageIfClaimsTransformationStringsAreNotEqual">An account could not be found for the provided User ID and email combination.</Item>
<Item Key="UserMessageIfClaimsTransformationBooleanValueIsNotEqual">Your account has been locked. Contact your support person to unlock it, then try again.</Item>
<Item Key="LocalAccountType">Username</Item>
<Item Key="LocalAccountProfile">true</Item>
<!-- Reduce the default self-asserted retry limit of 7 for the reset journey -->
<Item Key="setting.retryLimit">5</Item>
</Metadata>
<CryptographicKeys>
<Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" />
</CryptographicKeys>
<InputClaimsTransformations>
<!-- This is what I'm trying to do, read the user to get email address -->
<InputClaimsTransformation ReferenceId="AAD-UserReadUsingUserNameAndGetStrongAuthenticationEmailAddressTest" />
<!-- Copy this address to a readonly field for display. This part works fine. -->
<InputClaimsTransformation ReferenceId="CopySignInEmailAddressToEmail" />
</InputClaimsTransformations>
<InputClaims>
<InputClaim ClaimTypeReferenceId="readOnlySignInName" />
<InputClaim ClaimTypeReferenceId="emailFromAAD" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="readOnlySignInName" Required="true" />
<OutputClaim ClaimTypeReferenceId="emailFromAAD" PartnerClaimType="Verified.Email" Required="true" />
<OutputClaim ClaimTypeReferenceId="authenticationSource" />
</OutputClaims>
<OutputClaimsTransformations>
<OutputClaimsTransformation ReferenceId="CopySignInNameFromReadOnly" />
</OutputClaimsTransformations>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" />
</TechnicalProfile>

Password Reset link Azure B2C Custom Policy

I have a custom policy that is working fine. However, noticed that the Password Reset (Forgotten Password) link is not showing. How do I get this to show, as we are also working on a custom ui for the policy as well.
I'm using the self asserted method.
<ContentDefinition Id="api.selfasserted">
<LoadUri>{Settings:CustomUIBaseUrl}/selfAsserted.html</LoadUri>
<RecoveryUri>~/common/default_page_error.html</RecoveryUri>
<DataUri>urn:com:microsoft:aad:b2c:elements:contract:selfasserted:2.1.0</DataUri>
<Metadata>
<Item Key="DisplayName">Collect information from user page</Item>
</Metadata>
</ContentDefinition>
that's being referenced by this technical profile
<DisplayName>Local Account Signin</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="DisplayName">Signin</Item>
<Item Key="SignUpTarget">SignUpWithLogonEmailExchange</Item>
<Item Key="setting.operatingMode">Email</Item>
<Item Key="setting.forgotPasswordLinkLocation">AfterLabel</Item>
<Item Key="ContentDefinitionReferenceId">api.selfasserted</Item>
</Metadata>
<IncludeInSso>false</IncludeInSso>
<InputClaims>
<InputClaim ClaimTypeReferenceId="signInName" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="signInName" Required="true" />
<OutputClaim ClaimTypeReferenceId="password" Required="true" />
<OutputClaim ClaimTypeReferenceId="objectId" />
<OutputClaim ClaimTypeReferenceId="authenticationSource" />
</OutputClaims>
<ValidationTechnicalProfiles>
<ValidationTechnicalProfile ReferenceId="login-NonInteractive" />
</ValidationTechnicalProfiles>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-AAD" />
</TechnicalProfile>
Use DATAURI: urn:com:microsoft:aad:b2c:elements:contract:unifiedssp:1.2.0 to have SignIn, SignUp and ForgotPassword in a single page.
When you click on Forgot Password you will get AADB2C90118 error code.
Handle Using Custom Policy:
https://github.com/azure-ad-b2c/samples/tree/master/policies/embedded-password-reset
If Using .Net then you can refer this link to handle the error code:
https://github.com/AzureADQuickStarts/B2C-WebApp-OpenIDConnect-DotNet-SUSI

Azure B2C MFA phone factor verification retry handling in custom policy

When using the phone factor technical profile for MFA, the default behavior after 3 incorrect code entries is to redirect the user back to the specified URI with an error saying maximum retries for MFA exceeded. However, the default behavior for email MFA is to simply show an error message and give the user an option to send a new code or cancel.
Is there a way to specify the allowed number of retries for phone MFA or to specify that the phone MFA should display an error in the template without redirecting with an error code?
My phonefactor technical profile:
<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="ContentDefinitionReferenceId">api.phonefactor</Item>
<Item Key="ManualPhoneNumberEntryAllowed">true</Item>
</Metadata>
<CryptographicKeys>
<Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" />
</CryptographicKeys>
<InputClaimsTransformations>
<InputClaimsTransformation ReferenceId="CreateUserIdForMFA" />
</InputClaimsTransformations>
<InputClaims>
<InputClaim ClaimTypeReferenceId="userIdForMFA" PartnerClaimType="UserId" />
<InputClaim ClaimTypeReferenceId="strongAuthenticationPhoneNumber" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="Verified.strongAuthenticationPhoneNumber" PartnerClaimType="Verified.OfficePhone" />
<OutputClaim ClaimTypeReferenceId="newPhoneNumberEntered" PartnerClaimType="newPhoneNumberEntered" />
</OutputClaims>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-MFA" />
</TechnicalProfile>
Example error from phone MFA: https://jwt.ms/#error=server_error&error_description=AADB2C90151%3a+User+has+exceeded+the+maximum+number+for+retries+for+multi-factor+authentication.%0d%0aCorrelation+ID%3a+0815e707-54b1-4a67-913e-7682742d1c65%0d%0aTimestamp%3a+2019-11-13+14%3a13%3a39Z%0d%0a

Can you pass password claims between steps in Azure AD B2C Custom Policies?

Can you pass password claims between steps in Azure AD B2C Custom Policies?
My symptom is that after signing up using a multiple page custom policy, a user cannot sign in until they reset their password.
I am asking this as I spent many hours debugging a problem that it turns out could not be fixed. I found the answer under another question (Azure AD B2C Multi steps custom policy) that was differently worded but had similar symptoms.
I am posting here in the hope it is more easily found and helpful to others. Apologies if you think this is a duplicate.
In short, no. See Azure AD B2C Multi steps custom policy.
A password claim is "scoped" to a given step. This means the orchestration step that collects the password claim from the end user must be the same step that writes it to the User object.
I was looking for the same and have found a way to do multi step sign up. I tried several methods, including a outputclaimstransformation to store the password in another claim, but that did not work out. Because I already needed to do some input validation against an API I found a way to also copy the password to a new claim (plaintextPassword) that is not scoped to one orchestration step. This claim can be used in a later step to create the user account with the password provided by the plaintextPassword claim.
Create a self asserted technical profile that has an inputclaim (the password) and a validation technical profile. In the validation technical profile you can copy the password to a claim of type string with an inputclaimstransformation. Then add the new claim as outputclaim to the validation profile and to the technical profile. See code below for an example:
<ClaimType Id="plaintextPassword">
<DisplayName>password</DisplayName>
<DataType>string</DataType>
<UserInputType>TextBox</UserInputType>
</ClaimType>
<ClaimType Id="password">
<DisplayName>Your password</DisplayName>
<DataType>string</DataType>
<UserHelpText>Your password</UserHelpText>
<UserInputType>Password</UserInputType>
</ClaimType>
<ClaimsTransformation Id="CopyPassword" TransformationMethod="FormatStringClaim">
<InputClaims>
<InputClaim ClaimTypeReferenceId="password" TransformationClaimType="inputClaim" />
</InputClaims>
<InputParameters>
<InputParameter Id="stringFormat" DataType="string" Value="{0}" />
</InputParameters>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="plaintextPassword" TransformationClaimType="outputClaim" />
</OutputClaims>
</ClaimsTransformation>
<TechnicalProfile Id="SignUp-PasswordValidation">
<DisplayName>Email signup</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.RestfulProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="ServiceUrl">url</Item>
<Item Key="AuthenticationType">ClientCertificate</Item>
<Item Key="SendClaimsIn">Body</Item>
</Metadata>
<CryptographicKeys>
<Key Id="ClientCertificate" StorageReferenceId="B2C_1A_ClientCertificate" />
</CryptographicKeys>
<InputClaimsTransformations>
<InputClaimsTransformation ReferenceId="CopyPassword" />
</InputClaimsTransformations>
<InputClaims>
<InputClaim ClaimTypeReferenceId="claim_to_validate" PartnerClaimType="claim_to_validate" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="plaintextPassword" />
</OutputClaims>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" />
</TechnicalProfile>
<TechnicalProfile Id="SignUp">
<DisplayName>Email signup</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<Item Key="IpAddressClaimReferenceId">IpAddress</Item>
<Item Key="ContentDefinitionReferenceId">api.localaccountsignup</Item>
<Item Key="setting.retryLimit">3</Item>
</Metadata>
<CryptographicKeys>
<Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" />
</CryptographicKeys>
<InputClaims>
<InputClaim ClaimTypeReferenceId="email" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="email" Required="true" />
<OutputClaim ClaimTypeReferenceId="claim_to_validate" Required="true" />
<OutputClaim ClaimTypeReferenceId="password" Required="true" />
<OutputClaim ClaimTypeReferenceId="executed-SelfAsserted-Input" DefaultValue="true" />
<OutputClaim ClaimTypeReferenceId="plaintextPassword" />
</OutputClaims>
<ValidationTechnicalProfiles>
<ValidationTechnicalProfile ReferenceId="SignUp-Validation" />
</ValidationTechnicalProfiles>
</TechnicalProfile>
In the technical profile where you create the user in AAD add this line:
<PersistedClaim ClaimTypeReferenceId="plaintextPassword" PartnerClaimType="password"/>
I was able to solve the problem. When we have to add the user information (LocalAccountSignUpWithLogonEmail) I removed the validation that called the technical profile that is written in AAD, I changed it to a validation that calls another technical profile. This will copy our password through a ClaimsTransformation that will save our password in another InputClaim to be visible in any other step of our flow.
<ClaimType Id="plaintextPassword">
<DisplayName>password</DisplayName>
<DataType>string</DataType>
</ClaimType>
<ClaimType Id="passwordTransformation">
<DisplayName>requestSocialRestSecondCall</DisplayName>
<DataType>string</DataType>
</ClaimType>
<ValidationTechnicalProfiles>
<ValidationTechnicalProfile ReferenceId="TransformationPassword" />
</ValidationTechnicalProfiles>
<ClaimsProvider> <!-- Copy Password-->
<DisplayName>Copy Password</DisplayName>
<TechnicalProfiles>
<TechnicalProfile Id="TransformationPassword">
<DisplayName>Copy Pass</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.ClaimsTransformationProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<InputClaims>
<InputClaim ClaimTypeReferenceId="passwordTransformation" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="passwordTransformation" />
</OutputClaims>
<OutputClaimsTransformations>
<OutputClaimsTransformation ReferenceId="Generate_TranformationPassword" />
</OutputClaimsTransformations>
</TechnicalProfile>
</TechnicalProfiles>
</ClaimsProvider>
<ClaimsTransformation Id="Generate_TranformationPassword" TransformationMethod="CopyClaim">
<InputClaims>
<InputClaim ClaimTypeReferenceId="newPassword" TransformationClaimType="inputClaim" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="plaintextPassword" TransformationClaimType="outputClaim" />
</OutputClaims>
</ClaimsTransformation>
I removed the validation that called the technical profile that is written in AAD and changed it to a validation that calls another technical profile.
This will copy the password through a ClaimsTransformation that will save our password in another InputClaim to be visible in any other step of our flow.
<TechnicalProfile Id="SignUp-PasswordValidation">
<Metadata>
<Item Key="ServiceUrl">url</Item>
<Item Key="AuthenticationType">ClientCertificate</Item>
<Item Key="SendClaimsIn">Body</Item>
</Metadata>
What is the url you used?
<CryptographicKeys>
<Key Id="issuer_secret" StorageReferenceId="B2C_1A_TokenSigningKeyContainer" />
</CryptographicKeys>
What was you application to create the Secret?

Resources