<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Shashwat jaiswal</title>
    <description>The latest articles on DEV Community by Shashwat jaiswal (@okayhead).</description>
    <link>https://dev.to/okayhead</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1387642%2Ffea1ca29-5e11-429f-aa53-30c205d452a1.png</url>
      <title>DEV Community: Shashwat jaiswal</title>
      <link>https://dev.to/okayhead</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/okayhead"/>
    <language>en</language>
    <item>
      <title>Session based authentication in nodejs welp</title>
      <dc:creator>Shashwat jaiswal</dc:creator>
      <pubDate>Tue, 07 May 2024 08:04:00 +0000</pubDate>
      <link>https://dev.to/okayhead/session-based-authentication-in-nodejs-help-2k55</link>
      <guid>https://dev.to/okayhead/session-based-authentication-in-nodejs-help-2k55</guid>
      <description>&lt;p&gt;You need authentication in nodejs. &lt;/p&gt;

&lt;p&gt;JWT is a half-baked solution. Don't pretend it is secure because it is popular.&lt;/p&gt;

&lt;p&gt;Either way you need to learn session based authentication once and for all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;The basic MERN app setup.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a basic express app, a react frontend&lt;/li&gt;
&lt;li&gt;Connect mongodb&lt;/li&gt;
&lt;li&gt;Add routes, controllers, models et cetra&lt;/li&gt;
&lt;li&gt;Connect to mongo via atlas, host db (render.com), host your frontend (netlify).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;My cors config in server.js looks like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nf"&gt;cors&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;origin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your site&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PATCH&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DELETE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="na"&gt;allowedHeaders&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Origin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Accept&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="na"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, on the frontend, requests are sent with the credentials flag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/tasks`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;withCredentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pretty straightforward.&lt;/p&gt;

&lt;p&gt;You can view the entire repo &lt;a href="https://github.com/okay-head/task-central" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Authentication
&lt;/h2&gt;

&lt;p&gt;Spoiler.&lt;/p&gt;

&lt;p&gt;Mind f##k.&lt;/p&gt;

&lt;p&gt;For simplicity, we'll only talk about login here.&lt;/p&gt;

&lt;p&gt;Every time I login, meaning after all the validations have passed and I finally move to the code where the session for the user needs to be created and stored. I do it with this logic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="c1"&gt;// finally login and create a session&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;session_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomUUID&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;session_id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;session_id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;maxAge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;86400000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;httpOnly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;secure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;sameSite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;partitioned&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="c1"&gt;// sameSite: 'strict',&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="nf"&gt;addSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The addSession is a helper function that uses the native crypto package to register a session in the server memory.&lt;/p&gt;

&lt;p&gt;So auth is straightforward.&lt;/p&gt;

&lt;p&gt;Frontend creds -&amp;gt; validations -&amp;gt; set cookie in headers as  a response -&amp;gt; the client sends that cookie w every request, making it clear that it is signed in&lt;/p&gt;

&lt;h3&gt;
  
  
  sameSite attribute
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Cookies with &lt;code&gt;sameSite: none&lt;/code&gt; are third party cookies&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Notice that I've the &lt;code&gt;sameSite:'strict'&lt;/code&gt; property commented out. This is because my frontend and backend are on different domains, so this is a cross-site request according to CORS and will naturally get blocked.&lt;/p&gt;

&lt;p&gt;But this brings with it, it's own set of problems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CSRF attacks&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not to mention, Chrome won't even ALLOW my cookies now. This is because I've got third party cookies blocked.&lt;/p&gt;

&lt;p&gt;But there's a way to solve this problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  CHIPS
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;As of 2024, Chrome has started a gradual blockage of 3rd party cookies. &lt;br&gt;
Cookies with &lt;code&gt;sameSite=none; Secure and Partitioned attribute unset&lt;/code&gt;  operating in cross-contexts are now counted as third party cookies and CHIPS, the &lt;a href="https://developers.google.com/privacy-sandbox/3pcd/storage-access-api" rel="noopener noreferrer"&gt;Storage Access API&lt;/a&gt;, and &lt;a href="https://developers.google.com/privacy-sandbox/3pcd/related-website-sets" rel="noopener noreferrer"&gt;Related Website Sets&lt;/a&gt; are the only ways to read and write cookies from cross-contexts. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This can be a real problem if your server is on a different domain than your websites.&lt;/p&gt;

&lt;p&gt;This can be a real problem if your server is on a different domain than your websites.&lt;br&gt;
CHIPS or Cookies Having Independent Partitioned State.&lt;br&gt;
Basically set the partitioned attr to true in your cookie options and voila it should work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Express bug
&lt;/h3&gt;

&lt;p&gt;Unfortunately, it's not always roses and sunshine.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;res.cookie()&lt;/code&gt; has a bug which doesn't set the partition attribute. So my code above, doesn't set the partitioned attribute to true in the response header.&lt;/p&gt;

&lt;h2&gt;
  
  
  Browser behaviours
&lt;/h2&gt;

&lt;p&gt;Here are the errors that I've encountered.&lt;/p&gt;

&lt;h3&gt;
  
  
  Firefox
&lt;/h3&gt;

&lt;p&gt;In firefox, it somehow &lt;em&gt;works&lt;/em&gt;&lt;br&gt;
Even though I've got my third party cookie blockage set to true. This might even be a firefox bug. &lt;/p&gt;

&lt;p&gt;It shows this warning&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foyxxqm1tksnpevrru0c8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foyxxqm1tksnpevrru0c8.png" alt="Image description" width="661" height="146"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Chrome
&lt;/h3&gt;

&lt;p&gt;In chrome, with 3rd party cookies blocked. Nothing works.&lt;br&gt;
Sessions authentication will not work. Period.&lt;/p&gt;

&lt;p&gt;However with 3rd party cookies enabled, I get this warning.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Folxc8tccgj0vpa3e1d1n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Folxc8tccgj0vpa3e1d1n.png" alt="Image description" width="800" height="85"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4sbpbmd3tcqa4kioqm18.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4sbpbmd3tcqa4kioqm18.png" alt="Image description" width="800" height="138"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I just wanted to implement session based authentication. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;GET&lt;/code&gt; requests will work, regardless of even if sameSite is set to strict (i guess). But what do i do now.&lt;/p&gt;

&lt;p&gt;Either express fixes the cookie issue&lt;/p&gt;

&lt;p&gt;or&lt;/p&gt;

&lt;p&gt;I find a way to bypass cors altogether.&lt;/p&gt;

&lt;p&gt;either way, stackoverflow&lt;/p&gt;

&lt;p&gt;here I come.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
