2
votes

Following the MS documentation for the ROPC flow I have added a custom User Journey for refreshing tokens in my app using the Authorization Code Flow. I've added the RefreshTokenUserJourneyId metadata with the Id of my new User Journey RefreshToken.

The key reason for doing this is to make a REST call to get an updated claim isVerified. It's the same REST TP that I use during sign-in-up and it works well.

Given I have a token with isVerified = true, I update my database to say the user is no longer verified, and I refresh the token. I can see that B2C calls my REST endpoint. I can see in Application Insights that the state bag has the correct value isVerified = false. But the id_token returned still has the old value isVerified = true.

Why is SendClaims not using the correct values from the state bag?

What do I have to do for B2C to generate the new token with the latest claims? Is this due to the fact I'm not using the ROPC flow, but instead the Authorization code flow?

JwtIssuer TP used for sign-in-up:

<TechnicalProfile Id="JwtIssuer">
    <Protocol Name="OpenIdConnect" />
    <Metadata>
        <Item Key="token_lifetime_secs">900</Item>
        <Item Key="id_token_lifetime_secs">900</Item>
        <Item Key="refresh_token_lifetime_secs">1209600</Item>
        <Item Key="allow_infinite_rolling_refresh_token">true</Item>
        <Item Key="RefreshTokenUserJourneyId">RefreshToken</Item>
    </Metadata>
    <UseTechnicalProfileForSessionManagement ReferenceId="SM-OAuth-issuer" />
</TechnicalProfile>

RefreshToken User Journey:

<UserJourney Id="RefreshToken">
    <PreserveOriginalAssertion>false</PreserveOriginalAssertion>
    <OrchestrationSteps>
        <OrchestrationStep Order="1" Type="ClaimsExchange">
            <ClaimsExchanges>
                <ClaimsExchange Id="RefreshTokenSetupExchange" TechnicalProfileReferenceId="SM-RefreshTokenReadAndSetup" />
            </ClaimsExchanges>
        </OrchestrationStep>
        <OrchestrationStep Order="2" Type="ClaimsExchange">
            <ClaimsExchanges>
                <ClaimsExchange Id="CheckRefreshTokenDateFromAadExchange" TechnicalProfileReferenceId="AAD-UserReadUsingObjectId-CheckRefreshTokenDate" />
            </ClaimsExchanges>
        </OrchestrationStep>
        <OrchestrationStep Order="3" Type="ClaimsExchange">
            <ClaimsExchanges>
                <ClaimsExchange Id="RESTGetUserCrm" TechnicalProfileReferenceId="SP-GetUser"/>
            </ClaimsExchanges>
        </OrchestrationStep>
        <OrchestrationStep Order="4" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />
    </OrchestrationSteps>
</UserJourney>

UserJourneyRecorder output showing the updated claims in the state bag:

{
  "Kind": "Action",
  "Content": "Web.TPEngine.StateMachineHandlers.TokenExchangeHandler"
},
{
  "Kind": "HandlerResult",
  "Content": {
    "Result": true,
    "Statebag": {
      "Complex-CLMS": {
        "objectId": "...",
        "refreshTokenIssuedOnDateTime": "7/2/2021 2:59:13 AM",
        "refreshTokensValidFromDateTime": "2021-06-08T07:16:24Z",
        "isVerified": "False",
        "role": "broker",
        "companyId": "...",
        "tenantId": "..."
      },
      "CT": {
        "c": "2021-07-02T03:02:09.7703777Z",
        "k": "CT",
        "v": "Spa",
        "p": true
      },
      "ComplexItems": "_MachineEventQ, TCTX, EX_T, REPRM, AUPRM, PRMCH"
    }
  }
}
1
This requirement is still something that is not fully implemented by B2C. You can find a partial solution here: github.com/azure-ad-b2c/samples/issues/230Jas Suri - MSFT
Thanks. Adding Endpoints seems to have resolved my particular issue.darnmason

1 Answers

0
votes

Thanks to Jas and his example on this GitHub issue I added Endpoints to my Relying Party file with my RefreshToken User Journey and this has resolved my issue.

I now see the latest claims in the ID Token returned from a token refresh.

<RelyingParty> 
  <DefaultUserJourney ReferenceId="SignUpOrSignIn" /> 
    <Endpoints> 
      <Endpoint Id="Token" UserJourneyReferenceId="RefreshToken" /> 
    </Endpoints>
    ...    
</RelyingParty>