Bug 232088 - Unable to set secure+httpOnly cookie for localhost in Safari from Node JS
Summary: Unable to set secure+httpOnly cookie for localhost in Safari from Node JS
Status: NEW
Alias: None
Product: WebKit
Classification: Unclassified
Component: Page Loading (show other bugs)
Version: Safari 15
Hardware: All macOS 11
: P2 Major
Assignee: Nobody
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2021-10-21 09:03 PDT by Raj
Modified: 2024-10-09 19:10 PDT (History)
11 users (show)

See Also:


Attachments
Http Cookie on Edge vs Safari (309.96 KB, image/png)
2021-10-21 09:03 PDT, Raj
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Raj 2021-10-21 09:03:43 PDT
Created attachment 442035 [details]
Http Cookie on Edge vs Safari

I am using node express server to set a httpOnly cookie on localhost:3000. I can see cookie setting on other browsers but not on Safari. 


Here is HTML code: 

<html>
    <head>
        <title> CGID Beta </title>
        <script src="https://assets.adobedtm.com/43cf45b098bd/38a98b49e24d/launch-5d7d0d6eb58d-development.min.js" async></script>
    </head>
    <body>
        <br><br><br>
        <h1><center>Welcome to CGID beta program</center></h1><br><br><br><br>
        <h3><center>To set a http only cookie click the below button</center></h3><br><br><br>
        <center>
            <form method="post" action="/">
                <button type="submit">CLICK ME</button>
          </form>
        </center>
    </body>
</html>


Here is node server-side code:

const express = require("express");
const bodyParser = require("body-parser")
const cookieParser = require('cookie-parser');
const { v4: uuidv4 } = require('uuid');

const app = express();

app.use(cookieParser());

app.use(bodyParser.urlencoded({
    extended:true
}));

app.get("/", (req, res) => {
  res.sendFile(__dirname + "/index.html");
});
  
app.post("/", function(req, res) {
    res.cookie('CGID', uuidv4(), {
        maxAge: 60*60*24*30*13, 
        httpOnly: true, 
        secure: true, 
        sameSite: "lax",
        domain: 'localhost',
        path: '/',
    }); 
    //res.send("<h2>CGID is now set</h2>")
});

app.listen(3000, () => {
    console.log("Application started and Listening on port 3000");
  });
Comment 1 Radar WebKit Bug Importer 2021-10-21 09:03:58 PDT
<rdar://problem/84509493>
Comment 2 Radar WebKit Bug Importer 2021-10-21 09:06:49 PDT
<rdar://problem/84509597>
Comment 3 Raj 2021-10-21 09:07:44 PDT
Oops, consider the below line of code uncommented

res.send("<h2>CGID is now set</h2>")
Comment 4 Raj 2021-10-21 09:08:16 PDT
Http Cookie on Edge vs Safari

I am using node express server to set a httpOnly cookie on localhost:3000. I can see cookie setting on other browsers but not on Safari. 


Here is HTML code: 

<html>
    <head>
        <title> CGID Beta </title>
        <script src="https://assets.adobedtm.com/43cf45b098bd/38a98b49e24d/launch-5d7d0d6eb58d-development.min.js" async></script>
    </head>
    <body>
        <br><br><br>
        <h1><center>Welcome to CGID beta program</center></h1><br><br><br><br>
        <h3><center>To set a http only cookie click the below button</center></h3><br><br><br>
        <center>
            <form method="post" action="/">
                <button type="submit">CLICK ME</button>
          </form>
        </center>
    </body>
</html>


Here is node server-side code:

const express = require("express");
const bodyParser = require("body-parser")
const cookieParser = require('cookie-parser');
const { v4: uuidv4 } = require('uuid');

const app = express();

app.use(cookieParser());

app.use(bodyParser.urlencoded({
    extended:true
}));

app.get("/", (req, res) => {
  res.sendFile(__dirname + "/index.html");
});
  
app.post("/", function(req, res) {
    res.cookie('CGID', uuidv4(), {
        maxAge: 60*60*24*30*13, 
        httpOnly: true, 
        secure: true, 
        sameSite: "lax",
        domain: 'localhost',
        path: '/',
    }); 
    //res.send("<h2>CGID is now set</h2>")
});

app.listen(3000, () => {
    console.log("Application started and Listening on port 3000");
  });
Comment 5 Raj 2021-10-21 09:08:58 PDT
Http Cookie on Edge vs Safari

I am using node express server to set a httpOnly cookie on localhost:3000. I can see cookie setting on other browsers but not on Safari. 


Here is HTML code: 

<html>
    <head>
        <title> CGID Beta </title>
        <script src="https://assets.adobedtm.com/43cf45b098bd/38a98b49e24d/launch-5d7d0d6eb58d-development.min.js" async></script>
    </head>
    <body>
        <br><br><br>
        <h1><center>Welcome to CGID beta program</center></h1><br><br><br><br>
        <h3><center>To set a http only cookie click the below button</center></h3><br><br><br>
        <center>
            <form method="post" action="/">
                <button type="submit">CLICK ME</button>
          </form>
        </center>
    </body>
