Retrieving cookie from chrome.webRequest.onBeforeSendHeaders

I have been developing a Firefox add-on with the goal of intercepting HTTP requests and extracting the cookie information. While I was successful in extracting the 'User-agent' data from the header, I faced difficulties when attempting to extract the actual cookie information. Below is the code snippet that I employed for this purpose:

chrome.webRequest.onBeforeSendHeaders.addListener(function(details){
  var headers = details.requestHeaders,
  blockingResponse = {};

  for( var i = 0, l = headers.length; i < l; ++i ) {
    window.alert("Checking headers");
    if( headers[i].name == 'Cookie' ) {
       headers[i].value = 'twid=notsecret';
       window.alert("Cookie Changed");
       console.log(headers[i].value);
       break;
    }
  }

  blockingResponse.requestHeaders = headers;
  return blockingResponse;
},
{urls: [ "<all_urls>" ]},['requestHeaders','blocking']);

I am puzzled as to why this approach is not yielding the desired results. Can anyone shed light on what might be going wrong, and suggest alternative methods to achieve the same outcome?

Answer №1

If you are testing in an older version of Firefox:
Possibly, the reason why your code is not working is because you are testing in a Firefox version earlier than 49.0a (which is currently in beta). In versions before 49.0a, using window.alert() will result in an error. Starting from Firefox version 49.0a, alert() no longer throws an error but instead opens the Browser Console and displays the following message along with your intended text:

alert() is not supported in background windows; please use console.log instead.

In pre-49.0a versions of Firefox, when trying to alert(), you may encounter these errors in the Browser Console:

