Azure AD B2C Custom SignIn Policy Displays SignUpSignIn - azure

I have a custom SignIn policy, because I need to fetch something from an application database (via REST API) during the sign in process.
So I have this user journey
<UserJourney Id="SignIn">
<OrchestrationSteps>
<OrchestrationStep Order="1" Type="CombinedSignInAndSignUp" ContentDefinitionReferenceId="api.localaccountsignin">
<ClaimsProviderSelections>
<ClaimsProviderSelection ValidationClaimsExchangeId="LocalAccountSigninEmailExchange" />
</ClaimsProviderSelections>
<ClaimsExchanges>
<ClaimsExchange Id="LocalAccountSigninEmailExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Email" />
</ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="2" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="AADUserReadWithObjectId" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" />
</ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="3" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="GetCustomDbObj" TechnicalProfileReferenceId="GetCustomDbObj" />
</ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="4" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />
</OrchestrationSteps>
<ClientDefinition ReferenceId="DefaultWeb" />
</UserJourney>
You can see that in step #3, I have a reference to a custom technical profile that fetches some data from a custom REST API.
In the first step, I display (supposedly) the sign in page, it references api.localaccountsignin
<ContentDefinition Id="api.localaccountsignin">
<LoadUri>https://mytenant.b2clogin.com/static/tenant/default/signin.cshtml</LoadUri>
<RecoveryUri>https://mytenant.b2clogin.com/static/tenant/default/signin.cshtml</RecoveryUri>
<DataUri>urn:com:microsoft:aad:b2c:elements:contract:unifiedssp:1.0.0</DataUri>
<Metadata>
<Item Key="TemplateId">azureBlue</Item>
</Metadata>
</ContentDefinition>
The problem is that when I use the policy, I see a page that resembles the signup+signin unified policy
Instead of just the sign in policy, which is what I desire.
I suspect that it has something to do with
<OrchestrationStep Order="1" Type="CombinedSignInAndSignUp" ContentDefinitionReferenceId="api.localaccountsignin">
More specifically, CombinedSignInAndSignUp
But I don't know what to put instead. I tried using ClaimsExchange but it didn't work.
Is there a solution?

As per this:
You can achieve this by setting SignUp to “False”.
<Item Key=”setting.showSignupLink”>False</Item>

Related

What does a PasswordChange with TOTP for Azure B2C look like?

