How to secure a refresh token?
Basically, it seems like a bad idea to use refresh tokens with browser based apps. Refresh tokens are meant for mobile apps where the refresh token can be stored securely on the phone - phones have some sort of secure storage mechanism, whereas browsers do not.
There is a good document OAuth 2.0 for Browser-Based Apps which discusses best practices for these applications.
I would choose between keeping tokens on client or server. Mixing it (keeping refresh tokens on your server and access tokens in browser), you create your own protocol with its own vulnerabilities.
If the browser application needs the access token just to access its backend, you could consider using your backend as an OAuth2 client (which receives an auth code), get the user's indentity, issue a cookie which will maintain a session between the browser and the backend. It's much easier than exchanging, refreshing and validating OAuth2 tokens.
If you really want to keep your browser application as an OAuth2 client which receives tokens, you should use PKCE extension (so the auth code kept in network caches and browser history cannot be used to get tokens) and get a new refresh token with each new access token - take a look at the chapter about refresh tokens:
Authorization servers SHOULD NOT issue refresh tokens to browser-based applications.
If an authorization server does choose to issue refresh tokens to browser-based applications, then it MUST issue a new refresh token with every access token refresh response. Doing this mitigates the risk of a leaked refresh token, as a leaked refresh token can be detected if both the attacker and the legitimate client attempt to use the same refresh token.
Your browser application can keep its tokens in sessionStorage
to survive page reloads.