NS_ERROR_NOT_AVAILABLE: Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [nsIDOMWindowUtils.isParentWindowMainWidgetVisible]                   nsPrompter.js:346
uncaught exception: unknown (can't convert to string)                                                                                                              (unknown)

Specifically, if you are using alert() in your webRequest listener, the error message would be slightly different:

NS_ERROR_NOT_AVAILABLE: Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [nsIDOMWindowUtils.isParentWindowMainWidgetVisible]                                                                                                                                                                 nsPrompter.js:346
[Exception... "Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [nsIDOMWindowUtils.isParentWindowMainWidgetVisible]"  nsresult: "0x80040111 (NS_ERROR_NOT_AVAILABLE)"  location: "JS frame :: resource://gre/components/nsPrompter.js :: openModalWindow :: line 346"  data: no]             (unknown)

Your original code functions correctly:
Your code seems appropriate as per the original question. However, when outputting the new cookie value using console.log(), it doesn't confirm whether the request headers were actually changed. To verify this, you should add another listener for the next event in the chain, webRequest.onSendHeaders.

Below is some adjusted code that ensures the cookie header has been altered, tested on FF48.0.2+:

manifest.json:

{
    "description": "Demonstrate changing the cookie of a WebRequest",
    "manifest_version": 2,
    "name": "change-webrequest-cookie-demo",
    "version": "0.1",

    "permissions": [
        "webRequest",
        "webRequestBlocking",
        "<all_urls>" //Required for Google Chrome. Not, currently, needed for Firefox.
    ],

    "background": {
        "scripts": ["background.js"]
    }
}

background.json:

/*Demonstrate changing the cookie of a WebRequet */
// For testing, open the Browser Console
try{
    //Alert is not supported in Firefox. In in FF49.0+, forces the Browser Console open.
    alert('Open the Browser Console.');
}catch(e){
    //alert throws an error in Firefox versions earlier than 49.0
    console.log('Alert threw an error. Probably, the version of Firefox is less than 49.');
}

chrome.webRequest.onBeforeSendHeaders.addListener(function(details){
  var blockingResponse = {};
  //console.log("Checking headers");
  details.requestHeaders.some(function(header){
      if( header.name == 'Cookie' ) {
          console.log("Original Cookie value:" + header.value);
          header.value = 'twid=notsecret';
          console.log("Cookie Changed");
          return true;
      }
      return false;
  });
  blockingResponse.requestHeaders = details.requestHeaders;
  return blockingResponse;
}, {urls: [ "<all_urls>" ]},['requestHeaders','blocking']);

chrome.webRequest.onSendHeaders.addListener(function(details){
  details.requestHeaders.some(function(header){
      if( header.name == 'Cookie' ) {
          console.log("New Cookie value:" + header.value);
          return true;
      }
      return false;
  });
}, {urls: [ "<all_urls>" ]},['requestHeaders']);

Tips for testing and developing WebExtensions in Firefox

Utilize Firefox Developer Edition or Firefox Nightly:
WebExtensions API continues improving with each Firefox release. It is advisable to develop and test your WebExtension add-on with Firefox Developer Edition or Firefox Nightly. Additionally, make note of the required Firefox version for your desired functionality under the "Browser compatibility" section of MDN documentation pages.

Employ the Browser Console:
Ensure to use the Browser Console to monitor console.log() outputs from your WebExtension background scripts. By checking the Browser Console, you can access error messages which, although require interpretation, provide valuable insights to include in your inquiries.

Answer №2

If you are using the latest versions of Chrome, it is important to include extraHeaders in the options.

As of Chrome 72, certain request headers cannot be modified or removed without specifying 'extraHeaders' in opt_extraInfoSpec

Chrome Developers - chrome.webRequest

For example, if you want to remove Cookies, you can use the following code snippet:

/**
 * Removes cookies 
 */
chrome.webRequest.onBeforeSendHeaders.addListener(function (details) {
  var blockingResponse = {};
  details.requestHeaders.find(a => a.name == "Cookie").value = ``
  blockingResponse.requestHeaders = details.requestHeaders;
  return blockingResponse;
}, { urls: ["<all_urls>"], }, ['requestHeaders', 'extraHeaders', 'blocking', ]);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The implementation of local JSON instead of external JSONP in Angular

I am exploring the option of storing a json-file on the same server as my Angular app. I am wondering about how I can modify this code to read from a locally stored json file: ergastAPI.getDrivers = function() { return $http({ method: 'GET&apos ...

Transitioning to the Bootstrap library from the jQuery library with the use of several image modals

After coming across this specific question about implementing multiple image modals on a webpage, I noticed that it primarily focused on javascript and jQuery. However, my project involves utilizing the latest version of Bootstrap, so I'm curious if t ...

Issue: Error occurs when using _.sample on an array containing nested arrays

I am working with an array of arrays that looks like this: [[0,0], [0,1], [0,2], [0,3]...] My goal is to randomly select N elements from the array using Underscore's _.sample method: exampleArr = [[0,0], [0,1], [0,2], [0,3]...] _.sample(exampleArr, ...

Ways to refresh my $scope once new data is inserted into the SQL database

As I implement the angularjs/SQL technique to fetch data from a database, the code snippet below demonstrates how it is done: $http.get("retrieveData.php").then(function(response){ $scope.tasks = response.data.tasks; }) In addition, there is a functi ...

React app (storybook) experiencing loading issues with @font-face

I am struggling to load custom fonts from a local directory. Can someone provide assistance? Below is the code I am currently using: @font-face { font-family: 'My Custom Font'; src: url('./fonts/MyCustomFont.eot'); src: url(&apo ...

Unexpected behavior of ion-select: No rendering of selected value when applied to filtered data

I came across an unexpected issue with the dynamic data filtering feature of ion-select. In my application, users are required to choose three unique security questions during registration. I have an array of available questions: questions: Array<{isSe ...

Organize the HTML output generated by a PHP array

There must be a simple solution to this, but for some reason, it's escaping me right now. I've created custom HTML/CSS/JS for a slider that fetches its content from an array structured like this: $slides = [ [ 'img' = ...

Troubleshooting the Width Problem in Bootstrap 5 Dropdowns

I am currently working on a new project and encountering an issue with the width of a Bootstrap 5 dropdown. The problem lies in the discrepancy between the button width and the menu width. Although it may seem simple, I am having trouble resolving it as I ...

The requested resource at http://127.0.0.1:8000/storage/profiles/ could not be located (Error 404: Not

I have successfully implemented a feature on my website that allows users to upload their avatar picture using Vue.js and Laravel as the backend. The image is stored in the storage directory, and I can display it on the user's profile page using Vue.j ...

Dark opaque background image with Material-UI styling

I'm enclosing all the widgets within a CardMedia component, and adding an image. return ( <CardMedia image={bg} className={classes.bg}> <main className={classes.content}> <div className={classes.toolbar} /> <Grid contai ...

Remove HTML tags from a table cell containing a combination of radio buttons and labels

Javascript Function: My JavaScript function posted below is designed to iterate through the column indexes specified in the 2nd parameter and also iterate through the element ids provided in the 3rd parameter. It will then populate the textbox, radiobutto ...

Redirecting and styling following an HTTP post operation

Implementing Stripe on my Firebase-hosted website. Utilizing a Cloud Function to handle the transaction. I have integrated the Stripe Checkout within a button displayed directly on my single HTML page, which then directs to the /charge function in inde ...

When the model is replaced, the Vue.js directive v-html may fail to update

Upon running the code below (a Vue.js component), my expectation is that both the v-html directive and the console.log() will display the same value after the AJAX call returns. To my surprise, while v-html remains stuck at "loading...(1)", the value of o ...

Learn how to display every ASCII or EBCDIC character once radio buttons have been selected

I'm currently working on a simple website that requires the user to input a minimum of 256 characters, choose between ASCII or EBCDIC for conversion, and then click the submit button (Run) to display the final converted result on the page. However, I& ...

Create an Interactive Data Visualization with JSON using CanvasJS Charts

Having some trouble creating a chart using CanvasJS. After fetching data from the API and checking the JSON array, I encounter two errors when attempting to generate dataPoints for the graph: "data invalid" on the data field and "NaN" on the value field. ...

A Guide on Adding Excel-Like Filtering Functionality to AngularJS

I am struggling to implement a simple Excel-like filter for a table using AngularJS (v.1). I have shared my code snippet below and would appreciate any help to show filtered data in the table after checking a checkbox and clicking on the OK button. I have ...

Analyzing the structure according to the month/week/year

My array consists of count and date values: day = [ { count: 1, date: '2022-07-07' }, { count: 1, date: '2022-08-14' }, { count: 2, date: '2022-07-19' }, { count: 4, date: '2022-07-19' }, { count: 2, date: ...

Ways to utilize jquery to limit the length of an editable div and prevent it from exceeding our specified restriction

Imagine a scenario where you have the following code snippet: <div id="editing" contenteditable onclick="document.execCommand('selectAll',false,null)">Put text here...</div> In this situation, let's say you want to impose a r ...

Relaunch node.js in pm2 after a crash

Based on this post, it seems that pm2 is supposed to automatically restart crashed applications. However, when my application crashes, nothing happens and the process no longer appears in the pm2 list. Do I need to enable an 'auto restart' featu ...

Enhancing ajax content with Rx.Observable.fromEvent: A step-by-step guide

I am currently fetching content using Ajax, in the form of a json object, which is then displayed in the browser. var stateSubjectSub = stateSubject.subscribe(function(data) { console.log('state changes'); console.log(data); var list = document ...