I have an existing Azure B2C solution using custom policies and provides sign up / sign in via AAD, MS Account, Google and Local. I'm now adding TOTP MFA as provided by https://learn.microsoft.com/en-us/azure/active-directory-b2c/multi-factor-authentication?pivots=b2c-custom-policy.
I have SignUp/SignIn and Password Reset policies using TOTP working for the Local Account. I don't need TOTP for the social accounts. However, I'm struggling with a ChangePassword policy, where a user who is already logged in can change their password. For this step, I would like the user to verify themselves via TOTP before getting to change the password.
In my non-TOTP solution, I'm using the PasswordChange UserJourney as provided by https://learn.microsoft.com/en-us/azure/active-directory-b2c/add-password-change-policy?pivots=b2c-custom-policy
For completeness, it looks like this:
<UserJourney Id="PasswordChange">
<OrchestrationSteps>
<OrchestrationStep Order="1" Type="ClaimsProviderSelection" ContentDefinitionReferenceId="api.signuporsignin">
<ClaimsProviderSelections>
<ClaimsProviderSelection TargetClaimsExchangeId="LocalAccountSigninEmailExchange" />
</ClaimsProviderSelections>
</OrchestrationStep>
<OrchestrationStep Order="2" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="LocalAccountSigninEmailExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Email" />
</ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="3" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="NewCredentials" TechnicalProfileReferenceId="LocalAccountWritePasswordChangeUsingObjectId" />
</ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="4" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="AADUserReadWithObjectId" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" />
</ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="5" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />
</OrchestrationSteps>
<ClientDefinition ReferenceId="DefaultWeb" />
</UserJourney>
I was hoping to get away with something similar for PasswordChangeWithTOTP, by inserting the TotpFactor-Input and TotpFactor-Verify steps between steps 2 and 3 of the old policy.
<UserJourney Id="PasswordChangeWithTOTP">
<OrchestrationSteps>
<OrchestrationStep Order="1" Type="ClaimsProviderSelection" ContentDefinitionReferenceId="api.signuporsignin">
<ClaimsProviderSelections>
<ClaimsProviderSelection TargetClaimsExchangeId="LocalAccountSigninEmailExchange" />
</ClaimsProviderSelections>
</OrchestrationStep>
<OrchestrationStep Order="2" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="LocalAccountSigninEmailExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Email" />
</ClaimsExchanges>
</OrchestrationStep>
<!-- Call the TOTP enrollment ub journey. If user already enrolled the sub journey will not ask the user to enroll -->
<OrchestrationStep Order="3" Type="InvokeSubJourney">
<JourneyList>
<Candidate SubJourneyReferenceId="TotpFactor-Input" />
</JourneyList>
</OrchestrationStep>
<!-- Call the TOTP validation sub journey-->
<OrchestrationStep Order="4" Type="InvokeSubJourney">
<JourneyList>
<Candidate SubJourneyReferenceId="TotpFactor-Verify" />
</JourneyList>
</OrchestrationStep>
<OrchestrationStep Order="5" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="NewCredentials" TechnicalProfileReferenceId="LocalAccountWritePasswordChangeUsingObjectId" />
</ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="6" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="AADUserReadWithObjectId" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" />
</ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="7" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />
</OrchestrationSteps>
<ClientDefinition ReferenceId="DefaultWeb" />
</UserJourney>
minor talking points: I went with a new policy due to the release cycle of the application using it, and I'm not totally sold that I should offer TOTP registration as a part of this particular step, even though it's something we do for SignUpSignIn and PasswordReset.
The error that I get "The service received a bad request" when performing the "Get available strong authentication devices" activity. The error message has a target type User and Id consistent with similar operations used during sign in. I can't see anything else particularly jumping out at me.
I did try inserting a <ClaimsExchange Id="AADUserReadWithObjectId" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" /> OrchestrationStep before the TotpFactor-Input step, but thought that may have been defeating the purpose of TOTP. I also didn't get prompted to provide a verification code before getting to change the password.
What should a PasswordChange with TOTP policy look like?
Do you have:
<OutputClaim ClaimTypeReferenceId="userPrincipalName" />
as an output claim from SelfAsserted-LocalAccountSignin-Email?
As far as I remember from docs/samples - userPrincipalName is required for TOTP SubJourneys to work.

Registration only site with custom policy

I have a task to create registration only custom policy. So I need a page to pick local account or different social provider. And after the user will be navigate to the proper registration site. I can manage this by standard policies, but I have to do this job with custom policies. Are there any was to do such think with custom policies? I didn't find any registration only reference in the starter pack....
rgds,
'child
This is covered here.
You can have as many IDP as you want.
The first step of the user journey will then have as many ClaimsProviderSelections as you require. This example is for adding Azure AD.
<ClaimsProviderSelections>
...
<ClaimsProviderSelection TargetClaimsExchangeId="AzureADContosoExchange" />
</ClaimsProviderSelections>
Update
Also, look in the B2C starter pack.
<UserJourney Id="SignUpOrSignIn">
<OrchestrationSteps>
<OrchestrationStep Order="1" Type="CombinedSignInAndSignUp" ContentDefinitionReferenceId="api.signuporsignin">
<ClaimsProviderSelections>
<ClaimsProviderSelection TargetClaimsExchangeId="FacebookExchange" />
<ClaimsProviderSelection ValidationClaimsExchangeId="LocalAccountSigninEmailExchange" />
</ClaimsProviderSelections>
<ClaimsExchanges>
<ClaimsExchange Id="LocalAccountSigninEmailExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Email" />
</ClaimsExchanges>
</OrchestrationStep>
<!-- Check if the user has selected to sign in using one of the social providers -->
<OrchestrationStep Order="2" Type="ClaimsExchange">
<Preconditions>
<Precondition Type="ClaimsExist" ExecuteActionsIf="true">
<Value>objectId</Value>
<Action>SkipThisOrchestrationStep</Action>
</Precondition>
</Preconditions>
<ClaimsExchanges>
<ClaimsExchange Id="FacebookExchange" TechnicalProfileReferenceId="Facebook-OAUTH" />
<ClaimsExchange Id="SignUpWithLogonEmailExchange" TechnicalProfileReferenceId="LocalAccountSignUpWithLogonEmail" />
</ClaimsExchanges>
</OrchestrationStep>
You'll see there are two "ClaimsProviderSelection", one for local accounts and one for Facebook.

