VOOZH about

URL: https://blog.logrocket.com/security-for-fullstack-web-developers-part-3-aaf81da57acb/

⇱ Security for full-stack web developers :  Part 3 - LogRocket Blog


2017-10-03
1113
#full stack
Robin Percy
556
👁 Image

See how LogRocket's Galileo AI surfaces the most severe issues for you

No signup required

Check it out
👁 Image

In this article, I’d like to look into the elements of web app security that are often the most dangerous — those involving users and sessions. From a backend perspective, users & authentication are two of the deepest attributes to our web app, but I’d like to look at those attributes from a frontend perspective. Although dealing with issues like user credential security are incredibly important, often we tend to overlook to the importance of frontend user & session security issues such as cookie theft and cross-site request forgery (CSRF).

Let’s start by discussing exactly what it is and how I believe we can entirely mitigate it in a modern web application.

Cross-site request forgery (CSRF)

Cross-site request forgery has been at the forefront of web app security for longer than any of us care to remember. How does it work? Essentially, a malicious agent sends a (forged) request from one app to another while the user is signed in and authorized. The malicious agent enters and alters restricted actions on the requested app, with the requested app believing entirely that the alterations are legitimate.

Let me show you.

Imagine, if you will, that I am security-abusing miscreant. Imagine, also, that I happen to know that Twitter has no CSRF protection. (It does, this is merely an exercise. Don’t get any ideas.) I’m also aware that most people who visit my web app probably leave their Twitter logged in. That means they have a cookie stored in their browser.

On my web app, I could embed something like this:

<form action="https://twitter.com/tweet" method="POST" id="sendTweet">
<input type="hidden" name="tweet" value="Hey! Check out my awesome spam site - spam.com">

