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

Uncaught (in promise) TypeError: Cannot read properties of null (reading 'refreshToken')

Open Zhuohui-Li opened this issue 2 years ago • 20 comments

Issue and Steps to Reproduce

it happens after a long idle randomly. Still not sure how to reproduce it.

Versions

6.13.4

Screenshots

image

Expected

When that error happens, go to the session lost page or the auth error page

Actual

Throw the error and the page crashes.

Additional Details

  • Installed packages: React

Zhuohui-Li avatar Feb 05 '23 01:02 Zhuohui-Li

Hi @Zhuohui-Li ,

Do you have a sample of your configuration ? May you update to the latest version? Lastest version fixed a similar bug.

guillaume-chervet avatar Feb 05 '23 06:02 guillaume-chervet

Hi @guillaume-chervet The config is

    client_id: 
    redirect_uri:
    scope: 
    authority: 
    refresh_time_before_tokens_expiration_in_second: 10,
    service_worker_only: false, 
    storage: localStorage,
    authority_configuration: {
   
    },

Zhuohui-Li avatar Feb 05 '23 23:02 Zhuohui-Li

@guillaume-chervet Some error info:

oidc:config_name:refreshTokensAsync_silent_error: {
    "message": "bad request",
    "tokenResponse": {
        "success": false,
        "status": 400
    }
}
oidc:config_name:refreshTokensAsync_error: {
    "message": "refresh token"
}

It happens in the latest version also after a really long idle (like overnight)

Zhuohui-Li avatar Feb 05 '23 23:02 Zhuohui-Li

Hi @Zhuohui-Li , do you know the lifetime of your refresh token? And the lifetime of ypu cookie session with your oidc server?

guillaume-chervet avatar Feb 08 '23 21:02 guillaume-chervet

Hello, we are experiencing similar issues, it is characterized by it trying to call fetch POST to the /token endpoint repeatedly and getting a error 400, then it throws an error along the lines of the title of the issue. It mainly appears within seconds / minutes of opening a tab, but sometimes also when they reenter a tab after several hours. (error message from various browsers: firefox: TypeError: c is null, chrome / edge / opera: Cannot read properties of null (reading 'refreshToken'), safari: null is not an object (evaluating 'c.refreshToken'))

Our oidc configuration is as follows:

        // Access Token Life : 30 minutes
        AccessToken: 30 * 60,
        // Refresh Token Life : 1 Week Refresh Token
        RefreshToken: 60 * 60 * 24 * 7,
        // ID Token Life : 15 minutes
        IdToken: 15 * 60,
        // Session Life 6 months
        Session: 60 * 60 * 24 * 30 * 6,
      },

Our client (this package) configuration is as follows:

export const DEFAULT_CONFIGURATION: OidcConfiguration = {
  client_id: process.env['NEXT_PUBLIC_OIDC_CLIENT_ID'] ?? '',
  redirect_uri: process.env['NEXT_PUBLIC_OIDC_REDIRECT_URL'] ?? '',
  // we forcibly add openid & profile in our wrapper, but we have offline_access in every project
  scope: process.env['NEXT_PUBLIC_OIDC_SCOPES'] ?? '', 
  authority: process.env['NEXT_PUBLIC_OIDC_AUTHORITY'] ?? 'https://boop.fynn.ai/oidc',
  service_worker_only: false,
  storage: window.localStorage
} as const;

We are using nextjs, but the OidcProvider is only activated once window != undefined (e.g. in the browser) because otherwise we get problems with using localStorage, and I believe nothing from the library is used before useOidc().isAuthenticated == true and useOidcUser().oidcUserLoadingState == OidcUserStatus.Loaded (we are using a small wrapper around the library).

TheChristophe avatar Feb 10 '23 20:02 TheChristophe

Hi @TheChristophe thank you very much for all your information. It will help a lot. Which version are you using?

guillaume-chervet avatar Feb 10 '23 20:02 guillaume-chervet

