You never store refresh tokens in a frontend. You can store access tokens (short-lived) in the frontend but you should never store refresh-tokens.
Instead of using refresh tokens, they have a "silent authentication" mechanism[1]. The idea is: sometime before the user's initial token expires, your app goes through the silent-auth process in an invisible iframe. Assuming the user's authentication credentials are still valid, the invisible iframe will eventually use the browsers postMessage() functionality to deliver a new token to the main app's frame, your app then quietly starts using this new token that has a new cryptoperiod.
The silent-auth mechanism doesn't use any different inputs than a normal Auth0 SSO login. Your app is constantly re-authenticating until the user is not allowed to login any more. This allows you to set short expiration times with no interruption of the user at all.
[1] - https://auth0.com/docs/api-auth/tutorials/silent-authenticat...
(Id argue that JWT is the wrong tool to use in a react front end - store that in the orchestration and implement some strong session management betweem FE and orch through an access gateway)
Alternatively, don't use access token / refresh token but an ID token. The refresh of the token will be done via the ID token and the user's session (cookie) to the OAuth provider.
The JWT server would check to see that the refresh token probably stored in the browser with a cookie or localStorage is valid before sending the new JWT.
Or, like with Oauth2, is the idea that JWT gets transmitted back to the server with every request, and the refresh token only when needed and therefore having a slightly smaller risk of intercepting both keys (assuming the refresh token is not stored in cookies)?