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-07-01 04:31 PDT (History)
8 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!