mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Bug 1802086 - remove auth header from redirected cross-origin requests. r=necko-reviewers,smaug,valentin
The change also updates WPT based on the discussions here https://github.com/web-platform-tests/wpt/pull/37145/files#r1042166622 Differential Revision: https://phabricator.services.mozilla.com/D163904
This commit is contained in:
parent
f5765da017
commit
cb305f0962
@ -8,6 +8,7 @@
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/dom/FetchDriver.h"
|
||||
|
||||
#include "mozilla/dom/ReferrerInfo.h"
|
||||
#include "nsIAsyncVerifyRedirectCallback.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "nsICookieJarSettings.h"
|
||||
@ -713,7 +714,7 @@ nsresult FetchDriver::HttpFetch(
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Set the same headers.
|
||||
SetRequestHeaders(httpChan, false);
|
||||
SetRequestHeaders(httpChan, false, false);
|
||||
|
||||
// Step 5 of https://fetch.spec.whatwg.org/#main-fetch
|
||||
// If request's referrer policy is the empty string and request's client is
|
||||
@ -1529,7 +1530,14 @@ FetchDriver::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
|
||||
Unused << oldHttpChannel->ShouldStripRequestBodyHeader(method,
|
||||
&rewriteToGET);
|
||||
|
||||
SetRequestHeaders(newHttpChannel, rewriteToGET);
|
||||
// we need to strip Authentication headers for cross-origin requests
|
||||
// Ref: https://fetch.spec.whatwg.org/#http-redirect-fetch
|
||||
bool skipAuthHeader = false;
|
||||
if (StaticPrefs::network_fetch_redirect_stripAuthHeader()) {
|
||||
skipAuthHeader = ReferrerInfo::IsCrossOriginRequest(oldHttpChannel);
|
||||
}
|
||||
|
||||
SetRequestHeaders(newHttpChannel, rewriteToGET, skipAuthHeader);
|
||||
}
|
||||
|
||||
// "HTTP-redirect fetch": step 14 "Append locationURL to request's URL list."
|
||||
@ -1637,7 +1645,8 @@ PerformanceTimingData* FetchDriver::GetPerformanceTimingData(
|
||||
}
|
||||
|
||||
void FetchDriver::SetRequestHeaders(nsIHttpChannel* aChannel,
|
||||
bool aStripRequestBodyHeader) const {
|
||||
bool aStripRequestBodyHeader,
|
||||
bool aStripAuthHeader) const {
|
||||
MOZ_ASSERT(aChannel);
|
||||
|
||||
// nsIHttpChannel has a set of pre-configured headers (Accept,
|
||||
@ -1658,6 +1667,11 @@ void FetchDriver::SetRequestHeaders(nsIHttpChannel* aChannel,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (aStripAuthHeader &&
|
||||
headers[i].mName.LowerCaseEqualsASCII("authorization")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool alreadySet = headersSet.Contains(headers[i].mName);
|
||||
if (!alreadySet) {
|
||||
headersSet.AppendElement(headers[i].mName);
|
||||
|
@ -207,8 +207,8 @@ class FetchDriver final : public nsIStreamListener,
|
||||
// response.
|
||||
void FailWithNetworkError(nsresult rv);
|
||||
|
||||
void SetRequestHeaders(nsIHttpChannel* aChannel,
|
||||
bool aStripRequestBodyHeader) const;
|
||||
void SetRequestHeaders(nsIHttpChannel* aChannel, bool aStripRequestBodyHeader,
|
||||
bool aStripAuthHeader) const;
|
||||
|
||||
void FinishOnStopRequest(AlternativeDataStreamListener* aAltDataListener);
|
||||
};
|
||||
|
@ -2567,7 +2567,7 @@ nsresult XMLHttpRequestMainThread::InitiateFetch(
|
||||
mAuthorRequestHeaders.Set("accept", "*/*"_ns);
|
||||
}
|
||||
|
||||
mAuthorRequestHeaders.ApplyToChannel(httpChannel, false);
|
||||
mAuthorRequestHeaders.ApplyToChannel(httpChannel, false, false);
|
||||
|
||||
if (!IsSystemXHR()) {
|
||||
nsCOMPtr<nsPIDOMWindowInner> owner = GetOwner();
|
||||
@ -3374,9 +3374,17 @@ nsresult XMLHttpRequestMainThread::OnRedirectVerifyCallback(nsresult result) {
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> newHttpChannel(do_QueryInterface(mChannel));
|
||||
if (newHttpChannel) {
|
||||
// we need to strip Authentication headers for cross-origin requests
|
||||
// Ref: https://fetch.spec.whatwg.org/#http-redirect-fetch
|
||||
bool skipAuthHeader = false;
|
||||
if (StaticPrefs::network_fetch_redirect_stripAuthHeader()) {
|
||||
skipAuthHeader = ReferrerInfo::IsCrossOriginRequest(oldHttpChannel);
|
||||
}
|
||||
|
||||
// Ensure all original headers are duplicated for the new channel (bug
|
||||
// #553888)
|
||||
mAuthorRequestHeaders.ApplyToChannel(newHttpChannel, rewriteToGET);
|
||||
mAuthorRequestHeaders.ApplyToChannel(newHttpChannel, rewriteToGET,
|
||||
skipAuthHeader);
|
||||
}
|
||||
} else {
|
||||
mErrorLoad = ErrorType::eRedirect;
|
||||
@ -4069,7 +4077,8 @@ void RequestHeaders::MergeOrSet(const nsACString& aName,
|
||||
void RequestHeaders::Clear() { mHeaders.Clear(); }
|
||||
|
||||
void RequestHeaders::ApplyToChannel(nsIHttpChannel* aChannel,
|
||||
bool aStripRequestBodyHeader) const {
|
||||
bool aStripRequestBodyHeader,
|
||||
bool aStripAuthHeader) const {
|
||||
for (const RequestHeader& header : mHeaders) {
|
||||
if (aStripRequestBodyHeader &&
|
||||
(header.mName.LowerCaseEqualsASCII("content-type") ||
|
||||
@ -4078,6 +4087,12 @@ void RequestHeaders::ApplyToChannel(nsIHttpChannel* aChannel,
|
||||
header.mName.LowerCaseEqualsASCII("content-location"))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (aStripAuthHeader &&
|
||||
header.mName.LowerCaseEqualsASCII("authorization")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Update referrerInfo to override referrer header in system privileged.
|
||||
if (header.mName.LowerCaseEqualsASCII("referer")) {
|
||||
DebugOnly<nsresult> rv = aChannel->SetNewReferrerInfo(
|
||||
|
@ -168,8 +168,8 @@ class RequestHeaders {
|
||||
void MergeOrSet(const char* aName, const nsACString& aValue);
|
||||
void MergeOrSet(const nsACString& aName, const nsACString& aValue);
|
||||
void Clear();
|
||||
void ApplyToChannel(nsIHttpChannel* aChannel,
|
||||
bool aStripRequestBodyHeader) const;
|
||||
void ApplyToChannel(nsIHttpChannel* aChannel, bool aStripRequestBodyHeader,
|
||||
bool aStripAuthHeader) const;
|
||||
void GetCORSUnsafeHeaders(nsTArray<nsCString>& aArray) const;
|
||||
};
|
||||
|
||||
|
@ -11005,6 +11005,20 @@
|
||||
value: true
|
||||
mirror: always
|
||||
|
||||
# Whether to strip auth headers for redirected fetch/xhr channels
|
||||
# https://fetch.spec.whatwg.org/#http-redirect-fetch
|
||||
- name: network.fetch.redirect.stripAuthHeader
|
||||
type: RelaxedAtomicBool
|
||||
value: true
|
||||
mirror: always
|
||||
|
||||
# Whether to strip auth headers for redirected http channels
|
||||
# https://fetch.spec.whatwg.org/#http-redirect-fetch
|
||||
- name: network.http.redirect.stripAuthHeader
|
||||
type: RelaxedAtomicBool
|
||||
value: true
|
||||
mirror: always
|
||||
|
||||
# Prefs allowing granular control of referers.
|
||||
# 0=don't send any, 1=send only on clicks, 2=send on image requests as well
|
||||
- name: network.http.sendRefererHeader
|
||||
|
@ -4900,6 +4900,16 @@ nsresult HttpBaseChannel::SetupReplacementChannel(nsIURI* newURI,
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
}
|
||||
|
||||
// we need to strip Authentication headers for cross-origin requests
|
||||
// Ref: https://fetch.spec.whatwg.org/#http-redirect-fetch
|
||||
nsAutoCString authHeader;
|
||||
if (StaticPrefs::network_http_redirect_stripAuthHeader() &&
|
||||
NS_SUCCEEDED(
|
||||
httpChannel->GetRequestHeader("Authorization"_ns, authHeader))) {
|
||||
rv = httpChannel->SetRequestHeader("Authorization"_ns, ""_ns, false);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1,26 +0,0 @@
|
||||
[authentication-redirection.any.serviceworker.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[getAuthorizationHeaderValue - cross origin redirection]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[authentication-redirection.any.sharedworker.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[getAuthorizationHeaderValue - cross origin redirection]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[authentication-redirection.any.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[getAuthorizationHeaderValue - cross origin redirection]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[authentication-redirection.any.worker.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[getAuthorizationHeaderValue - cross origin redirection]
|
||||
expected: FAIL
|
@ -1,32 +0,0 @@
|
||||
[xhr-authorization-redirect.any.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[getAuthorizationHeaderValue - cross origin redirection]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[xhr-authorization-redirect.any.serviceworker.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[getAuthorizationHeaderValue - no redirection]
|
||||
expected: FAIL
|
||||
|
||||
[getAuthorizationHeaderValue - same origin redirection]
|
||||
expected: FAIL
|
||||
|
||||
[getAuthorizationHeaderValue - cross origin redirection]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[xhr-authorization-redirect.any.worker.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[getAuthorizationHeaderValue - cross origin redirection]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[xhr-authorization-redirect.any.sharedworker.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[getAuthorizationHeaderValue - cross origin redirection]
|
||||
expected: FAIL
|
@ -21,6 +21,6 @@ promise_test(async test => {
|
||||
}, "getAuthorizationHeaderValue - same origin redirection");
|
||||
|
||||
promise_test(async (test) => {
|
||||
const result = await getAuthorizationHeaderValue(get_host_info().HTTP_REMOTE_ORIGIN + "/fetch/api/resources/redirect.py?allow_headers=Authorization&location=" + encodeURIComponent(get_host_info().HTTP_ORIGIN + "/fetch/api/resources/dump-authorization-header.py"));
|
||||
const result = await getAuthorizationHeaderValue(get_host_info().HTTPS_REMOTE_ORIGIN + "/fetch/api/resources/redirect.py?allow_headers=Authorization&location=" + encodeURIComponent(get_host_info().HTTPS_ORIGIN + "/fetch/api/resources/dump-authorization-header.py"));
|
||||
assert_equals(result, "none");
|
||||
}, "getAuthorizationHeaderValue - cross origin redirection");
|
||||
|
@ -1,4 +1,4 @@
|
||||
// META: global=window,worker
|
||||
// META: global=window,sharedworker,dedicatedworker
|
||||
// META: script=/common/get-host-info.sub.js
|
||||
|
||||
const authorizationValue = "Basic " + btoa("user:pass");
|
||||
|
Loading…
Reference in New Issue
Block a user