How do you Trigger a Technical Profile if Validation Technical Profile fails - azure-ad-b2c

I am wanting to log the error if the validation technical profile fails. Since the app insight log is in a technical profile... how do I trigger it?
The code below is in the technical profile that the orchestration step points to.
The send Data step seems to fail a decent amount of time, and I want to log it.
Is there a way to keep the "ContinueOnError="False" but also run a technical profile ONLY if it errors?
<ValidationTechnicalProfiles>
<ValidationTechnicalProfile ReferenceId="REST-AcquireAccessToken" />
<ValidationTechnicalProfile ReferenceId="REST-SendData" ContinueOnError="false">
<Preconditions>
<Precondition Type="ClaimsExist" ExecuteActionsIf="false">
<Value>extension_1</Value>
<Value>extension_2</Value>
<Action>SkipThisValidationTechnicalProfile</Action>
</Precondition>
</Preconditions>
</ValidationTechnicalProfile>
</ValidationTechnicalProfiles>

In situations where error capture needs to be more granular that what is available, I've seen many people create an extensionAttribute within the policy and pipe the error code into the claim bag. The App insights will capture the data being piped into that specific claim type and you can create logging analytics to track when this claim is populated with XYZ error code value.
Using default values to these extensionAttributes can be powerful. You can make assumptions and logic something like extensionAttribute error = true unless the validation technical profile is updates it to 'false' with a claimtransformation. Azure App Insights should be able to track this data as well if enabled.
Alternatively, you can use the method above to trigger a REST-SendDataFAILED validation technical profile that is triggered in the scenario where it fails (this would allow you to capture the data regardless of if it is triggered but again, this should be triggered on preconditions and leveraging attributes. Make sure you output any claims in your validation technical profile to ensure that value is in the claim bag for the next precondition.

Related

Can MFA be switched on or off for a user based on an application setting in Azure AD B2C?

We are using Azure AD B2C login in our web application. We want to be able to set MFA for a B2C user based on a setting in the application. From the documentation, I can see that custom policies are able to be applied. But can the custom policy hook in to the application to read a setting (eg whether MFA should be applied in this case)?
Another approach we are considering is to set MFA programmatically for the user, based on the application setting. I have read that MFA can be set on a per user basis, through the Azure Portal. Is there a way to do this programmatically? I have looked at the Graph API but have not seen anything obvious.
I have tried setting the MFA setting for a user via the Azure portal, but this is not working for me yet. Despite setting the user's MFA to Enforced, the user can still sign in without being challenged. I also find the portal confusing, and for many users there is no clear way of identifying them (the portal only shows display name as Unknown and email address as an internal identity rather than an external identity).
I have seen these following posts Can I apply MFA to each user in Azure ADB2C and Azure AD B2C MFA on a function which do provide some useful information, but I am still unclear on this.
Is this possible, and which approach (custom policy hooking in to the application to read setting, or setting the MFA for the specific user from the application) would be better?
The way I normally do this is by having an extension attribute in B2C that determines whether the user has MFA or not.
Using the starter pack MFA sample e.g.:
<OrchestrationStep Order="7" Type="ClaimsExchange">
<Preconditions>
<Precondition Type="ClaimsExist" ExecuteActionsIf="false">
<Value>extension_MFA</Value>
<Action>SkipThisOrchestrationStep</Action>
</Precondition>
<Precondition Type="ClaimsExist" ExecuteActionsIf="true">
<Value>isActiveMFASession</Value>
<Action>SkipThisOrchestrationStep</Action>
</Precondition>
</Preconditions>
<ClaimsExchanges>
<ClaimsExchange Id="PhoneFactor-Verify" TechnicalProfileReferenceId="PhoneFactor-InputOrVerify"/>
</ClaimsExchanges>
</OrchestrationStep>
You would need to add the extension attribute as an output claim in a "AAD-UserRead" step.

B2C custom policy Change Password "The username or password provided in the request are invalid"

I'm trying to implement a password change custom policy for Azure AD B2C.
I've used this file as a base, changed the tenantid, and uploaded it to Azure.
When I try a demo from the Azure portal, it asks me to log in, then asks for an old password and a new password to change it. And it works perfectly fine. I can change my password there.
Then I've implemented a button, that redirects to the password change URL.
private redirectPasswordChange(appConfigService: AppConfigService): void {
const passwordChangeUrl = `${appConfigService.config.AD_AUTHORITY_CHANGE}?client_id=${appConfigService.config.AD_CLIENT_ID}
&nonce=defaultNonce
&redirect_uri=${appConfigService.config.BASE_URL}
&scope=openid
&response_type=id_token`;
if (isPlatformBrowser(PLATFORM_ID)) {
window.location.href = passwordChangeUrl;
} else {
this.window.location.href = passwordChangeUrl;
}
}
I've removed prompt=login from the URL because the button that is going to redirect to the password change URL is on the "My profile" section on our website. So users are already logged in, and I don't want them to log in again.
Then I tested it on our website, when I click to button, it redirects me to the password change page, it asks for my old password, new password, and confirmation of it, which is perfect for me. But the problem is, it doesn't accept my old password, it says "The username or password provided in the request are invalid".
I've searched for the problem online, including StackOverflow, but I found that there are lots of different answers for this problem. One of them is saying that:
Its because these input claims are overwriting the input claim names for login-noninteractive.
<InputClaim ClaimTypeReferenceId="grant_type" DefaultValue="client_credentials" />
<InputClaim ClaimTypeReferenceId="scope" DefaultValue="https://{{tenantID}}.onmicrosoft.com/{{registeredApiAppName}}/.default" />
</InputClaims>
use different claim names, and use a partnerclaimtype to send the value with the original claim name.
https://stackoverflow.com/a/65931145/8831824
When I take a look, I can see that those orchestrationsteps on PasswordChange.xml are the same in TrustFrameworkBase.xml
<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="3" Type="ClaimsExchange"> <ClaimsExchanges> <ClaimsExchange Id="AADUserReadWithObjectId" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" /> </ClaimsExchanges> </OrchestrationStep>
Is there some kind of overwriting here? I mean, they are exactly the same, but in two different files, In TrustFrameworkBase.xml, for SignUpOrSignIn journey, and PasswordChange.xml, for PasswordChange journey.
Here are the policies I have. I did put great effort to solve the problem, but I couldn't even identify it. Hope someone can give me an idea to work on it. Thanks for reading.
TrustFrameworkBase.xml: https://pastebin.com/RXXhcwpN
TrustFrameworkExtensions.xml: https://pastebin.com/UUfVNaJ7
PasswordChange.xml : https://pastebin.com/sPjZjNYT
PasswordReset.xml : https://pastebin.com/CxE3pMH3
Your password change xml should have the base policy node reference the trust framework extensions policy, not the trust framework base policy, as per my sample.
Ultimately the issue is because trust framework base file only contains part of the login-noninteractive technical profile. It is completed in the extension file, hence you must reference a file from which all dependencies are satisfied.
Got the same problem, but different from the question author my issue wasn't mixing up user flows with custom policies.
I was 100% sure that the root cause was not misconfiguration of login-noninteractive nor IdentityExperienceFramework to ProxyIdentityExperienceFrameworkAppId wrong setup as I followed copybook style ms docs on it.
The error cause turns out to be that the property accessTokenAcceptedVersion on IdentityExperienceFramework's manifest file was set to 2 instead of null.
Setting it to null solves the issue.
Considerations
How come this property was set to 2? And why is this a problem
Most likely because I've created the app initially configured to
support Accounts in any organizational directory (Any Azure AD
directory - Multitenant) but changed my mind and updated it to
support Accounts in this organizational directory only (your-tenant
only - Single tenant) changing the manifest property to look like so:
"signInAudience": "AzureADMyOrg",
as the docs states:
If signInAudience is azureADandPersonalMicrosoftAccount, the value (of accessTokenAcceptedVersion) must be 2.
How do I spot that issue?
By automating the environment configuration of an auxiliary B2C tenant by using the https://b2ciefsetupapp.azurewebsites.net/ and comparing each of the app's configs.
If you've setup IdentityExperienceFramework and ProxyIdentityExperienceFrameworkAppId manually by following ms docs and still facing this obscure issue:
I highly recommend you delete your apps and rely on the automated tool. (I've learned my lesson)

Azure B2C disable Identity Provider Sign up of a SignUpAndSignIn policy - Apple Identity Provider IDP

I need some advice on Customizing Azure B2c (Apple Identity Provider)
Is there a way to disable the sign up of a SignUpAndSignIn policy for an specific IDP? In that case apple?
I checked that post Azure B2C disable Sign up of a SignUpAndSignIn policy but is regarding to local signup, not for a social provider
You can do it only in custom policies. They are divided into steps (OrchestrationStep) which can be run under specified conditions (Precondition). One of those conditions can be identity provider selected. In your case it would be configuring the step which writes new external IdP user to directory to be skipped when particular provider is detected.
Something similar to this:
<OrchestrationStep Order="7" Type="ClaimsExchange">
<Preconditions>
<Precondition Type="ClaimEquals" ExecuteActionsIf="true">
<Value>identityProvider</Value>
<Value>https://appleid.apple.com</Value>
<Action>SkipThisOrchestrationStep</Action>
</Precondition>
</Preconditions>
<ClaimsExchanges>
<ClaimsExchange Id="AADUserWrite" TechnicalProfileReferenceId="AAD-UserWriteUsingAlternativeSecurityId" />
</ClaimsExchanges>
However, this is just stopping the signup from happening. Some error handling, UX etc would have to be added as well.
Thank you very much for your time.
I'm receiving the following window, we don't want to see the following prompt
enter image description here
We want to use our Apple ID and jump to the app (see image bellow)
enter image description here

B2C Custom Policy - Are SubJourney OutputClaims accessible in parent UserJourney

There appears to be limited documentation around sub journeys. https://learn.microsoft.com/en-us/azure/active-directory-b2c/subjourneys
I have a problem where in my SubJourney, I read the user and get the object Id. In the main UserJourney, I later use that object Id to read the user again, but it complains.
Although objectId is an output claim in the first step of the SubJourney, the main User Journey cannot use that output.
<SubJourneys>
<SubJourney Id="ResetPhoneNumberOnAccount" Type="Call">
<OrchestrationSteps>
<!-- Look to see if the user exists if its a phone recovery -->
<OrchestrationStep Order="1" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="CheckIfUserExists" TechnicalProfileReferenceId="AAD-UserDiscoveryUsingLogonPhoneNumber-FullProfile" />
</ClaimsExchanges>
</OrchestrationStep>
<!-- Other Step -->
</SubJourney>
</SubJourneys>
AAD-UserDiscoveryUsingLogonPhoneNumber-FullProfile is defined: https://github.com/Azure-Samples/active-directory-b2c-custom-policy-starterpack/blob/master/scenarios/phone-number-passwordless/Phone_Email_Base.xml#L905
Are SubJourneys not able to send output claims up the chain?
Yes, output claims from orchestration steps in sub journeys are accessible from the parent user journey. It seems like when an orchestration step depends on an output claim returned from a sub journey, the step must itself be encapsulated in its own sub journey.
If AAD-UserReadUsingObjectId exists in the main journey, but objectId is only output in a sub journey, the policy will fail validation. This appears to me to be bug with the XML schema validator.
I have examined trace logs in app insights and, after applying this workaround, can confirm that claims output in sub journeys do persist until the main journey has ended.
For a more in depth look at this problem, check out my issue on GitHub.
Seems like its not possible, can you try using the transfer sub-journey here?
<SubJourneys>
<SubJourney Id="B" Type="Transfer">
<OrchestrationSteps>
...
<OrchestrationStep Order="5" Type="SendClaims">
</OrchestrationSteps>
</SubJourney>
</SubJourneys>

Avoid verification code emails when the user is not registered in Azure AD B2C

Azure B2C is gives a false impression that the user is in the directory when they try to reset their password.
Following is steps in reset password:
1) User clicks the Reset Password link
2) B2C presents a page with “Email Address” field and says “Verification is necessary. Please click Send button.”
3) User enters his email address and clicks “Send Verification Code”
4) B2C sends the verification code this that email address (Even if no user is associated with that email address. This is where the user thinks he is registered with the system)
5) Now the user enters the verification code he received and click “Verify Code”
6) B2C validated the code and says “E-mail address verified. You can now continue” (This is the step where they become confident that they exist in the system)
7) Now when the users click “Continue” they get the error “An account could not be found for the provided user ID.” As given in the screenshot.
Confirming an email that is not associated with a user completely confuses them.
i found this solution but not getting exactly how to use these policy along with my current policy
Based on this solution, you need to use the following XML snippet to implement it:
<Action Id="SendCode">
<ValidationClaimsExchange>
<ValidationClaimsExchangeTechnicalProfile TechnicalProfileReferenceId="AAD-UserReadUsingEmailAddress-emailAddress" />
<ValidationClaimsExchangeTechnicalProfile TechnicalProfileReferenceId="AadSspr-SendCode">
<Preconditions>
<Precondition Type="ClaimsExist" ExecuteActionsIf="false">
<Value>objectId</Value>
<Action>SkipThisValidationTechnicalProfile</Action>
</Precondition>
</Preconditions>
</ValidationClaimsExchangeTechnicalProfile>
</ValidationClaimsExchange>
</Action>
So you should begin with adding "emailVerificationControl" into the "LocalAccountDiscoveryUsingEmailAddress" TechnicalProfile.
Just adding line 163-165 to the place behind line 890.
And you need to add DisplayControls into your TrustFrameworkExtensions.xml file so that it could be referenced.
If there are any other references, you should also add them to the corresponding position.

Resources