darnmason
darnmason

Reputation: 2732

Azure B2C session causing unintended flow

Can somebody help me make sense of this behaviour with Azure AD B2C and reveal what I'm not understanding when it comes to the SSO session.

I have a fairly complex custom policy for signing in that includes sub journeys for both a custom Sign Up and embedded reset password, following the embedded password reset sample. I have a claim signinOption that gets set to either SignUp or ForgotPassword depending on the Claims Provider Selection in the CombinedSignInAndSignUp orchestration step. I then check the value of signinOption to decide whether to launch each sub journey. This is all working perfectly the first time around.

My issue occurs using MSAL with React but I haven't nailed down how to reliably reproduce it. It appears that MSAL is sending cookies and B2C is detecting an existing session, so it skips the signin screen and lands me on one of the sub journeys (SignUp or ForgotPassword). Closing the browser doesn't resolve it. Every time I launch my web app, it launches the signin custom policy and I land on the wrong screen. The only way I have fixed the state is to clear the cookies for my B2C tenant domain.

I have a User Journey log that I'm hoping somebody can help me analyse to figure out what's going wrong. In this instance the flow goes directly to the Forgot Password journey. I can see that it executes the ForgotPasswordExchange which sets my signinOption claim and that is what triggers the sub journey. My question is why is it executing the ForgotPasswordExchange when the user did not click Forgot Password on the signin screen, as the signin screen was skipped altogether.

Is it remembering it from the session somehow?

Some code to give an idea of my setup, here's the key parts.

Overriding the forgot password and sign up links:

<TechnicalProfile Id="ForgotPassword">
    <DisplayName>Forgot your password?</DisplayName>
    <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.ClaimsTransformationProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
    <OutputClaims>
        <OutputClaim ClaimTypeReferenceId="signinOption" DefaultValue="ForgotPassword" AlwaysUseDefaultValue="true"/>
    </OutputClaims>
</TechnicalProfile>
<TechnicalProfile Id="SignUp">
    <DisplayName>Sign up?</DisplayName>
    <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.ClaimsTransformationProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
    <OutputClaims>
        <OutputClaim ClaimTypeReferenceId="signinOption" DefaultValue="SignUp" AlwaysUseDefaultValue="true"/>
    </OutputClaims>
</TechnicalProfile>
<TechnicalProfile Id="SelfAsserted-LocalAccountSignin-Email">
    <Metadata>
        <Item Key="setting.forgotPasswordLinkOverride">ForgotPasswordExchange</Item>
        <Item Key="SignUpTarget">SignUpExchange</Item>
    </Metadata>
</TechnicalProfile>

My orchestration steps:

<OrchestrationStep Order="1" Type="GetClaims"
                                   CpimIssuerTechnicalProfileReferenceId="IdTokenHint_ExtractClaims"/>
<OrchestrationStep Order="2" Type="CombinedSignInAndSignUp"
                   ContentDefinitionReferenceId="api.signuporsignin">
    <Preconditions>
        <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
            <Value>objectId</Value>
            <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
        <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
            <Value>signinOption</Value>
            <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
    </Preconditions>
    <ClaimsProviderSelections DisplayOption="ShowSingleProvider">
        <ClaimsProviderSelection ValidationClaimsExchangeId="LocalAccountSigninEmailExchange"/>
        <ClaimsProviderSelection TargetClaimsExchangeId="SignUpExchange"/>
        <ClaimsProviderSelection TargetClaimsExchangeId="ForgotPasswordExchange"/>
    </ClaimsProviderSelections>
    <ClaimsExchanges>
        <ClaimsExchange Id="LocalAccountSigninEmailExchange"
                        TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Email"/>
    </ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="3" Type="ClaimsExchange">
    <Preconditions>
        <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
            <Value>objectId</Value>
            <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
        <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
            <Value>signinOption</Value>
            <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
    </Preconditions>
    <ClaimsExchanges>
        <ClaimsExchange Id="SignUpExchange" TechnicalProfileReferenceId="SignUp"/>
        <ClaimsExchange Id="ForgotPasswordExchange" TechnicalProfileReferenceId="ForgotPassword"/>
    </ClaimsExchanges>
</OrchestrationStep>
<OrchestrationStep Order="4" Type="InvokeSubJourney">
    <Preconditions>
        <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
            <Value>objectId</Value>
            <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
        <Precondition Type="ClaimEquals" ExecuteActionsIf="false">
            <Value>signinOption</Value>
            <Value>ForgotPassword</Value>
            <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
    </Preconditions>
    <JourneyList>
        <Candidate SubJourneyReferenceId="PasswordReset"/>
    </JourneyList>
