balgamat / expo-keycloak

TypeScript + Expo + Keycloak login
24 stars 15 forks source link

Auto refresh doesn't work #1

Open nliveris opened 3 years ago

nliveris commented 3 years ago

Hi,

Thanks for your work, this library is really very useful. However there is a little problem. The autorefresh of the token does not work.

I did some investigation to solve the problem and I think I found it.

const handleTokenRefresh = useCallback(() => {
    if (!hydrated) return;
    if (!savedTokens && hydrated) { // <-- always null
      updateState(null);
      return;
    }
    if (TokenResponse.isTokenFresh(savedTokens!)) {
      updateState({ tokens: savedTokens });
    }
    if (!discovery)
      throw new Error('KC Not Initialized. - Discovery not ready.');
    AuthSession.refreshAsync(
      { refreshToken: savedTokens!.refreshToken, ...config },
      discovery!,
    )
      .catch(updateState)
      .then(updateState);
  }, [discovery, hydrated, savedTokens, updateState]);

savedToken here is alway null and I don't understand why. I first thought that the problem was related to the setTimeout callback. I tried to use a useRef but it doesn't solve the problem.

Does anyone have an idea? I am willing to do a PR if necessary.

(translated from French with an automatic translator)

rubhiauliatirta commented 3 years ago

Yes, I am facing the same problem, savedTokens always null and never reaches AuthSession.refreshAsync()

To make autorefresh work temporarily, I need to wrap it with AsyncStorage.getItem() for getting the current value. I also need to change the implementation of AuthSession.refreshAsync() resolved value because it doesn't have the property tokens.

But, I think to solve this problem we need to identify why savedTokens is null and I don't understand it either 😆

 const handleTokenRefresh = useCallback(() => {
    if (!hydrated) return;
    AsyncStorage.getItem(TOKEN_STORAGE_KEY) // or props.tokenStorageKey
      .then(result => {
        const token = JSON.parse(result)

        if (!token && hydrated) {
          updateState(null);
          return
        }
        if (TokenResponse.isTokenFresh(token)) {
          updateState({ tokens: token });
          return
        }
        if (!discovery)
          throw new Error('KC Not Initialized. - Discovery not ready.');

        return AuthSession.refreshAsync(
          { refreshToken: token.refreshToken, ...config },
          discovery,
        )
          .catch(updateState)
          .then((tokens) => { // need to wrap with object with key "tokens"
            updateState({ tokens })
          });
      })

  }, [discovery, hydrated, savedTokens, updateState]);
nliveris commented 3 years ago

hi @rubhiauliatirta and @balgamat !

Sorry for the delay of response.

I found out what was wrong. I have created a branch and a PR for the patch.

@balgamat Do you accept contributions ?

(translated from French with an automatic translator)