#TokenRefreshException

3 messages · Page 1 of 1 (latest)

tiny sable
#

I am doing something slightly unorthodox, but I am having trouble understanding the behavior that I am seeing.

I am using amplify with react-native. We have created an iOS Live Activity that can be started and updated remotely (without needing to open our app). The Live Activity needs to be able to make API calls to our API.

We setup the live activity when the user opens the app for the first time. I am passing the refresh token to native swift code using react-native-keychain.

The refresh token is not available via any amplify APIs, so we pull it from AsyncStorage and do someting like this:

const authSession = await fetchAuthSession();
    const key = `@MemoryStorage:CognitoIdentityServiceProvider.${authSession.tokens?.accessToken.payload.client_id}.${authSession.tokens?.accessToken.payload.username}.refreshToken`;
    const refreshToken = await AsyncStorage.getItem(key);
    await Keychain.setInternetCredentials(
      'refreshToken',
      'refreshToken',
      refreshToken
    );

This all works fine. However, since we have started doing this, every now and again, rare, and seemingly random, I get this error when opening the app:

TokenRefreshException: Token refresh is not supported when authenticated with the 'implicit grant' (token) oauth flow. Please change your oauth configuration to use 'code grant' flow.

We ARE using the code grant flow. I dug into the amplify source to understand why this error would happen. It seems that if it is able to find an access token, but not a refresh token, this exception is thrown.

Why would it, seemingly randomly, not be able to find the refresh token? This feels like some sort of race condition to me. I thought that maybe when I am pulling the refreshToken out of AsyncStorage that maybe Amplify can't.

However, as far as I can tell, there is no lock on this data. I tested a Promise.all call to that same key with 15+ calls and they all return the refresh token.

Any idea why this would happen?

tiny sable
#

the race condition is not with asyncstorage but with the fetchAuthSession call