Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1430,6 +1430,9 @@
<name>Vladimir Babin</name>
<email>vovababin@gmail.com</email>
</contributor>
<contributor>
<name>Vidya m</name>
</contributor>
</contributors>

<dependencies>
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/org/htmlunit/WebClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@
* @author René Schwietzke
* @author Sven Strickroth
* @author Ashutosh Panda
* @author Vidya m
*/
@SuppressWarnings("PMD.TooManyFields")
public class WebClient implements Serializable, AutoCloseable {
Expand Down Expand Up @@ -1711,6 +1712,8 @@ && getOptions().isRedirectEnabled()
+ webResponse.getWebRequest().getUrl(), webResponse);
}

final boolean crossOriginRedirect = !UrlUtils.isSameOrigin(url, newUrl);

if (status == HttpStatus.MOVED_PERMANENTLY_301
|| status == HttpStatus.FOUND_302
|| status == HttpStatus.SEE_OTHER_303) {
Expand All @@ -1723,6 +1726,10 @@ && getOptions().isRedirectEnabled()
for (final Map.Entry<String, String> entry : webRequest.getAdditionalHeaders().entrySet()) {
wrs.setAdditionalHeader(entry.getKey(), entry.getValue());
}
if (crossOriginRedirect) {
// credentials are not forwarded to another origin
wrs.removeAdditionalHeader("Authorization");
}
wrs.setFetchDestination(webRequest.getFetchDestination());
wrs.setFetchModeOverride(webRequest.getFetchModeOverride());
wrs.setRequestingUrl(webRequest.getRequestingUrl());
Expand Down Expand Up @@ -1751,6 +1758,10 @@ else if (status == HttpStatus.TEMPORARY_REDIRECT_307
for (final Map.Entry<String, String> entry : webRequest.getAdditionalHeaders().entrySet()) {
wrs.setAdditionalHeader(entry.getKey(), entry.getValue());
}
if (crossOriginRedirect) {
// credentials are not forwarded to another origin
wrs.removeAdditionalHeader("Authorization");
}

return loadWebResponseFromWebConnection(wrs, allowedRedirects - 1);
}
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/org/htmlunit/html/HtmlPage.java
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@
* @author Ronny Shapiro
* @author Lai Quang Duong
* @author Sven Strickroth
* @author Vidya m
*/
@SuppressWarnings("PMD.TooManyFields")
public class HtmlPage extends SgmlPage {
Expand Down Expand Up @@ -1105,6 +1106,10 @@ private Object loadJavaScriptFromUrl(final URL url, final Charset scriptCharset,
final WebRequest request = new WebRequest(url);
// copy all headers from the referring request
request.setAdditionalHeaders(new HashMap<>(referringRequest.getAdditionalHeaders()));
if (!UrlUtils.isSameOrigin(referringRequest.getUrl(), url)) {
// credentials are not forwarded to another origin
request.removeAdditionalHeader("Authorization");
}

// at least overwrite this headers
request.setAdditionalHeader(HttpHeader.ACCEPT, client.getBrowserVersion().getScriptAcceptHeader());
Expand Down
34 changes: 34 additions & 0 deletions src/test/java/org/htmlunit/WebClientTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
* @author Ronald Brill
* @author Carsten Steul
* @author Joerg Werner
* @author Vidya m
*/
public class WebClientTest extends SimpleWebTestCase {

Expand Down Expand Up @@ -526,6 +527,39 @@ private void redirection_AdditionalHeadersMaintained(final int statusCode) throw
assertEquals("bar", conn.getLastAdditionalHeaders().get("foo"));
}

/**
* Verifies that the "Authorization" header of the original {@link WebRequest} is only
* sent to the redirect location if the redirect does not leave the origin.
* @throws Exception if an error occurs
*/
@Test
public void redirection_AuthorizationHeaderDroppedForCrossOrigin() throws Exception {
for (final int statusCode : new int[] {301, 302, 303, 307, 308}) {
redirection_AuthorizationHeader(statusCode, URL_SECOND, "Bearer secret");
redirection_AuthorizationHeader(statusCode, URL_THIRD, null);
}
}

private void redirection_AuthorizationHeader(final int statusCode, final URL redirectUrl,
final String expectedAuthorization) throws Exception {
final WebClient client = getWebClient();
final MockWebConnection conn = new MockWebConnection();
client.setWebConnection(conn);

final List<NameValuePair> headers = asList(new NameValuePair("Location", redirectUrl.toString()));
conn.setResponse(URL_FIRST, "", statusCode, "", MimeType.TEXT_HTML, headers);
conn.setResponse(redirectUrl, DOCTYPE_HTML + "<html><body>abc</body></html>");

final WebRequest request = new WebRequest(URL_FIRST);
request.setAdditionalHeader("Authorization", "Bearer secret");
request.setAdditionalHeader("foo", "bar");
client.getPage(request);

assertEquals(redirectUrl, conn.getLastWebRequest().getUrl());
assertEquals(expectedAuthorization, conn.getLastAdditionalHeaders().get("Authorization"));
assertEquals("bar", conn.getLastAdditionalHeaders().get("foo"));
}

/**
* Basic logic for all the redirection tests.
*
Expand Down
37 changes: 37 additions & 0 deletions src/test/java/org/htmlunit/html/HtmlScriptTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.htmlunit.MockWebConnection;
import org.htmlunit.SimpleWebTestCase;
import org.htmlunit.WebClient;
import org.htmlunit.WebRequest;
import org.htmlunit.junit.annotation.Alerts;
import org.htmlunit.util.MimeType;
import org.junit.jupiter.api.Test;
Expand All @@ -37,6 +38,7 @@
* @author Ahmed Ashour
* @author Ronald Brill
* @author Ronny Shapiro
* @author Vidya m
*/
public class HtmlScriptTest extends SimpleWebTestCase {

Expand Down Expand Up @@ -83,6 +85,41 @@ public void badExternalScriptReference() throws Exception {
}
}

/**
* Verifies that the "Authorization" header of the page request is only sent
* with the request for an external script if the script has the same origin.
* @throws Exception if an error occurs
*/
@Test
public void authorizationHeaderNotSentToCrossOriginScript() throws Exception {
externalScriptAuthorizationHeader(new URL(URL_FIRST, "script.js"), "Bearer secret");
externalScriptAuthorizationHeader(new URL(URL_THIRD, "script.js"), null);
}

private void externalScriptAuthorizationHeader(final URL scriptUrl,
final String expectedAuthorization) throws Exception {
final String html = DOCTYPE_HTML
+ "<html><head><title>foo</title>\n"
+ "<script src='" + scriptUrl + "'></script>\n"
+ "</head><body></body></html>";

final WebClient client = getWebClient();

final MockWebConnection webConnection = new MockWebConnection();
webConnection.setResponse(URL_FIRST, html);
webConnection.setResponse(scriptUrl, "var i = 7;", MimeType.TEXT_JAVASCRIPT);
client.setWebConnection(webConnection);

final WebRequest request = new WebRequest(URL_FIRST);
request.setAdditionalHeader("Authorization", "Bearer secret");
request.setAdditionalHeader("foo", "bar");
client.getPage(request);

assertEquals(scriptUrl, webConnection.getLastWebRequest().getUrl());
assertEquals(expectedAuthorization, webConnection.getLastAdditionalHeaders().get("Authorization"));
assertEquals("bar", webConnection.getLastAdditionalHeaders().get("foo"));
}

/**
* @throws Exception if an error occurs
*/
Expand Down
Loading