springspring-bootsecuritycookiesjwt

Securing JWT client side in cookies


I am developing a rest api in spring boot, in which i've integrated keycloak for handling user authentication and authorization. What happens is:

  1. When I want to use the rest service, I retrieve the token via keycloak and use it to contact the spring api
  2. When I want to manage authentication via frontend web app, I pass user credentials in https to spring boot login endpoint, which contacts keycloak and generates the token. I return this token in cookies along with the refresh token.

On the frontend application side, I make subsequent calls by exchanging cookies with the server (http-only, secure, samesite, etc). So the token is saved in the cookies and the cookie expiration follows the token expiration. Each request to spring boot validates the token backend-side.

In this case, the access token and the refresh token are stored in two cookies, in clear text in the user's browser, so an attacker can read and reuse the token while it is still valid... perhaps.

What is the best practice for hardening security in this regard? Does it make sense to return an encrypted token with a private key from the back end? What are the best practices to make the token, which is currently stored in clear text in browser cookies, even more secure?

Thank you


Solution

  • When I want to manage authentication via frontend web app, I pass user credentials in https to spring boot login endpoint

    This looks like the OAuth2 password flow which was deprecated long ago and is removed from OAuth 2.1 for security reasons

    What is the best practice for hardening security in this regard?

    1. neither your frontend nor an OAuth2 client should ever have access to user credentials. Only the authorization server should. In other words, do not use the password flow. To authenticate users on a device with decent input capbilities, use the authorization code flow.
    2. do not send tokens to the user device. Tokens should remain on the server. Use sessions (http-only, secure, and same-site cookies) with protection against CSRF (cookie-based in case of a SPA), and apply the OAuth2 BFF pattern: a middleware on the backend that stores tokens in session and replaces the session cookie with an access token when routing a request from the frontend to a resource server. I wrote an article on Baeldung to do that with Spring Cloud Gateway. When the frontend is React app with Next.js, an alternative is using the NextAuth lib (based on a confidential client running in a node instance on the server).