Custom policy add overlay message

I am using a custom policy for password change. I am following the custom policy mentioned here
https://learn.microsoft.com/en-us/azure/active-directory-b2c/add-password-change-policy?pivots=b2c-custom-policy
Is there any way to add an orchestration step that displays overlay message that password has been changed before SendClaims step.
The User Journey as mentioned in the link:
<UserJourney Id="PasswordChange">
<OrchestrationSteps>
<OrchestrationStep Order="1" Type="ClaimsProviderSelection" ContentDefinitionReferenceId="api.signuporsignin">
<ClaimsProviderSelections>
<ClaimsProviderSelection TargetClaimsExchangeId="LocalAccountSigninEmailExchange" />
</ClaimsProviderSelections>
</OrchestrationStep>
<OrchestrationStep Order="2" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="LocalAccountSigninEmailExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Email" />
</ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="3" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="NewCredentials" TechnicalProfileReferenceId="LocalAccountWritePasswordChangeUsingObjectId" />
</ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="4" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="AADUserReadWithObjectId" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" />
</ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="5" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />
</OrchestrationSteps>
<ClientDefinition ReferenceId="DefaultWeb" />
</UserJourney>
Between step 4 and step 5, add an orchestration step to call a selfAsserted technical profile.
Demonstrated here:
Add a step (you can remove the preconditions node)
https://github.com/azure-ad-b2c/samples/blob/master/policies/invite/policy/SignUpInvitation.xml#L165
SelfAsserted technical profile with a message
https://github.com/azure-ad-b2c/samples/blob/master/policies/invite/policy/SignUpInvitation.xml#L110
You must have one output claim in the selfAsserted technical profile. Here a claim transform is used to generate a string to display to the user.
All options available to a self asserted page
https://learn.microsoft.com/en-us/azure/active-directory-b2c/self-asserted-technical-profile
Apply custom html to the page to deliver the message/branding
https://learn.microsoft.com/en-us/azure/active-directory-b2c/customize-ui-with-html?pivots=b2c-custom-policy

Azure AD B2C Custom Policy with Sign Up Page Only

I want to create a custom policy in Azure AD B2C. I can't find such an example in the starterpack.
I checked this post Azure AD B2C Link to Sign Up Page (Not Sign In) and, if I understand it correctly, there is no URL I can use for an existing custom signup_signin policy to end up directly in the Sign Up page. Creating "Sign up v2" flow works, but I need a custom one, and copying code from the build in one and placing it to the LocalAccounts example from the starterpack doesn't work.
This is the UserJourney code downloaded from "Sign up v2" flow
<UserJourney Id="B2CSignUp_V2">
<OrchestrationSteps>
<OrchestrationStep Order="1" Type="ClaimsProviderSelection" ContentDefinitionReferenceId="api.idpselections.signup">
<ClaimsProviderSelections>
<ClaimsProviderSelection TargetClaimsExchangeId="SignUpWithLogonEmailExchange" />
</ClaimsProviderSelections>
</OrchestrationStep>
</OrchestrationSteps>
</UserJourney>
I tried to replace the OrchestrationStep 1 and 2 from the starter pack with the one here but it doesn't work.
In your Custom policies, In the B2C_1A_TrustFrameworkBase.xml file replace the 1st Orchestration Step for the User Journey Id="SignUpOrSignIn" with the following Orchestration Step and you will be directly landed to Signup page -
<OrchestrationStep Order="1" Type="ClaimsProviderSelection" ContentDefinitionReferenceId="api.idpselections.signup">
<ClaimsProviderSelections>
<ClaimsProviderSelection TargetClaimsExchangeId="SignUpWithLogonEmailExchange" />
</ClaimsProviderSelections>
</OrchestrationStep>
Alternatively, you can:
Remove orchestration step 1
Remove the objectId precondition from orchestration step 2
Renumber the following orchestration steps
Such as:
<OrchestrationStep Order="1" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="SignUpWithLogonEmailExchange" TechnicalProfileReferenceId="LocalAccountSignUpWithLogonEmail" />
</ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="2" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="AADUserReadWithObjectId" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" />
</ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="3" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />

