Support user login on the frontend domain

Created on 30 August 2024, 3 months ago
Updated 10 September 2024, 3 months ago

Motivation

For 📌 Simplify authentication by leveraging CSR + CORS Active we want to support the login on the frontend domain. With the support for user-forms - as established by the parent issue - this is almost working. However, the backend by defaults sets the cookie for the backend domain, what the browser ignores.

As workaround one can configure a common, shared parent domain as cookie domain - as we do currently in the example project. But we want to remove this limitation + make the setup simpler. Thus we need to improve this, such that the cookie gets set for the frontend domain.

Proposed resolution

When forwarding POST requests to the backend, the frontend shall provide the host in some header, like the X-Forwarded-For header. Then the lupus-decoupled-user-form module can take care of re-writing the cookie to be set for this header.

📌 Task
Status

Fixed

Version

1.0

Component

Code

Created by

🇦🇹Austria fago Vienna

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @fago
  • 🇦🇹Austria fago Vienna

    This is handled by Drupal session configuration like this;

      protected function getCookieDomain(Request $request) {
        // $this->options is what is set as session configuration via drupal services.yml config
        if (isset($this->options['cookie_domain'])) {
          $cookie_domain = $this->options['cookie_domain'];
        }
        else {
          $host = $request->getHost();
          // To maximize compatibility and normalize the behavior across user
          // agents, the cookie domain should start with a dot.
          $cookie_domain = '.' . $host;
        }
    
        // Cookies for domains without an embedded dot will be rejected by user
        // agents in order to defeat malicious websites attempting to set cookies
        // for top-level domains. Also IP addresses may not be used in the domain
        // attribute of a Set-Cookie header. IPv6 addresses will not pass the first
        // test, so it's acceptable to bias the second test to IPv4.
        if (count(explode('.', $cookie_domain)) > 2 && !is_numeric(str_replace('.', '', $cookie_domain))) {
          return $cookie_domain;
        }
    

    When nothing is returned, the request is returned with a Domain parameter set. Without it being set, browsers implement the safe default:

    Section 5.2.3 of RFC 6265, which defines the HTTP State Management Mechanism (including cookies), states:

    If the server omits the Domain attribute, the user agent will return the cookie only to the origin server.

    For example, if the value of the Host header field is "example.com", a Set-Cookie header field containing a cookie without a Domain attribute will set a cookie with a domain attribute of "example.com".

    Full RFC: https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.3

    Thus,when we drop the else clause $host = $request->getHost(); we get a working cookie on the frontend and backend, while staying safe. It's even better than the drupal default ".$host" since that allows also other sub-domains.

    Let's provide a new alternative session configuration that decorates the existing one, which does not use the host default. Then, inject that into the session manager. Finally, we should add a test-case to ensure this does not break during major upgrades.

  • Merge request !91Remove cookie domain by default. → (Merged) created by fago
  • Status changed to Needs review 3 months ago
  • 🇦🇹Austria fago Vienna

    ok, tests where a bit tricky but got it working now. Turns out this is not properly doable with kernel tests, so moved it to a functional test case.

  • Status changed to Needs work 3 months ago
  • 🇸🇮Slovenia useernamee Ljubljana

    @fago I added my remarks to the PR:

    - I'm wondering what happens when IPv4 and IPv6 checks are skipped.
    - We only override session_configuration service in one place (inside session configuration). The service is used on other places as well which might cause some confusion.
    - Should we properly decorate the session_configuration service?
    - Service provider should be in /src folder.

  • Status changed to Needs review 3 months ago
  • 🇦🇹Austria fago Vienna

    > - We only override session_configuration service in one place (inside session configuration). The service is used on other places as well which might cause some confusion.

    The only goal is to change how Session-Manager works, so this seems to be fine. I cannot think of any other usages of cookie_domain besides sending this header, this is the one and only purpose. So this seems fine to me.

    > - I'm wondering what happens when IPv4 and IPv6 checks are skipped.
    It does not skip anything. When the value is set, it calls the parent and all the parent logic is run as normal.

    > - Should we properly decorate the session_configuration service?
    I thought it's less intrusive when avoiding to do so, since only once module can do that. Less chance for conflics.

    > - Service provider should be in /src folder.
    good point, updated! strange it still works! fixed.

  • Pipeline finished with Skipped
    3 months ago
    #278836
  • Pipeline finished with Skipped
    3 months ago
    #278841
    • fago → committed 166fe13e on 1.x
      Issue #3471132 by fago: Support user login on the frontend domain by...
  • 🇦🇹Austria fago Vienna

    thus, moving and merging this!

  • Status changed to Fixed 3 months ago
  • 🇦🇹Austria fago Vienna
  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.71.5 2024