</html>


Here is node server-side code:

const express = require("express");
const bodyParser = require("body-parser")
const cookieParser = require('cookie-parser');
const { v4: uuidv4 } = require('uuid');

const app = express();

app.use(cookieParser());

app.use(bodyParser.urlencoded({
    extended:true
}));

app.get("/", (req, res) => {
  res.sendFile(__dirname + "/index.html");
});
  
app.post("/", function(req, res) {
    res.cookie('CGID', uuidv4(), {
        maxAge: 60*60*24*30*13, 
        httpOnly: true, 
        secure: true, 
        sameSite: "lax",
        domain: 'localhost',
        path: '/',
    }); 
    res.send("<h2>CGID is now set</h2>")
});

app.listen(3000, () => {
    console.log("Application started and Listening on port 3000");
  });
Comment 6 John Wilander 2021-10-21 09:40:36 PDT
Thanks for filing.

(In reply to Raj from comment #0)
> Created attachment 442035 [details]
> Http Cookie on Edge vs Safari
> 
> I am using node express server to set a httpOnly cookie on localhost:3000. I
> can see cookie setting on other browsers but not on Safari. 
> 
> 
> Here is HTML code: 
> 
> <html>
>     <head>
>         <title> CGID Beta </title>
>         <script
> src="https://assets.adobedtm.com/43cf45b098bd/38a98b49e24d/launch-
> 5d7d0d6eb58d-development.min.js" async></script>
>     </head>
>     <body>
>         <br><br><br>
>         <h1><center>Welcome to CGID beta
> program</center></h1><br><br><br><br>
>         <h3><center>To set a http only cookie click the below
> button</center></h3><br><br><br>
>         <center>
>             <form method="post" action="/">
>                 <button type="submit">CLICK ME</button>
>           </form>
>         </center>
>     </body>
> </html>
> 
> 
> Here is node server-side code:
> 
> const express = require("express");
> const bodyParser = require("body-parser")
> const cookieParser = require('cookie-parser');
> const { v4: uuidv4 } = require('uuid');
> 
> const app = express();
> 
> app.use(cookieParser());
> 
> app.use(bodyParser.urlencoded({
>     extended:true
> }));
> 
> app.get("/", (req, res) => {
>   res.sendFile(__dirname + "/index.html");
> });
>   
> app.post("/", function(req, res) {
>     res.cookie('CGID', uuidv4(), {
>         maxAge: 60*60*24*30*13, 
>         httpOnly: true, 
>         secure: true,

Are you using a self-signed certificate for localhost and serving all of its resources over https? Secure cookies are not accepted from non-secure pages.

>         sameSite: "lax",
>         domain: 'localhost',
>         path: '/',
>     }); 
>     //res.send("<h2>CGID is now set</h2>")
> });
> 
> app.listen(3000, () => {
>     console.log("Application started and Listening on port 3000");
>   });
Comment 7 Sam Sneddon [:gsnedders] 2021-10-21 17:19:19 PDT
(In reply to John Wilander from comment #6)
> Are you using a self-signed certificate for localhost and serving all of its
> resources over https? Secure cookies are not accepted from non-secure pages.

This is notably different to every other browser where localhost is treated as a secure context; this is likely another dupe of bug 218980 as a result.
Comment 8 Robert Knight 2023-12-13 03:42:25 PST
We got tripped up by this today. Something that makes it extra confusing is that Safari does treat localhost as secure in other respects (eg. `window.isSecureContext`).
Comment 9 Julian 2024-01-25 14:37:32 PST
(In reply to John Wilander from comment #6)

Thank you for this extremely helpful clarification:

> Are you using a self-signed certificate for localhost and serving all of its
> resources over https? Secure cookies are not accepted from non-secure pages.

This issue tripped up my team for several hours today, and although the behavior makes sense, but it would be helpful to have more documentation.

I would also like to note that chromium and gecko engines have different behavior and accept the cookie.

Thanks, Julian
Comment 10 Stefanos 2024-07-01 04:31:41 PDT
(In reply to Robert Knight from comment #8)
> We got tripped up by this today. Something that makes it extra confusing is
> that Safari does treat localhost as secure in other respects (eg.
> `window.isSecureContext`).

I agree with this.

Is there a reasoning/explanation on why the `window.isSecureContext` returns `true` on `localhost` but then it rejects cookies with the `Secure` attribute?

Thanks!
Comment 11 Karl Dubost 2024-10-09 01:39:08 PDT
A very similar report has been created on webcompat.com 
https://github.com/webcompat/web-bugs/issues/142566

And there are other instances of bugs on bugs.webkit.org which are similar such as Bug 276313
Comment 12 Karl Dubost 2024-10-09 18:28:44 PDT
There are larger intrinsic issues about localhost and secure contexts, including dependencies probably on the OS. The WebKit team is looking at them. And also inconsistencies which need to be solved, see for example Bug 281149