We are currently on 6.14.2, and I believe it also happened on an older version before

TheChristophe avatar Feb 10 '23 20:02 TheChristophe

You can already set up token_renew_mode: PropTypes.string, // Optional, update tokens base on the selected token(s) lifetime: "access_token_or_id_token_invalid" (default), "access_token_invalid" , "id_token_invalid" Property to acceaccess_token_invalid, I think it will help to reduce token updates for your case. I have to reproduce your case.

guillaume-chervet avatar Feb 10 '23 20:02 guillaume-chervet

Thank you @TheChristophe for the version :)

guillaume-chervet avatar Feb 10 '23 20:02 guillaume-chervet

I will try the access_token_invalid and keep an eye on whether we're still seeing it pop up, thanks

TheChristophe avatar Feb 10 '23 20:02 TheChristophe

By random chance I've managed to reproduce the error in a staging environment too, in case this is useful: image It does not seem to crash or break the application in production at least, it just goes to the login screen on our application

The flow seems to be:

  • the tokens are attempted to be requested here https://github.com/AxaGuilDEv/react-oidc/blob/master/packages/react/src/oidc/vanilla/oidc.ts#L449, but it fails (5 times) because {"error":"invalid_grant","error_description":"grant request is invalid"}
  • (...)
  • it fails here https://github.com/AxaGuilDEv/react-oidc/blob/master/packages/react/src/oidc/vanilla/renewTokens.ts#L24 (tokens = null)

Because we use the same client ID in staging and local development I could copy the localStorage entry to reproduce the error on my local machine, I don't know what the issue is, but at least I found that if I change this https://github.com/AxaGuilDEv/react-oidc/blob/master/packages/react/src/oidc/vanilla/renewTokens.ts#L18

    if (!oidc.tokens) {
       await oidc.destroyAsync(status);
       return;
   }

to

    if (!tokens || !oidc.tokens) {
        await oidc.destroyAsync(status);
        return;
    }

the error stops appearing

TheChristophe avatar Feb 10 '23 23:02 TheChristophe

Hi @guillaume-chervet I tried to connect with my auth provider team but no response yet. Here's my guess to reproduce it. During a long idle, the refresh token in the storage is expired. After the system wakes up it sends the expired refresh token to auth provider endpoint and then get a 400 error without any return value. After that the react-oidc library tries to read refreshToken from undefined and therefore throws the error.

Zhuohui-Li avatar Feb 14 '23 07:02 Zhuohui-Li

Thank you @Zhuohui-Li , I sorry was busy.

I have an idea, I make some tests right now !

guillaume-chervet avatar Feb 14 '23 10:02 guillaume-chervet

Hello,

I have the same problem when I stay idle too long (with version 6.14.3).

And once I refresh the page the problem is still here and I am stuck, the only way I can go the login page again is to stop the service worker by hand with the Chrome tools (maybe an error on my side for this part ?)

leonoredesplas avatar Feb 14 '23 16:02 leonoredesplas

I think version 6.14.4 just publish fixed the bug. But I'am not sure.

guillaume-chervet avatar Feb 14 '23 17:02 guillaume-chervet

Hello,

It worked for me, thank you very much !

leonoredesplas avatar Feb 15 '23 08:02 leonoredesplas

Hi @guillaume-chervet It works well. Thanks a lot.

Zhuohui-Li avatar Feb 15 '23 20:02 Zhuohui-Li

Thank you a lot for your feedbacks @Zhuohui-Li and @TheChristophe and @leonoredesplas

guillaume-chervet avatar Feb 15 '23 21:02 guillaume-chervet

I'm still observing the issue in production after updating, I'm wondering if my issue is different (or people are accidentally still loading the old page). I'll keep an eye on it in the following days

TheChristophe avatar Feb 16 '23 01:02 TheChristophe

Hi @TheChristophe , thank you for your feedback, i will make more tests with next and localStorage

guillaume-chervet avatar Feb 16 '23 08:02 guillaume-chervet