I have a full stack app with a React frontend and FastAPI (python) backend, which ultimately revolves around the user authenticating with Spotify and generating playlist data.
Since the app and the data it displays is exclusively linked to their Spotify account, I don't want to create an additional account creation + login process for my own app/website (including the database maintenance), but I need to obviously add some authentication to my application.
Here's my idea: I'm authenticating with Spotify using the OAuth2.0 Auth Code flow pattern, which is performed by my backend (the Backend For Frontend pattern). Thus the backend performs the access token exchange after authenticating... Using the token received from Spotify, can I then create an ENCRYPTED JWT token, via something like python-jose, which is composed of the user's Spotify OAuth access token and refresh token? And then pass that back and forth between my frontend and backend, validating the JWT token on the backend with each request, and decrypting the payload to receive the user's access/refresh tokens. I can then just use them to query the Spotify API and return the intended Spotify user data to my frontend.
Is this a secure solution?
Encrypting the JWT doesn't add any security over using the Spotify tokens directly in the browser, since an attacker only needs to send the encrypted JWT to get data.
A better solution is for your BFF to limit the impact of malicious JavaScript. This would involve your BFF issuing encrypted cookies rather than encrypted JWTs. Malicious JS cannot access and exfiltrate HttpOnly cookies, whereas it might be able to exfiltrate an encrypted JWT.
You might issue an AT cookie and a RT cookie, with properties like these. Encrypt cookies using a symmetric algorithm like AES256-GCM.
Your end-to-end flow then operates largely as you suggest. The solution also follows the mainstrean best practices for browser-based apps. Malicious JS might still abuse the cookie and steal data, but such attacks end when the user navigates away from the page etc.