Search code examples
react-nativeoauth-2.0expo

What's the right way to handle access and refresh tokens with Expo AuthSession?


I have something like:

export const Step1 = () => {
  const [instanceUrl, setInstanceUrl] = useState('')
  const [request, response, promptAsync] = AuthSession.useAuthRequest(
    {
      clientId: '...',
      clientSecret: '...',
      redirectUri: 'exp://localhost:19000',
      scopes: ['read', 'write', 'follow'],
    },
    discovery
  );

  const handleLoginPress = () => {
    promptAsync()
  }

  useEffect(() => {
    const fetchAccessToken = async () => {
      const tokenResult = await AuthSession.exchangeCodeAsync({
        clientId: '...',
        clientSecret: '...',
        code: response.params.code,
        redirectUri: 'exp://localhost:19000',

      }, discovery)

      console.log({ tokenResult })
    }
    if (response.type === 'success') {
      fetchAccessToken()
    }
    console.log({ response })
  }, [response])

  return <><Dialog.Title title="Welcome" />
    <Text>Dialog body text. Add relevant information here.</Text>
    <Input placeholder="Community URL" onChangeText={(v) => setInstanceUrl(v)} />
    <Button color='secondary' disabled={!request} onPress={handleLoginPress}>Login</Button></>
}

So I can get the token result and I can store that in AsyncStorage. But how do I deal with it when it expires? What's the right way to get a refreshToken and where in my codebase would that go?


Solution

  • I'll try to address the questions one by one.

    What's the right way to get a refreshToken

    If you take a look at the result of exchangeCodeAsync, you'd see that the result is actually TokenResponse that provides config with all the metadata that includes accessToken as well as refreshToken.

    But how do I deal with it when it expires?

    It's quite simple - you just refresh it, you can either base it on the same meta information from the config, or utilize TokenResponse functions such as isTokenFresh and refreshAsync. You may also refresh in advance with some rules.

    where in my codebase would that go?

    Depends on your needs, and what this token is for. If you use it for API access, then your networking stack may be the best place to refresh it. E.g. if you're using Apollo Client, then you may create a link to do it in case you get 401 response. Additionally, you may choose to refresh it on the app start or app foreground events even before hitting 401 if you expect tokens to expire often.

    So I can get the token result and I can store that in AsyncStorage.

    AsyncStorage is def an option, additionally, you may consider things like SecureStore that expo provides as an option for storing more sensitive information.