Access Tokens (AT) and Refresh Tokens (RT) should still both be used. ATs should be short in duration no matter what. They are the keys to your house and shouldn't be exposed for long.
Adding to Anders UX discussion, something like the following could be considered which would present better security:
Remember me is checked
Have a sliding RT expiration time, with a lengthy lifetime (a month). If a user keeps accessing your application, the sliding mechanism keeps pushing it a month. If you feel like at some point you need for the user to re-authenticate, you can set an absolute time (a year).
AT and RT (it should be linked to a specific path, e.g. /refresh
) should both be stored as cookies with the upmost levels of security, by implementing cookie prefixes (e.g. __HOST-
), attributes (Secure, HttpOnly, SameSite) to avoid HTTP leakage, XSS attacks, and CSRF. XSS still has one way to achieve an attack which is by simply creating an XHR and sending it to the attacker with credentials. CSP could help with locking data exfiltration attacks if properly implemented.
By using other web storage mechanisms, you're opening up the attack surface. Cookies are the main spot where security controls are being added over the years.
Remember me is NOT checked
Instead of having the RT with a lifetime of a month, it could have it for a couple of hours. The AT should still be as small as possible. To remove the RT on browser closing, create Session Cookies.
Using cookies allows you to destroy them on demand by setting the Expiry to an earlier date, so that helps as well on that end.
I mainly focused on cookies, but any other type of storage could be used with the same logic in mind. I am biased to using cookies for anything related to AuthN-Z.