When a browser loads my web app, it will also load this form (entirely invisibly. I would then also have embedded a small piece of JS to POST the form without you ever knowing:

document.getElementById("sendTweet").submit();

Cool. I’ve just sent a tweet on your account, without ever having to know your username or password. The cookie you had stored in your browser allowed my app to send a forged request, pretending to be you — and if Twitter had no CSRF mitigation, it would have worked too!

Perhaps a better way to relate this back to your own web app would be to use the scenario in which, like most of us, you probably have a route setup for your own users to alter their user profile. /user/profile is probably the most common example, and given that most security-abusing miscreants know this (myself included), it would be trivial to send a POST request to your web app, updating the user’s profile with a new email address.

While this may not seem like an obvious problem, once the user’s email address is changed, I could then issue a password reset for that user account. The new password, of course, goes to whatever email address I dropped in the user profile. At this point, the user account is completely compromised. Any sensitive data is now in my hands and, lest we forget, I’m a miscreant. Scary stuff.

For years, we have been trying to solve CSRF requests by checking HTTP headers such as the Origin and Referer. Whilst these have offered fairly robust protection for a few years, there is now a simple directive that, once applied, will entirely mitigate CSRF attacks.

Enter the SameSite cookie directive. SameSite is relatively new and remains widely unknown. In essence, the SameSite directive, once applied, will tell the browser to never send that cookie when a request from an external (cross-site) URL is made. We can apply this directive by altering our cookies as such:

Set-Cookie: sess=sessionid123; path=/; SameSite

It really is that easy. I wouldn’t recommended removing your existing CSRF protection just yet, but I would definitely recommend including this directive on your web app.


🚀 Sign up for The Replay newsletter

The Replay is a weekly newsletter for dev and engineering leaders.

Delivered once a week, it's your curated guide to the most important conversations around frontend dev, emerging AI tools, and the state of modern software.

Over 200k developers use LogRocket to create better digital experiences

👁 Image
Learn more →

Cookies

As I mentioned in the intro, my first article in this series talked about a couple of cookie directives — namely HTTPOnly and Secure . As we know, cookies are an important feature of our web applications, carrying data mainly referring to our user sessions. While simply implementing the aforementioned directives is sufficient in securing your cookies, and preventing attacks, we can actually take cookie security a step further.

Cookie prefixing is a relatively underused technique that we can utilize to ensure a cookie is secure:

The __Secure prefix – If a cookie’s name begins with “__Secure”, the cookie MUST be:

  • Set with a “ Secure ” attribute
  • Set from a URL whose scheme is considered secure by the user
    agent

The following cookie would be rejected when set from any origin, as the “Secure” flag is not set:

Set-Cookie: __Secure-sess=12345; Domain=myapp.com

While the following would be accepted if set from a secure origin e.g. https:// and rejected otherwise:

Set-Cookie: __Secure-sess=12345; Secure; Domain=myapp.com

Alongside the __Secure prefix, we also have the __Host prefix:

The __Host prefix – If a cookie’s name begins with “__Host”, the cookie MUST be:

  • Set with a “Secure” attribute
  • Set from a URI whose “scheme” is considered “secure” by the user agent
  • Sent only to the host which set the cookie. That is, a cookie named “__Host-cookie1” set from “https://example.com ” MUST NOT contain a “Domain” attribute (and will therefore be sent only to “example.com”, and not to “subdomain.example.com”)
  • Sent to every request for a host. That is, a cookie named “__Host-cookie1” MUST contain a “Path” attribute with a value of “/”

The following cookies would always be rejected:

Set-Cookie: __Host-sess=12345
Set-Cookie: __Host-sess=12345; Secure
Set-Cookie: __Host-sess=12345; Domain=example.com
Set-Cookie: __Host-sess=12345; Domain=example.com; Path=/
Set-Cookie: __Host-sess=12345; Secure; Domain=example.com; Path=/

While the following would be accepted if set from a secure origin e.g. https:// , and rejected otherwise:

Set-Cookie: __Host-sess=12345; Secure; Path=/

By setting these prefixes, any compliant browser will be made to enforce them.

Now, if we include the tips from my first article, and the tips above, we can make the most secure cookie possible:

Set-Cookie: __Host-sess=id123; path=/; Secure; HttpOnly; SameSite

In this most-secure-cookie, we’re utilizing the __Host prefix, which means the Secure attribute has to be set, and it must be served from a secure host. There is no Domain attribute set and the Path is /. We’ve set HttpOnly for XSS protection, and SameSite is enabled to prevent CSRF. Of course, this won’t be the best or most practical solution for a lot of people, but it is the most secure cookie we could set from our web app in theory.

Get set up with LogRocket's modern error tracking in minutes:

  1. Visit https://logrocket.com/signup/ to get an app ID
  2. Install LogRocket via npm or script tag. LogRocket.init() must be called client-side, not server-side

    $ npm i --save logrocket 
    
    // Code:
    
    import LogRocket from 'logrocket'; 
    LogRocket.init('app/id');
     
    // Add to your HTML:
    
    <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script>
    <script>window.LogRocket && window.LogRocket.init('app/id');</script>
     
  3. (Optional) Install plugins for deeper integrations with your stack:
    • Redux middleware
    • NgRx middleware
    • Vuex plugin
Get started now
👁 Image
👁 Image
👁 Image

Stop guessing about your digital experience with LogRocket

Get started for free

Recent posts:

Debug Next.js apps with AI agents and next-browser

Learn how next-browser gives AI agents runtime context for debugging Next.js apps, including React props, hydration, PPR, forms, and performance.

👁 Image
Emmanuel John
Jun 17, 2026 ⋅ 9 min read

Stop hardcoding LLM SDKs: Dynamic LLM routing with OpenRouter and Next.js

Build dynamic LLM routing in Next.js with OpenRouter, TanStack AI, task classification, model fallbacks, and cost-aware routing.

👁 Image
Chizaram Ken
Jun 16, 2026 ⋅ 13 min read

What is TSRX?: What JSX would look like if it were designed today

TSRX adds first-class control flow, conditional hooks, and scoped styles to React via a TypeScript compiler extension — no new framework required.

👁 Image
Ikeh Akinyemi
Jun 12, 2026 ⋅ 6 min read

How to add authentication to a React Native app with Better Auth

Learn how to build a full React Native auth system using Better Auth and Expo — with email/password login, Google OAuth, session persistence, and protected routes.

👁 Image
Chinwike Maduabuchi
Jun 9, 2026 ⋅ 13 min read
View all posts

Would you be interested in joining LogRocket's developer community?

Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.

Sign up now