AAD B2C UI Customization - MS content not appearing

I'm trying to use AAD B2C Page UI customization along with Custom Policies as described here: https://learn.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-ui-customization-custom. I can get my content to appear, but the standard B2C content does not seem to be merged in as expected.
I have this userjourney in my Extensions.xml file:
<UserJourney Id="SignInB2CLocal">
<OrchestrationSteps>
<OrchestrationStep Order="1" Type="CombinedSignInAndSignUp" ContentDefinitionReferenceId="api.signuporsignin">
<ClaimsProviderSelections>
<ClaimsProviderSelection ValidationClaimsExchangeId="LocalAccountSigninEmailExchange" />
</ClaimsProviderSelections>
<ClaimsExchanges>
<ClaimsExchange Id="LocalAccountSigninEmailExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Email" />
</ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="2" Type="ClaimsExchange">
<Preconditions>
<Precondition Type="ClaimsExist" ExecuteActionsIf="true">
<Value>objectId</Value>
<Action>SkipThisOrchestrationStep</Action>
</Precondition>
</Preconditions>
<ClaimsExchanges>
<ClaimsExchange Id="SignUpWithLogonEmailExchange" TechnicalProfileReferenceId="LocalAccountSignUpWithLogonEmail" />
</ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="3" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="AADUserReadWithObjectId" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" />
</ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="4" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />
</OrchestrationSteps>
</UserJourney>
and I have this ContentDefinition, also in my Extensions.xml file:
<BuildingBlocks>
<ContentDefinitions>
<ContentDefinition Id="api.signuporsignin">
<LoadUri>https://kdesteasidmcustom.blob.core.windows.net/LocalSignUI.html</LoadUri>
<RecoveryUri>~/common/default_page_error.html</RecoveryUri>
<DataUri>urn:com:microsoft:aad:b2c:elements:idpselection:1.0.0</DataUri>
<Metadata>
<Item Key="DisplayName">Idp selection page</Item>
<Item Key="language.intro">Sign in</Item>
</Metadata>
</ContentDefinition>
</ContentDefinitions>
</BuildingBlocks>
My UI customization file (LocalSignUI.html) as referenced above is very simple:
<!DOCTYPE html>
<html>
<body>
<h1>It worked!</h1>
<div id="api"></div>
</body>
</html>
www.test-cors.org seems to think that CORS is set up correctly for my content file. When I try to run the userjourney (using the path per the Azure AADB2C portal) I get a page that displays "It worked!" (from my html content file), "Sign in" (not sure where this originates but perhaps from the ContentDefinition "language.intro" key), and nothing else - rest of page is blank. If I examine page source, there is lots of javascript and a few tags to cover no-cookie and no-javascript scenarios, but there are no form or input tags. I've looked at the log info in application insights and see a reference to my content file but no apparent errors.
Any ideas?
thanks!
Martin
Solved thanks to hint from #spottedmahn! In my TrustFrameworkExtensions.xml file, I created a ContentDefinition (within BuildingBlocks -> ContentDefinitions) like this:
<ContentDefinition Id="api.signuporsignin">
<LoadUri>URL-OF-MY-CUSTOMIZATON-FILE</LoadUri>
<RecoveryUri>~/common/default_page_error.html</RecoveryUri>
<DataUri>urn:com:microsoft:aad:b2c:elements:unifiedssp:1.0.0</DataUri>
<Metadata>
<Item Key="DisplayName">Signin and Signup</Item>
</Metadata>
</ContentDefinition>
The UserJourney's first orchestration step is of Type CombinedSignInAndSignUp and ContentDefinitionReferenceID of api.signuporsignin. It appears that
the urn:com:microsoft:aad:b2c:elements:unifiedssp:1.0.0 value for DataUri in the ContentDefinition is key. The Div tag in my customization file contains simply id="api".
thanks!
Martin
I think you need at least a <head><title></title></head> otherwise it's not well formed HTML and may not work.

Resources