</OrchestrationStep>
<OrchestrationStep Order="5" Type="InvokeSubJourney">
    <Preconditions>
        <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
            <Value>objectId</Value>
            <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
        <Precondition Type="ClaimEquals" ExecuteActionsIf="false">
            <Value>signinOption</Value>
            <Value>SignUp</Value>
            <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
    </Preconditions>
    <JourneyList>
        <Candidate SubJourneyReferenceId="SignUp"/>
    </JourneyList>
</OrchestrationStep>

And the User Journey log:

[
  {
    "Kind": "Headers",
    "Content": {
      "UserJourneyRecorderEndpoint": "urn:journeyrecorder:applicationinsights",
      "CorrelationId": "7fcfa796-ecfe-43df-9e08-ec5317e1beb2",
      "EventInstance": "Event:AUTH",
      "TenantId": "mytenant.onmicrosoft.com",
      "PolicyId": "B2C_1A_Signin"
    }
  },
  {
    "Kind": "Transition",
    "Content": {
      "EventName": "AUTH",
      "StateName": "Initial"
    }
  },
  {
    "Kind": "Predicate",
    "Content": "Web.TPEngine.StateMachineHandlers.NoOpHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true,
      "Statebag": {
        "MACHSTATE": {
          "c": "2021-06-10T01:13:52.7375163Z",
          "k": "MACHSTATE",
          "v": "Initial",
          "p": true
        },
        "JC": {
          "c": "2021-06-10T01:13:52.7375163Z",
          "k": "JC",
          "v": "en",
          "p": true
        },
        "ComplexItems": "_MachineEventQ, TCTX"
      },
      "PredicateResult": "True"
    }
  },
  {
    "Kind": "Action",
    "Content": "Web.TPEngine.OrchestrationManager"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true,
      "Statebag": {
        "Complex-CLMS": {},
        "ORCH_CS": {
          "c": "2021-06-10T01:13:52.7375163Z",
          "k": "ORCH_CS",
          "v": "0",
          "p": true
        },
        "RA": {
          "c": "2021-06-10T01:13:52.7375163Z",
          "k": "RA",
          "v": "0",
          "p": true
        },
        "ComplexItems": "_MachineEventQ, TCTX, ORCH_IDX"
      }
    }
  },
  {
    "Kind": "Transition",
    "Content": {
      "EventName": "PreStep",
      "StateName": "Initial"
    }
  },
  {
    "Kind": "Predicate",
    "Content": "Web.TPEngine.StateMachineHandlers.NoOpHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true,
      "PredicateResult": "True"
    }
  },
  {
    "Kind": "Action",
    "Content": "Web.TPEngine.StateMachineHandlers.PreSetupHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true,
      "Statebag": {
        "RPP": {
          "c": "2021-06-10T01:13:52.7375163Z",
          "k": "RPP",
          "v": "OAUTH2",
          "p": true
        },
        "RPIPP": {
          "c": "2021-06-10T01:13:52.7375163Z",
          "k": "RPIPP",
          "v": "OAuth2ProtocolProvider",
          "p": true
        },
        "OTID": {
          "c": "2021-06-10T01:13:52.7375163Z",
          "k": "OTID",
          "v": "mytenant.onmicrosoft.com",
          "p": true
        },
        "APPMV": {
          "c": "2021-06-10T01:13:52.7375163Z",
          "k": "APPMV",
          "v": "V2",
          "p": true
        }
      }
    }
  },
  {
    "Kind": "Predicate",
    "Content": "Web.TPEngine.StateMachineHandlers.InitiatingMessageValidationHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": false,
      "RecorderRecord": {
        "Values": [
          {
            "Key": "Validation",
            "Value": {
              "Values": [
                {
                  "Key": "SubmittedBy",
                  "Value": "Application"
                },
                {
                  "Key": "ProtocolProviderType",
                  "Value": "OpenIdConnectProtocolProvider"
                }
              ]
            }
          }
        ]
      },
      "Statebag": {
        "CT": {
          "c": "2021-06-10T01:13:52.8875243Z",
          "k": "CT",
          "v": "Spa",
          "p": true
        },
        "CC": {
          "c": "2021-06-10T01:13:52.8875243Z",
          "k": "CC",
          "v": "gIsVYH_0vVOTcxFUoYdb9oen4eq6Bfionj1djotzkQ4",
          "p": true
        },
        "CCM": {
          "c": "2021-06-10T01:13:52.8875243Z",
          "k": "CCM",
          "v": "S256",
          "p": true
        },
        "MSG(508dad2b-059e-4fb5-9719-f24c8d5360e8)": {
          "c": "2021-06-10T01:13:52.8925242Z",
          "k": "MSG(508dad2b-059e-4fb5-9719-f24c8d5360e8)",
          "v": "{\"TenantId\":\"mytenant.onmicrosoft.com\",\"PolicyId\":\"B2C_1A_Signin\",\"RedirectUri\":\"https://mywebsite.com.au/\",\"AdditionalParameters\":{\"client-request-id\":\"eb98add7-a02c-3312-a98c-b0f9c6ddeb15\",\"x-client-SKU\":\"msal.js.browser\",\"x-client-VER\":\"2.14.2\",\"x-client-OS\":\"\",\"x-client-CPU\":\"\",\"client_info\":\"1\",\"code_challenge\":\"gIsVYH_0wWOTcxFUoYdb9oen4eq6Bfionj1djotzkQ4\",\"code_challenge_method\":\"S256\"},\"Nonce\":\"41d42929-eabb-45a3-b0f2-743b89247a24\",\"State\":\"eyJpZCI6IjEwOGUyOWUzLTY3YzMtNGQ1OS05YmFkLTBkMWIwN2QyM2ZiOSIsIm1ldGEiOnsiaW50ZXJhY3Rpb25UeXBlIjoicmVkaXJlY3QifX0=\",\"ClientId\":\"cb8678e1-0eee-4f6f-868a-72b968b0a8c0\",\"ResponseType\":\"code\",\"ResponseMode\":\"fragment\",\"ResponseRedirector\":{\"URI\":\"https://mywebsite.com.au\",\"D\":false,\"WF\":true},\"Scope\":\"https://mytenant.onmicrosoft.com/api/user.read openid profile offline_access\",\"AppModelVersion\":1,\"ScopedProviders\":[]}",
          "p": true,
          "t": "OAuth2"
        },
        "CMESSAGE": {
          "c": "2021-06-10T01:13:52.8925242Z",
          "k": "CMESSAGE",
          "v": "508dad2b-059e-4fb5-9719-f24c8d5360e8",
          "p": true
        },
        "IMESSAGE": {
          "c": "2021-06-10T01:13:52.8925242Z",
          "k": "IMESSAGE",
          "v": "508dad2b-059e-4fb5-9719-f24c8d5360e8",
          "p": true
        },
        "ComplexItems": "_MachineEventQ, TCTX, ORCH_IDX, REPRM, IC"
      },
      "PredicateResult": "True"
    }
  },
  {
    "Kind": "Predicate",
    "Content": "Web.TPEngine.StateMachineHandlers.NoOpHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true,
      "PredicateResult": "True"
    }
  },
  {
    "Kind": "Action",
    "Content": "Web.TPEngine.SSO.ResetSSOSessionHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true
    }
  },
  {
    "Kind": "Action",
    "Content": "Web.TPEngine.StateMachineHandlers.ClientInputClaimsTransformationHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true
    }
  },
  {
    "Kind": "Action",
    "Content": "Web.TPEngine.OrchestrationManager"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true,
      "Statebag": {
        "ORCH_CS": {
          "c": "2021-06-10T01:13:52.9025365Z",
          "k": "ORCH_CS",
          "v": "1",
          "p": true
        }
      }
    }
  },
  {
    "Kind": "Transition",
    "Content": {
      "EventName": "GetClaims",
      "StateName": "AwaitingNextStep"
    }
  },
  {
    "Kind": "Predicate",
    "Content": "Web.TPEngine.StateMachineHandlers.NoOpHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true,
      "Statebag": {
        "MACHSTATE": {
          "c": "2021-06-10T01:13:52.9025365Z",
          "k": "MACHSTATE",
          "v": "AwaitingNextStep",
          "p": true
        }
      },
      "PredicateResult": "True"
    }
  },
  {
    "Kind": "Action",
    "Content": "Web.TPEngine.StateMachineHandlers.GetRelyingPartyInputClaimsHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true
    }
  },
  {
    "Kind": "Action",
    "Content": "Web.TPEngine.OrchestrationManager"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true,
      "Statebag": {
        "ORCH_CS": {
          "c": "2021-06-10T01:13:52.9025365Z",
          "k": "ORCH_CS",
          "v": "2",
          "p": true
        }
      }
    }
  },
  {
    "Kind": "Transition",
    "Content": {
      "EventName": "CombinedSignInAndSignUp",
      "StateName": "AwaitingNextStep"
    }
  },
  {
    "Kind": "Predicate",
    "Content": "Web.TPEngine.SSO.IsSSOSessionParticipantHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true,
      "PredicateResult": "False"
    }
  },
  {
    "Kind": "Predicate",
    "Content": "Web.TPEngine.StateMachineHandlers.HomeRealmDiscoveryHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true,
      "RecorderRecord": {
        "Values": [
          {
            "Key": "HomeRealmDiscovery",
            "Value": {
              "Values": [
                {
                  "Key": "CurrentStep",
                  "Value": 2
                },
                {
                  "Key": "TechnicalProfileEnabled",
                  "Value": {
                    "EnabledRule": "Always",
                    "EnabledResult": true,
                    "TechnicalProfile": "SelfAsserted-LocalAccountSignin-Email"
                  }
                },
                {
                  "Key": "TechnicalProfileEnabled",
                  "Value": {
                    "EnabledRule": "Always",
                    "EnabledResult": true,
                    "TechnicalProfile": "SignUp"
                  }
                },
                {
                  "Key": "TechnicalProfileEnabled",
                  "Value": {
                    "EnabledRule": "Always",
                    "EnabledResult": true,
                    "TechnicalProfile": "ForgotPassword"
                  }
                }
              ]
            }
          }
        ]
      },
      "Statebag": {
        "TAGE": {
          "c": "2021-06-10T01:13:52.907517Z",
          "k": "TAGE",
          "v": "ForgotPasswordExchange",
          "p": true
        }
      },
      "PredicateResult": "True"
    }
  },
  {
    "Kind": "Predicate",
    "Content": "Web.TPEngine.StateMachineHandlers.NoOpHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true,
      "PredicateResult": "True"
    }
  },
  {
    "Kind": "Action",
    "Content": "Web.TPEngine.SSO.SSOSessionHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true
    }
  },
  {
    "Kind": "Action",
    "Content": "Web.TPEngine.OrchestrationManager"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true,
      "Statebag": {
        "ORCH_CS": {
          "c": "2021-06-10T01:13:52.907517Z",
          "k": "ORCH_CS",
          "v": "3",
          "p": true
        }
      }
    }
  },
  {
    "Kind": "Transition",
    "Content": {
      "EventName": "ClaimsExchange",
      "StateName": "AwaitingNextStep"
    }
  },
  {
    "Kind": "Predicate",
    "Content": "Web.TPEngine.StateMachineHandlers.ShouldOrchestrationStepBeInvokedHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true,
      "RecorderRecord": {
        "Values": [
          {
            "Key": "EnabledForUserJourneysTrue",
            "Value": {
              "Values": [
                {
                  "Key": "CurrentStep",
                  "Value": 3
                },
                {
                  "Key": "TechnicalProfileEnabled",
                  "Value": {
                    "EnabledRule": "Always",
                    "EnabledResult": true,
                    "TechnicalProfile": "SignUp"
                  }
                },
                {
                  "Key": "TechnicalProfileEnabled",
                  "Value": {
                    "EnabledRule": "Always",
                    "EnabledResult": true,
                    "TechnicalProfile": "ForgotPassword"
                  }
                }
              ]
            }
          }
        ]
      },
      "PredicateResult": "True"
    }
  },
  {
    "Kind": "Predicate",
    "Content": "Web.TPEngine.StateMachineHandlers.IsClaimsExchangeProtocolARedirectionHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true,
      "PredicateResult": "False"
    }
  },
  {
    "Kind": "Predicate",
    "Content": "Web.TPEngine.StateMachineHandlers.IsClaimsExchangeProtocolAnApiHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true,
      "PredicateResult": "False"
    }
  },
  {
    "Kind": "Predicate",
    "Content": "Web.TPEngine.SSO.IsSSOSessionParticipantHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true,
      "PredicateResult": "False"
    }
  },
  {
    "Kind": "Predicate",
    "Content": "Web.TPEngine.StateMachineHandlers.IsClaimsExchangeProtocolAServiceCallHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true,
      "RecorderRecord": {
        "Values": [
          {
            "Key": "InitiatingClaimsExchange",
            "Value": {
              "ProtocolType": "backend protocol",
              "TargetEntity": "ForgotPasswordExchange",
              "TechnicalProfileId": "ForgotPassword",
              "ProtocolProviderType": "ClaimsTransformationProtocolProvider"
            }
          }
        ]
      },
      "PredicateResult": "True"
    }
  },
  {
    "Kind": "Action",
    "Content": "Web.TPEngine.StateMachineHandlers.GenerateRequestInputParamsHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": false
    }
  },
  {
    "Kind": "Action",
    "Content": "Web.TPEngine.StateMachineHandlers.InputClaimsTransformationHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true
    }
  },
  {
    "Kind": "Action",
    "Content": "Web.TPEngine.StateMachineHandlers.PersistedClaimsTransformationHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true
    }
  },
  {
    "Kind": "Action",
    "Content": "Web.TPEngine.StateMachineHandlers.OutputClaimsTransformationHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true,
      "RecorderRecord": {
        "Values": [
          {
            "Key": "GettingClaims",
            "Value": {
              "Values": [
                {
                  "Key": "InitiatingBackendClaimsExchange",
                  "Value": {
                    "TechnicalProfileId": "ForgotPassword",
                    "ProtocolProviderType": "ClaimsTransformationProtocolProvider"
                  }
                }
              ]
            }
          },
          {
            "Key": "OutputClaimsTransformation",
            "Value": {
              "Values": [
                {
                  "Key": "MappingDefaultValueForClaim",
                  "Value": {
                    "PartnerClaimType": "signinOption",
                    "PolicyClaimType": "signinOption"
                  }
                }
              ]
            }
          }
        ]
      },
      "Statebag": {
        "Complex-CLMS": {
          "signinOption": "ForgotPassword"
        }
      }
    }
  },
  {
    "Kind": "Action",
    "Content": "Web.TPEngine.SSO.SSOSessionHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true
    }
  },
  {
    "Kind": "Action",
    "Content": "Web.TPEngine.OrchestrationManager"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true,
      "Statebag": {
        "ORCH_CS": {
          "c": "2021-06-10T01:13:52.9125258Z",
          "k": "ORCH_CS",
          "v": "4",
          "p": true
        }
      }
    }
  },
  {
    "Kind": "Transition",
    "Content": {
      "EventName": "InvokeSubJourney",
      "StateName": "AwaitingNextStep"
    }
  },
  {
    "Kind": "Predicate",
    "Content": "Web.TPEngine.StateMachineHandlers.NoOpHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true,
      "PredicateResult": "True"
    }
  },
  {
    "Kind": "Action",
    "Content": "Web.TPEngine.StateMachineHandlers.EnqueueNewJourneyHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true,
      "RecorderRecord": {
        "Values": [
          {
            "Key": "SubJourneyInvoked",
            "Value": "PasswordReset"
          }
        ]
      },
      "Statebag": {
        "ORCH_CS": {
          "c": "2021-06-10T01:13:52.9125258Z",
          "k": "ORCH_CS",
          "v": "0",
          "p": true
        },
        "ComplexItems": "_MachineEventQ, TCTX, ORCH_IDX, REPRM, IC, JL"
      }
    }
  },
  {
    "Kind": "Action",
    "Content": "Web.TPEngine.OrchestrationManager"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true,
      "Statebag": {
        "ORCH_CS": {
          "c": "2021-06-10T01:13:52.9125258Z",
          "k": "ORCH_CS",
          "v": "1",
          "p": true
        }
      }
    }
  },
  {
    "Kind": "Transition",
    "Content": {
      "EventName": "ClaimsExchange",
      "StateName": "AwaitingNextStep"
    }
  },
  {
    "Kind": "Predicate",
    "Content": "Web.TPEngine.StateMachineHandlers.ShouldOrchestrationStepBeInvokedHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true,
      "RecorderRecord": {
        "Values": [
          {
            "Key": "EnabledForUserJourneysTrue",
            "Value": {
              "Values": [
                {
                  "Key": "CurrentStep",
                  "Value": 1
                },
                {
                  "Key": "TechnicalProfileEnabled",
                  "Value": {
                    "EnabledRule": "Always",
                    "EnabledResult": true,
                    "TechnicalProfile": "LocalAccountDiscoveryUsingEmailAddress"
                  }
                }
              ]
            }
          }
        ]
      },
      "PredicateResult": "True"
    }
  },
  {
    "Kind": "Predicate",
    "Content": "Web.TPEngine.StateMachineHandlers.IsClaimsExchangeProtocolARedirectionHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true,
      "PredicateResult": "False"
    }
  },
  {
    "Kind": "Predicate",
    "Content": "Web.TPEngine.StateMachineHandlers.IsClaimsExchangeProtocolAnApiHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true,
      "RecorderRecord": {
        "Values": [
          {
            "Key": "InitiatingClaimsExchange",
            "Value": {
              "ProtocolType": "Identity Experience Engine API",
              "TargetEntity": "ForgotPasswordExchange",
              "TechnicalProfileId": "LocalAccountDiscoveryUsingEmailAddress",
              "ProtocolProviderType": "SelfAssertedAttributeProvider"
            }
          }
        ]
      },
      "PredicateResult": "True"
    }
  },
  {
    "Kind": "Action",
    "Content": "Web.TPEngine.StateMachineHandlers.SwitchToApiOrchestrationHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true
    }
  },
  {
    "Kind": "Transition",
    "Content": {
      "EventName": "SELFASSERTED",
      "StateName": "AwaitingNextStep"
    }
  },
  {
    "Kind": "Predicate",
    "Content": "Web.TPEngine.SSO.IsSSOSessionParticipantHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true,
      "PredicateResult": "False"
    }
  },
  {
    "Kind": "Predicate",
    "Content": "Web.TPEngine.StateMachineHandlers.IsSelfAssertedEmpty"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true,
      "PredicateResult": "False"
    }
  },
  {
    "Kind": "Action",
    "Content": "Web.TPEngine.StateMachineHandlers.InputClaimsTransformationHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true
    }
  },
  {
    "Kind": "Action",
    "Content": "Web.TPEngine.StateMachineHandlers.ConvertToAttributeFieldHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true,
      "Statebag": {
        "ComplexItems": "_MachineEventQ, TCTX, ORCH_IDX, REPRM, IC, JL, SA_FIELDS"
      }
    }
  },
  {
    "Kind": "Action",
    "Content": "Web.TPEngine.StateMachineHandlers.ApiLoadHandler"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true,
      "Statebag": {
        "ComplexItems": "_MachineEventQ, TCTX, ORCH_IDX, REPRM, IC, JL, SA_FIELDS, EID, UXRC, ARC"
      }
    }
  },
  {
    "Kind": "Action",
    "Content": "Web.TPEngine.Api.ApiUIManager"
  },
  {
    "Kind": "HandlerResult",
    "Content": {
      "Result": true,
      "RecorderRecord": {
        "Values": [
          {
            "Key": "ApiUiManagerInfo",
            "Value": {
              "Values": [
                {
                  "Key": "Language",
                  "Value": "..."
                },
                {
                  "Key": "Settings",
                  "Value": "..."
                }
              ]
            }
          }
        ]
      }
    }
  }
]

