2

I have a custom sign-in policy that calls a custom REST API that fetches some information about the user from my database.

That information needs to be updated every once in a while, but I can afford to update it once an hour.

The problem is, that we don't prompt the user to login every hour. Instead, we refresh the token silently every hour with acquireTokenSilent

I need to somehow intercept the acquireTokenSilent, to make it call my custom REST API and pull the additional claims, just like I do it in the custom sign-in policy.

Is there a way to do it?

user10962730
  • 979
  • 1
  • 7
  • 15

2 Answers2

2

The Configure the resource owner password credentials flow in Azure Active Directory B2C using a custom policy article describes how you can implement a user journey for the token refresh.

Specifically:

  1. This user journey is referred to from the RefreshTokenUserJourneyId metaproperty of the JwtIssuer technical profile.
<ClaimsProvider>
  <DisplayName>Token Issuer</DisplayName>
  <TechnicalProfiles>
    <TechnicalProfile Id="JwtIssuer">
      <Metadata>
        <!-- Point to the redeem refresh token user journey-->
        <Item Key="RefreshTokenUserJourneyId">ResourceOwnerPasswordCredentials-RedeemRefreshToken</Item>
      </Metadata>
    </TechnicalProfile>
  </TechnicalProfiles>
</ClaimsProvider>
  1. The ResourceOwnerPasswordCredentials-RedeemRefreshToken user journey checks whether the refresh token has been invalidated.
<UserJourney Id="ResourceOwnerPasswordCredentials-RedeemRefreshToken">
  <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="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />
  </OrchestrationSteps>
</UserJourney>

You can add your API call to this user journey.

Chris Padgett
  • 14,186
  • 1
  • 15
  • 28
  • 1
    I tried this but adding additional claims in here do not refresh claims passed in access token. Did you had any luck testing this ? Also looked at your other answer without any luck - > https://stackoverflow.com/a/49603509/1371639 – Karthik Sep 10 '19 at 02:44
  • Anyone got this to work? I have the same problem as @Karthik... no update claims in access token after REST call added to journey. Like adding a break point shows it fires, just token doesn't have the changes. – Tim Harker Jul 09 '20 at 06:03
  • 2
    @TimHarker - When I did this last year - There is no way we can refresh claims with the out-of-box B2C setup. You need to raise a request with Microsoft to enable this feature for your Azure AD Tenant (they do some magic in the backend for you). – Karthik Jul 15 '20 at 10:34
  • Any updates on this? I've implemented it and experiencing the same behaviour. When I perform a token refresh I can see it hits my REST endpoint and the UserJourneyRecorder shows the updated claim value, however the id_token returned to the client still reflects the old value. – darnmason Jul 02 '21 at 03:10
1

Check @Chris Padgett answer

One way you can achieve like,

  1. Put a timer to make a web API call (I guess you already have one to raise silent renew request)
  2. Make a [Authorize] rest API call from JS by sending user access token
  3. Make a DB Call to pull the details from rest API and save them in your SPA app local variables.
Ramakrishna
  • 4,928
  • 3
  • 20
  • 24
  • 1. Actually, I call `acquireTokenSilent` prior to every request. The method automatically refreshes the token if it's expired. 2. If I store the additional claim in the client, then the server would have to verify them every request, that's what I want to avoid by storing them inside the token. – user10962730 Jul 04 '19 at 13:20