title: Azure AD B2C custom policy set extension attribute value
body: <p>I have B2C custom policy signin UserJouney which checks to see if the user requires a password reset on their first logon. We are using an extension attribute to do this as B2C has a bug where the "forceChangePasswordNextLogin" value prevents the user from logging in at all.</p>
  
  <p>Here is the sign in user journey.</p>
  
  <pre><code>&lt;UserJourney Id="SignUpOrSignInSaml"&gt;
    &lt;OrchestrationSteps&gt;
      &lt;OrchestrationStep Order="1" Type="CombinedSignInAndSignUp" ContentDefinitionReferenceId="api.signuporsignin"&gt;
        &lt;ClaimsProviderSelections&gt;
          &lt;ClaimsProviderSelection ValidationClaimsExchangeId="LocalAccountSigninUsernameExchange" /&gt;
        &lt;/ClaimsProviderSelections&gt;
        &lt;ClaimsExchanges&gt;
          &lt;ClaimsExchange Id="LocalAccountSigninUsernameExchange" TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Username" /&gt;
        &lt;/ClaimsExchanges&gt;
      &lt;/OrchestrationStep&gt;
      &lt;OrchestrationStep Order="2" Type="ClaimsExchange"&gt;
        &lt;Preconditions&gt;
          &lt;Precondition Type="ClaimsExist" ExecuteActionsIf="true"&gt;
            &lt;Value&gt;objectId&lt;/Value&gt;
            &lt;Action&gt;SkipThisOrchestrationStep&lt;/Action&gt;
          &lt;/Precondition&gt;
        &lt;/Preconditions&gt;
        &lt;ClaimsExchanges&gt;
          &lt;ClaimsExchange Id="SignUpWithLogonUsernameExchange" TechnicalProfileReferenceId="LocalAccountSignUpWithLogonName" /&gt;
        &lt;/ClaimsExchanges&gt;
      &lt;/OrchestrationStep&gt;
      &lt;!-- This step reads any user attributes that we may not have received when in the token. --&gt;
      &lt;OrchestrationStep Order="3" Type="ClaimsExchange"&gt;
        &lt;ClaimsExchanges&gt;
          &lt;ClaimsExchange Id="AADUserReadWithObjectId" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" /&gt;
        &lt;/ClaimsExchanges&gt;
      &lt;/OrchestrationStep&gt;
      &lt;OrchestrationStep Order="4" Type="ClaimsExchange"&gt;
        &lt;Preconditions&gt;
          &lt;Precondition Type="ClaimEquals" ExecuteActionsIf="false"&gt;
            &lt;Value&gt;extension_ChangePasswordRequired&lt;/Value&gt;
            &lt;Value&gt;true&lt;/Value&gt;
            &lt;Action&gt;SkipThisOrchestrationStep&lt;/Action&gt;
          &lt;/Precondition&gt;
          &lt;/Preconditions&gt;
          &lt;ClaimsExchanges&gt;
          &lt;ClaimsExchange Id="NewCredentials" TechnicalProfileReferenceId="LocalAccountWritePasswordChangeUsingObjectId" /&gt;
        &lt;/ClaimsExchanges&gt;
      &lt;/OrchestrationStep&gt;
      &lt;OrchestrationStep Order="5" Type="ClaimsExchange"&gt;
      &lt;ClaimsExchanges&gt;
        &lt;ClaimsExchange Id="UpdatePasswordResetValue" TechnicalProfileReferenceId="LocalAccountUpdatePasswordResetStateValue" /&gt;
      &lt;/ClaimsExchanges&gt;
    &lt;/OrchestrationStep&gt;
      &lt;OrchestrationStep Order="6" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="Saml2AssertionIssuer" /&gt;
    &lt;/OrchestrationSteps&gt;
    &lt;ClientDefinition ReferenceId="DefaultWeb" /&gt;
  &lt;/UserJourney&gt;
  </code></pre>
  
  <p>Step 4 in the UserJourney evaluates whether the extension attribute "extension_ChangePasswordRequired" is set to "true" and will prompt the user to change their password if it reads "true". This is working fine.</p>
  
  <p>Step 5 is then used to update the extension attribute to something other than "true" so the user isn't prompted again at next login however doesn't seem to be working.</p>
  
  <p>Here is my "LocalAccountUpdatePasswordResetStateValue" TechnicalProfile</p>
  
  <pre><code>    &lt;TechnicalProfile Id="LocalAccountUpdatePasswordResetStateValue"&gt;
          &lt;DisplayName&gt;Update Password Set Value&lt;/DisplayName&gt;
          &lt;Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.SelfAssertedAttributeProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /&gt;
          &lt;OutputClaims&gt;
            &lt;OutputClaim ClaimTypeReferenceId="extension_ChangePasswordRequired" Required="true" /&gt;
          &lt;/OutputClaims&gt;
          &lt;OutputClaimsTransformations&gt;
            &lt;OutputClaimsTransformation ReferenceId="SetPasswordResetStatus" /&gt;
          &lt;/OutputClaimsTransformations&gt;
          &lt;UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" /&gt;
        &lt;/TechnicalProfile&gt;
  </code></pre>
  
  <p>And here is the Output claims transformation that it is calling</p>
  
  <pre><code>&lt;ClaimsTransformation Id="SetPasswordResetStatus" TransformationMethod="FormatStringClaim"&gt;
        &lt;InputClaims&gt;
          &lt;InputClaim ClaimTypeReferenceId="extension_ChangePasswordRequired" TransformationClaimType="inputClaim" /&gt;
        &lt;/InputClaims&gt;
        &lt;InputParameters&gt;
          &lt;InputParameter Id="stringFormat" DataType="string" Value="abc123" /&gt;
        &lt;/InputParameters&gt;
        &lt;OutputClaims&gt;
          &lt;OutputClaim ClaimTypeReferenceId="extension_ChangePasswordRequired" TransformationClaimType="outputClaim" /&gt;
        &lt;/OutputClaims&gt;
      &lt;/ClaimsTransformation&gt;
  </code></pre>
  
  <p>The policies pass validation at time of upload however doesn't set the extension attribute on the user after a password reset.</p>
  
  <p>Does anyone know what I'm doing wrong here or if there is a better way of achieving this?</p>
  
  <p>-----Update-----</p>
  
  <p>I'm successfully able to write a value to a different extension attribute via a persisted claim as seen here</p>
  
  <pre><code>&lt;TechnicalProfile Id="AAD-UserUpdateStateValue"&gt;
     &lt;Metadata&gt;
        &lt;Item Key="Operation"&gt;Write&lt;/Item&gt;
        &lt;Item Key="RaiseErrorIfClaimsPrincipalAlreadyExists"&gt;false&lt;/Item&gt;
        &lt;Item Key="RaiseErrorIfClaimsPrincipalDoesNotExist"&gt;true&lt;/Item&gt;
     &lt;/Metadata&gt;
     &lt;IncludeInSso&gt;false&lt;/IncludeInSso&gt;
   &lt;InputClaims&gt;
     &lt;InputClaim ClaimTypeReferenceId="objectId" Required="true" /&gt;
   &lt;/InputClaims&gt;
   &lt;PersistedClaims&gt;
      &lt;!-- Required claims --&gt;
      &lt;PersistedClaim ClaimTypeReferenceId="objectId" /&gt;
      &lt;!-- Optional claims --&gt;
      &lt;PersistedClaim ClaimTypeReferenceId="extension_Flag" DefaultValue="abc1234567"/&gt;
      &lt;/PersistedClaims&gt;
    &lt;IncludeTechnicalProfile ReferenceId="AAD-Common" /&gt;
  &lt;/TechnicalProfile&gt;
  </code></pre>
  
  <p>However as mentioned by Chris in this <a href="https://stackoverflow.com/questions/51103669/azure-ad-b2c-custom-policy-update-user-attribute-with-static-value">post</a> this doesn't work if I have read the claim in a previous step.</p>