Search code examples
node.jsjwtcsrf

JWT and CSRF Token Workflows


I have an architecture which involves two microservices. The workflow is as follows:

  • User accesses a URL (localhost:8090) and gets registerd in the database through microservice 1
  • After registration the user is redirected to service 2 which runs on localhost:3000

Now, given my limited knowledge about CSRF and JWT tokens, I currently use the below code for redirection

res.setCookie('jwt_signed', token, ...);
res.redirect('localhost:3000');

and then in service 2, I decode and verify the signed token to check the integrity of the data passed. Additionally, I also see a CSRF token that is passed in the cookies.

Now, what I'm confused about is that since I am redirecting to service 2 for any further actions, how will the CSRF token be useful from a security POV? And is it a security good practice to send a JWT Signed token in the cookie?

Also, would it be a good idea to add the CSRF token to the JWT Signed token?


Solution

  • Initial Questions

    Let me answer your questions 1 by 1.

    CSRF (cross site request forgery) token is useful because it means that no one can hijack your session and submit a form (or send a request) to a website from another tab (using your session). It works by generating a token every time a form is loaded, and then when this form is submitted the token needs to match.

    See: https://portswigger.net/web-security/csrf AND https://owasp.org/www-community/attacks/csrf

    1. I don't think it's good practice to send anything critical inside a cookie. You should instead set it to the request header. Cookies are very easily stolen and copied. If someone copies the cookie they can authenticate. Also, JWT header will be secure when used on conjunction with https so that you also have encryption.

    e.g. req.session.myToken = jwt.sign(insideToken, "password");

    1. You could put the CSRF token inside the JWT token. It wouldn't necessarily hurt and it would make your JWT header more random for every request.

    In addition to JWT inside request header, I strongly recommend HTTPS. Otherwise a man in the middle attack using a sniffer will easily defeat your security.

    Update

    A great article explaining CSRF is the following : https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html

    You can generate the tokens server-side and you don't need to necessarily have forms. You can put them on the session. Do note:

    Per-request tokens are more secure than per-session tokens as the time range for an attacker to exploit the stolen tokens is minimal. ... When a request is issued by the client, the server-side component must verify the existence and validity of the token in the request compared to the token found in the user session. If the token was not found within the request, or the value provided does not match the value within the user session, then the request should be aborted, session of the user terminated and the event logged as a potential CSRF attack in progress.

    CSRF tokens should be:

    Unique per user session. Secret Unpredictable (large random value generated by a secure method). CSRF tokens prevent CSRF because without token, attacker cannot create a valid requests to the backend server.

    CSRF tokens should not be transmitted using cookies.

    The CSRF token can be added through hidden fields, headers, and can be used with forms, and AJAX calls. Make sure that the token is not leaked in the server logs, or in the URL. CSRF tokens in GET requests are potentially leaked at several locations, such as the browser history, log files, network appliances that log the first line of an HTTP request, and Referer headers if the protected site links to an external site.

    Source: https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html

    There's a lot more interesting information inside that article that is useful