SerenityOS / serenity

The Serenity Operating System 🐞
https://serenityos.org
BSD 2-Clause "Simplified" License
30.66k stars 3.19k forks source link

Ladybird: Cookies are not persisted after redirects #22520

Closed winfr34k closed 10 months ago

winfr34k commented 10 months ago

Steps to Reproduce

  1. Run the provided Python script as a demo server.
  2. Access /, no Cookie: should be present.
  3. Access /redirect, you should get redirected.
  4. See that still, no Cookie: is present.

This diverges from behavior in Firefox, Chrome and Safari.

Originally found trying to login to https://winhistory-forum.net (a MyBB based classic forum.)

Issue is crossplatform in Ladybird and Serenity's native Browser.

Workaround

Run Ladybird with --disable-sql-database, then is works.

This switches from PersistedStorage (via SQL database) to TransientStorage (HashMap in memory).

Reproduction Server

repro.py:

from http.server import BaseHTTPRequestHandler, HTTPServer
from datetime import datetime, timedelta

class ExampleServer(BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == "/":
            self._handle_root()
            return

        if self.path == "/redirect":
            self._handle_redirect()
            return

        self._handle_not_found()

    def _handle_root(self):
        self.send_response(200)
        self.send_header("Content-Type", "text/html")
        self.end_headers()
        self.wfile.write(b"<h1>Well, hello friend :^)</h1><p>You sent these headers:<pre>")
        self.wfile.write(bytes(f"{self.headers.as_string()}\n", "utf-8"))
        self.wfile.write(b"</pre></p>")

    def _handle_redirect(self):
        one_hour_later = (datetime.now() + timedelta(hours=1)).strftime("%a, %d-%b-%Y %H:%M:%S %Z")
        self.send_response(302)
        self.send_header("Location", "http://localhost:8080/")
        self.send_header("Set-Cookie", f"message=whf; expires={one_hour_later}; path=/; domain=localhost")
        self.end_headers()

    def _handle_not_found(self):
        self.send_response(404)
        self.send_header("Content-Type", "text/plain")
        self.end_headers()
        self.wfile.write(b"Not Found: %s" % bytes(self.path, "utf-8"))

if __name__ == "__main__":
    server = HTTPServer(("localhost", 8080), ExampleServer)
    print("Server started: http://localhost:8080")

    try:
        server.serve_forever()
    except KeyboardInterrupt:
        pass

    server.server_close()
    print("Server stopped.")

Found and debugged with help of ADKaster at 37C3 :^) Thanks!

trflynn89 commented 10 months ago

Hey @winfr34k, thanks for the report! This should be fixed by #22690. A video showing the login process working is attached to that PR.

winfr34k commented 10 months ago

I can confirm your solution is working! Thanks a lot. Also, welcome to our forum 😀