CORS Request Block - Same Origin Policy

Hello, I’m working on my first custom Twitch Extension and have been following along with the Extension 101 Tutorial Series ( JSON Web Tokens (JWT) | Twitch Developers ) while making my extension. I’m having a hard time figuring out a CORS issue which is shown below. Prior to, allow me to briefly explain the project:

In my extension, one of four buttons are pressed calling a JS function which runs:

  type: 'POST',
  url: location.protocol + '//localhost:3000/words',
  data: JSON.stringify( {term: word, difficulty: difficulty_level} ),
  contentType: 'application/json',
  headers: { 'Authorization': 'Bearer ' + token }

On my backend JS file the following related code is executed:

app.use((req, res, next) => {
    res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With');
    res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST');
    res.setHeader('Access-Control-Allow-Origin', '*');

const key = "omitted for obvious reasons";
const secret = Buffer.from( key, 'base64');

//JWT - Bearer Prefix 
const bearerPrefix = 'Bearer '; 

function verifyAndDecode(header) {
    if (header.startsWith(bearerPrefix)) {
        try {
            const token = header.substring(bearerPrefix.length);
            return jsonwebtoken.verify(token, secret, { algorithms: ['HS256'] });
        catch (e) {
            return console.log('Invalid JWT');

//Mongoose - Model
var Word = mongoose.model("Word", {
    userID: String,
    term: String,
    difficulty: String,

//Express - POST Route"/words", (req, res) => {
    const payload = verifyAndDecode(req.headers.authorization);
    const { channel_id: channelId, opaque_user_id: opaqueUserId } = payload;
    var newWord = new Word({
        userID: payload.opaque_user_id, 
        term: req.body.term, 
        difficulty: req.body.difficulty}); (err) {
        if (err) handleError( err );

The error received when pressing one of my buttons is:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:3000/words. (Reason: CORS request did not succeed). Status code: (null).

Additionally, I get the same error whenever trying to get the words in my live configuration.

      	type: 'GET',
      	url: location.protocol + '//localhost:3000/words',
     	success: function(response) {
        	var trHTML = '';
        	$.each(response, function(i, item) {
          		trHTML += '<tr><th>' + item.term + ' | ' + item.difficulty + '</td></tr>';

Backend code is as follows:

app.get('/words', (req, res) => {
    Word.find({}).then(function(words) {

Is there something wrong with my code? Is the protocol location not set up correctly?

Your server serving the HTML/JS/CSS to be embedded in the iframe on Twitch has it’s own CSP headers preventing communications.

see also

The errors suggests the problem is not your EBS but in the FrontEnd server.

Thank you for the quick and informative reply.

Though I am still pretty confused as I am still learning; If I follow along with “Twitch Extensions Part 6 – Dev Environment Updates – Content Security Policy!” and modify my code to consider CSP headers then it will permit communication between the front end and back end?

Also, are any plans to update the Extension 101 tutorial series to reflect these changes? As of now, the tutorial does not work when reaching the backend section. It is a lot of information and jargon to process in order to understand the solution without examples in relation to the code to highlight the mechanics of what is going on. Though Extensions | Twitch Developers does sort of do a good job of explaining things the Extension 101 tutorial series should really mention this.

That depends as the error you have stated appears to be an error in the frontend server.

But if you are following the 101 Guide then the error shouldn’t be present.

But it’s a very outdated guide.

At the end of the day, an extensions is LITERALLY just a website where the backend and frontend are no different servers, and theres no server side rendering on the frontend.

With one rule of “include and invoke the Twitch JS helper”

So if you can build a website then you can build an extension.

The tutorial goes thru some extra bits such has how to verify a message sent via AJAX from the frontend is from an extension or not. Which you could also totally skip.

So, if this doesn’t make sense, skip it and just start building your extension based on the knowledge that it is JUST a website at the end of the day.

As to if it will get update I don’t know, most of the examples and tutorials in the docs/TwitchDev github are super out of date both just in general changes to extensions but the old Twitch API being removed.

1 Like