For browser extensions, I would recommend keeping everything auth related in the background script. This also refers to the storage of access and/or refresh tokens. Storing tokens, especially refresh tokens, using the Web Storage API is most likely not the “safest” option but the only one I’m aware of that allows users to be logged in for longer period of times (assuming that the access tokens expire fairly quickly). Luckily, Auth0 introduced rotating refresh tokens which should resolve some of the concerns in regards to refresh tokens and storage.
So, if the content script needs to get data from a protected ressource, i.e. your backend API, it has to send a message to the background script. The background script can then send the request to your API (using the stored access token which it needs to periodically update using the refresh token) and send the data back to the content script.
In your backend script, you can’t use the Auth0 SDK as it won’t work (as you’ve mentioned). Instead, you need to write the authorization code grant (PKCE, as you don’t want to expose the client secret) logic yourself. Luckily, browser extensions offer the launchWebAuthFlow method which simplify most of the complexity. You can also use the getRedirectURL method to automatically get the unique extension URL (which you also need to store in your Auth0 SPA settings) in your background script. To implement the PKCE challenge you can either write that logic yourself (the math is fairly simple) or use PKCE libraries on NPM.