Can Sözbir
Can Sözbir

Reputation: 53

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".

password change page

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

Upvotes: 2

Views: 1174

Answers (2)

basquiatraphaeu
basquiatraphaeu

Reputation: 667

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

  1. 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.

  1. 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.

  1. 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)

Upvotes: 2

Jas Suri - MSFT
Jas Suri - MSFT

Reputation: 11335

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.

Upvotes: 1

Related Questions