oidc-client
oidc-client copied to clipboard
useOidcAccessToken behavior is patchy, gives expired token after refresh token routine
Issue and Steps to Reproduce
We cannot deterministically rely on the hook - useOidcAccessToken. For the first time we get a correct token but after token refresh we get the previous token that has expired. If we fetch the accessToken from localStorage where idc lib stores it, we get a good token. Most of the issues seen in this area are around after token refresh.
Steps:
- Login and check accessToken(will be good one)
- Wait for refresh token to trigger and useOidcAccessToken() to trigger the rerender
- mostly you will find token is older one.
Versions
exists in latest (v6.10.18) as well
Screenshots
Expected
hooks should deterministically provide latest and greatest accessToken
Actual
After first refresh most of the time the token received is previous one (expired)
Additional Details
- Installed packages:
Thank you @rbalyan for the issue. I look a it today!
Hi @rbalyan , i did not sucess to reproduce the problem. Dobyou have a sample of your configuration ?
Hi @guillaume-chervet I have the same issue The config is (without serviceWorker)
client_id:
redirect_uri:
scope:
authority:
refresh_time_before_tokens_expiration_in_second: 10,
service_worker_only: false,
storage: localStorage,
authority_configuration: {
},
The example code
export const PingIDContext = React.createContext();
export const PingIdProvider = ({ children, envData }) => {
const { login, logout, isAuthenticated } = useOidc("configName");
const { oidcUser, oidcUserLoadingState } = useOidcUser("configName");
const oidcAccessTokenState = useOidcAccessToken("configName");
const decorateToken = useCallback(() => {
const { accessToken, accessTokenPayload } = oidcAccessTokenState; // the accessToken here is always the previous one
// use the accessToken to do other stuffs
}, [oidcAccessTokenState]);
// sync token on load
useEffect(() => {
if (!isLoaded) {
decorateToken();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
};
PingIdProvider.propTypes = {
children: PropTypes.element.isRequired,
envData: PropTypes.shape({
//...
}).isRequired,
};
Thanks a lot
my impression is that somehow the state of the hook changes before the actual token is updated in the token state. some timing issue. Zhuohui has provided a reasonable code snippet here, only thing I would add is that in the decorateToken function if you try to validate expiry of token then you will see it is expired most of the times and will exactly match ti the token that just expired
Hi @guillaume-chervet
This issue happens if I try to read id_token like
const { idTokenPayload } = useOidcIdToken(configName);
If I remove this line, I can get the right access token
Thank you @Zhuohui-Li @rbalyan your feedback help are very helpful !
hi @rbalyan, @Zhuohui-Li, I do not success to reproduce it => https://github.com/AxaGuilDEv/react-oidc/pull/913/files Which OIDC server are your using?
here the published demo by the pullrequest => https://black-rock-0dc6b0d03-913.westeurope.1.azurestaticapps.net/
Hi @guillaume-chervet Thanks a lot. I didn't get you but we are using PingId as our auth provider
Hi @guillaume-chervet
The token comes from token.oauth2
The response from auth provider is
{
access_token: ""
expires_in: 899
refresh_token: ""
token_type: "Bearer"
}
Is it because that the id token is not in the response?
Thank you @Zhuohui-Li , I think it is the information I needed :)
I @Zhuohui-Li , I removed openid scope from my demo so I have only the access_token now in the demo.
https://github.com/AxaGuilDEv/react-oidc/pull/913/files but I still cannot reproduce your bug:
https://black-rock-0dc6b0d03-913.westeurope.1.azurestaticapps.net/
DO you have any idea that can help ?
Hi @guillaume-chervet
The only difference I can find is I wrapper the hook in the react context.
Also, could you check whether the access token from const { accessToken } = oidcAccessTokenState;
in line 13 is same as the access token in the local storage? Ideally they should have same exp
Thanks a lot
react version could be at play here too, just a thought
Which react version are you using @rbalyan ?
Hi @guillaume-chervet [email protected]
if it helps