Upvotes: 1

Views: 1570

Answers (1)

darnmason
darnmason

Reputation: 2732

So through some trial and error I discovered a solution to my problem and think I've gained some extra understanding of the black box that is B2C custom policies.

I figured out reproduction steps which were:

  1. During my sign in flow select sign up or forgot password.
  2. Complete registration/reset to end up back in my application signed in.
  3. Close the browser tab.
  4. Launch the web app again, MSAL redirects to B2C.
  5. I land on the flow I selected previously, it's not possible to get back to the sign in screen.

The solution to my problem was to add <UseTechnicalProfileForSessionManagement ReferenceId="SM-AAD"/> to every technical profile throughout my orchestration steps. This includes the claims exchange TPs that I created to handle the SignUpLink and Forgot Password targets.

My understanding is that B2C steps through all of the orchestration steps, as it detects a session it skips any TP that uses session management. In my case only step 2 SelfAsserted-LocalAccountSignin-Email had session management and so this was skipped. I can only assume that the Claims Provider selection that was previously selected was saved and retrieved from the session, which caused it to act as if the user had selected it again.

As the proceeding steps didn't use session management they ended up being executed, landing the user on either the sign up or reset password screen, depending on which Claims Provider was previously selected.

If anyone can expand on my understanding or suggest a more refined solution I'm all ears.

Upvotes: 4

Related Questions