Login form failing: 302 POST ends up in 403 Forbidden instead of 200 OK

Issue #2883 resolved
Cristian Amarie created an issue


  1. Navigate to https://direct.credit-suisse.com/dn/c/cls/auth?language=en with cefclient 3904.
  2. Open DevTools.
  3. Enter some bogus User-ID and Password and click on login button.


The POST request to https://direct.credit-suisse.com/dn/c/cls/auth is a 302 redirects and second request coming is a GET 200 OK with normal “Your login is invalid.” This is working in Chrome 80.0.3987.106 normally (and in 3904 as well).

Actual result:

The POST request 302 redirect end in a GET 403 Forbidden.

This does happen also in 3809, but if --disable-features=NetworkService is passed then the behavior is normal, 200 OK with the message about invalid login.

It looks to be something related to the new NetworkService implementation; might be related to issues 2699, 2707, 2806, but it is not quite the same.

Comments (11)

  1. Marshall Greenblatt

    I’ll leave this issue open for the time being. While the current CEF behavior is compliant with the HTTP spec it’s also not a bad idea to have the same behavior as Chrome.

  2. Cristian Amarie reporter

    “Use 307 redirect if you want the request to be repeated“
    I’m not sure what do you mean by this. 302 (or 307) are not set by me. It’s just the behavior I see on credit-suisse.com.
    And another thing: issue 2707 is marked as Resolved. This issue is not referring to a Post-Redirect-Get or ERR_TOO_MANY_REDIRECTS, because POST 302 is correctly followed by a GET and that’s it, no loops I can see.
    The problem is the GET have status code 403 instead of 200.

  3. Marshall Greenblatt

    The POST request 302 redirect end in a GET 403 Forbidden.

    What does the DevTools Network tab show as the difference (content and headers) between this request as executed in CEF and Chrome, specifically as related to the redirect?

  4. Cristian Amarie reporter

    There is one URL involved, https://direct.credit-suisse.com/dn/c/cls/auth with 2 requests in both cases, first the POST and then the GET. I’m posting the differences (and attach the full link/request/response headers files).

    1. https://direct.credit-suisse.com/dn/c/cls/auth POST /dn/c/cls/auth HTTP/1.1
    Chrome (incognito) cefclient 3904
    REQ POST /dn/c/cls/auth HTTP/1.1 POST /dn/c/cls/auth HTTP/1.1
    DNT: 1
    Sec-Fetch-Dest: document
    Cookie: SCDID_S=… Cookie: SCDID_S=…
    1. https://direct.credit-suisse.com/dn/c/cls/auth GET /dn/c/cls/auth HTTP/1.1
    Chrome (incognito) cefclient 3904
    REQ GET /dn/c/cls/auth HTTP/1.1 GET /dn/c/cls/auth HTTP/1.1
    DNT: 1
    Sec-Fetch-Dest: document
    Origin: https://direct.credit-suisse.com
    Content-Type: application/x-www-form-urlencoded
    Cookie: check=true; _gcl_au=… Cookie: SCDID_S=…
    RESP HTTP/1.1 200 OK HTTP/1.1 403 Forbidden
    Pragma: No-cache
    Cache-Control: no-cache,no-store,max-age=0
    Expires: Thu, 01 Jan 1970 00:00:00 GMT
    Content-Type: text/html;charset=UTF-8
    Vary: Accept-Encoding
    Content-Encoding: gzip
    Transfer-Encoding: chunked
    Last-Modified: Mon, 23 Dec 2019 15:31:26 GMT
    ETag: "20f0-59a60b8788f80"
    Accept-Ranges: bytes
    Content-Length: 8432
    Content-Type: text/html
    Cache-Control: no-store, no-cache, must-revalidate

    What looks odd is the Content-Type: “application/x-www-form-urlencoded” in the CEF request, and also the Cookie which seems copied from the POST, while Chrome Cookie: for GET looks normal.

    Looking in resource_request_handler_wrapper.cc on HandleRedirect and HandleResponse, I’d say these are the places to look:

    • HandleRedirect does a Set with redirect_info and then enters in ResponseMode::CONTINUE
    • HandleResponse does RevertChanges and enters ResponseMode::RESTART

  5. Cristian Amarie reporter

    I think I get the 307 thing from URLRequest::BeforeRequestComplete, where I see the new URLRequestJob with REDIRECT_307_TEMPORARY_REDIRECT.

    I see URLRequestJob: NotifyHeadersComplete => FollowRedirect called with removed headers and modified headers set to nullopt, then => URLRequest::Redirect is copying from redirect_info method, referrer, policy, site for cookies and top frame origin and then calls Start.

    Also, inside URLRequest::Redirect calls net::RedirectUtil::UpdateHttpRequest, which tells something interesting:

        // The inclusion of a multipart Content-Type header can cause problems with
        // some servers:
        // http://code.google.com/p/chromium/issues/detail?id=843

    which pinpoints to … a 2008 issue, “Issue 843: Invalid Content-Type in GET request to follow a 302 redirect from a POST request

    Looks quite familiar, only that issue got a 404 editing an issue in Jira instead of 403 as this one.

  6. Log in to comment