I recommend fail2ban:
> Fail2ban scans log files (e.g. /var/log/apache/error_log) and bans IPs that show the malicious signs -- too many password failures, seeking for exploits, etc.
We find it a very powerful way of reducing the volume of unwanted traffic to both Apache and Postfix.
Did you import burp's root certificate so that it's trusted as a CA? Essentially, for BURP to work with TLS, it needs to man-in-the-middle your browser traffic and for this to work properly, your browser needs to trust Burp's certificate as a CA cert. https://portswigger.net/burp/documentation/desktop/tools/proxy/options/installing-ca-certificate <-- has more details and instructions.
> After some reading it seems like csrf is still possible in this scenario
As long as you are not using HTTP Cookies you should not have CSRF problems. Additionally, CSRF attacks only work on "simple requests", so if your HTTP requests triggers a CORS-Preflight check then you're safe. (https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Preflighted_requests)
As for the implicit flow, it's a bit tricky to do this properly from a SPA because in theory you can't store things like a refresh token. If you haven't, I recommend reading up on Auth0 (https://auth0.com/docs/api-auth/grant/implicit) and how they recommend to do it.
From my side I'm also looking at this scenario/problem, specifically to adopt "refresh tokens" and have short lived auth tokens. We have a similar setup on what you described, only we put the JWT in a HTTP Cookie (with HttpOnly), to prevent JS code from reading from it (XSS attacks). At the moment the JWT is long lived but I'm looking into making it short lived and therefore using some sort of refreshing mechanism.
After doing some research, I found these reads helpful: