oidc-client-js icon indicating copy to clipboard operation
oidc-client-js copied to clipboard

Silent renew with refresh token doesn't update user but silent renew via iframe does

Open GordonBlahut opened this issue 5 years ago • 10 comments

When doing a silent renew via iframe (e.g. in a browser with no offine_access scope), the user manager calls the userinfo endpoint and updates the user profile/claims.

But when doing a silent renew via refresh_token (e.g. in a native/hybrid app with offline_access scope) does not seem to call the userinfo endpoint and therefore the user profile/claim does not get updated.

How can I get silent renew via refresh_token to also update the user profile/claims just like a silent renew via iframe? I want to keep the user info current.

In both cases I am using the same authorization code flow with PKCE.

I saw some other issues related to updating user after a silent renew but not specifically about differences caused by renewal method.

GordonBlahut avatar Jan 09 '20 19:01 GordonBlahut

Is there a method to manually refresh the user profile/claims and update the user that is tracked by the UserManager?

GordonBlahut avatar Feb 07 '20 15:02 GordonBlahut

Is there a method to manually refresh the user profile/claims and update the user that is tracked by the UserManager?

Nothing built-in as a public API. What's your scenario?

brockallen avatar Feb 07 '20 18:02 brockallen

What's your scenario?

Client is a Vue/vuex-based SPA with both a web browser version and Cordova Android/iOS version. Both versions are using oidc-client as the client and IdentityServer4 on the server but with different configurations (the Android/iOS clients have offline_access scope).

The browser version uses typical redirect oauth config and iframe for silent renew. The Cordova version launches a custom tab or ASWebAuthenticationSession to authenticate via browser and uses a refresh_token to renew so that the browser doesn't pop up unexpectedly as the auth_token nears expiration.

If the user changes something in their profile that is included as a claim (like first name), it will be automatically updated in the browser app the next time a silent renew is triggered, but the Cordova app never gets updated claims on silent renewals so the experience is inconsistent and the user would have to sign out and sign back in to see the profile changes.

Certain actions the user takes may affect claims, so on the browser version I can immediately issue a silent renewal and the claims will be updated, but the Cordova version will not.

I'm not worried about claims being 100% up to date as that's not really feasible when the user has multiple active clients. But since the auth token is relatively short-lived, they will always be recent enough in the browser version, plus I could add a "refresh profile" button in the web version that simply triggers a silent renew. Not so much in the Cordova version.

I could always call the userinfo endpoint and manage the claims myself, but then I'm deviating from the UserManager and maintaining duplicate sets of claims, which does not seem ideal.

GordonBlahut avatar Feb 07 '20 19:02 GordonBlahut

Ok yea, I think there's already another issue open related to this -- in short, once the RT comes back with a new AT we don't use that to trigger a new request to userinfo.

brockallen avatar Feb 12 '20 22:02 brockallen

once the RT comes back with a new AT we don't use that to trigger a new request to userinfo

Is this by design? Is there a reason for the different behaviour compared to silent renew via iframe?

GordonBlahut avatar Apr 15 '20 18:04 GordonBlahut

Not sure if I recall why... I can look back into it again

brockallen avatar Jul 21 '20 22:07 brockallen

Any update on this @brockallen ? I face same issue too.

adityaputral avatar Sep 07 '20 06:09 adityaputral

We're getting the UserInfoService from the UserManager._validator._userInfoService and then doing the following:

    const claims = await userInfoService.getClaims(accessToken);
    const oidcUser = await manager.getUser();
    if (oidcUser != null) {
      Object.assign(oidcUser.profile, claims);
      await manager.storeUser(oidcUser);
    }

StummeJ avatar Sep 16 '20 22:09 StummeJ

@brockallen any update on this?

dHihich avatar Sep 18 '20 12:09 dHihich

Got a similar problem with my configuration:

...requiredConf,
response_type: 'code',
scope: 'openid profile',
loadUserInfo: true

signinSilent and getUser doesn't invoke userInfo service.

vukadinFE avatar Dec 30 '20 08:12 vukadinFE