Redirect to authentication for CORS request using XMLHttpRequest

Hi,

I went through the installation of Node.js and Express Tutorial: Authentication Using Passport which runs on localhost:3000 (or with a custom local domain localist.com:3000)

Now, I added a new endpoint that I want to call from localhost:3002 (it requires CORS)

This is my endpoint on localhost:3000

app.post("/items", secured, (req, res, next) => {
  try {
    res.send('Something')
  } catch (err) {
    next(err);
  }
});

This is my call from localhost:3002 (copy/paste from somewhere else).

console.log( 'loading main.js' );
const btn = document.getElementById('add-to-list')
const url = 'http://localist.com:3000/items'

function sendData( data ) {
  console.log( 'Sending data' );

  const XHR = new XMLHttpRequest();

  let urlEncodedData = "",
      urlEncodedDataPairs = [],
      name;

  // Turn the data object into an array of URL-encoded key/value pairs.
  for( name in data ) {
    urlEncodedDataPairs.push( encodeURIComponent( name ) + '=' + encodeURIComponent( data[name] ) );
  }

  // Combine the pairs into a single string and replace all %-encoded spaces to
  // the '+' character; matches the behavior of browser form submissions.
  urlEncodedData = urlEncodedDataPairs.join( '&' ).replace( /%20/g, '+' );

  // Define what happens on successful data submission
  XHR.addEventListener( 'load', function(event) {
    console.log( 'Response is: ' + XHR.response);
  } );

  // Define what happens in case of error
  XHR.addEventListener( 'error', function(event) {
    console.error( 'Oops! Something went wrong.' );
  } );

  // Set up our request
  XHR.open( 'POST', url );

  // Add the required HTTP header for form data POST requests
  XHR.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );

  // Finally, send our data.
  XHR.send( urlEncodedData );
}

btn.addEventListener( 'click', function() {
  sendData( {test:'ok'} );
} )

I set up cors and my POST call works as long as I don’t add the secured. If I do, the call fails because localhost:3000 doesnt seem to pick up any credentials and I get the following error:

Access to XMLHttpRequest at 'https://tirelire.eu.auth0.com/authorize?scope=openid%20email%20profile&nonce=92556d3b157611b49ee879add630309d&response_type=code&redirect_uri=http%3A%2F%2Flocalist.com%3A3000%2Fcallback&state=0H9vhAcGwBmAaSaiyx2eOXaU&client_id=qUJXOW0tpO5BG2EUXWwIdJJ8h8lfuWVN' (redirected from 'http://localist.com:3000/items') from origin 'http://localist.com:3002' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
main.js:31 Oops! Something went wrong.
(anonymous) @ main.js:31
error (async)
sendData @ main.js:30
(anonymous) @ main.js:45
main.js:41 GET https://tirelire.eu.auth0.com/authorize?scope=openid%20email%20profile&nonce=92556d3b157611b49ee879add630309d&response_type=code&redirect_uri=http%3A%2F%2Flocalist.com%3A3000%2Fcallback&state=0H9vhAcGwBmAaSaiyx2eOXaU&client_id=qUJXOW0tpO5BG2EUXWwIdJJ8h8lfuWVN net::ERR_FAILED

I woudn’t expect to see any redirect but a reuse of existing credentials from the session or cookies. I understand why req.user is empty but then what am I supposed to use instead to avoid the redirect to the login?

This is how secured looks like (which understandably redirect to login because req.user is undefined)

const secured = (req, res, next) => {
  if (req.user) {
    return next();
  }
  req.session.returnTo = req.originalUrl;
  res.redirect("/login");
};

Any e2e example that I could use or an explanation of what I am doing wrong? I have seen many posts with similar question but I don’t seem to find anything that solves my problem

Thanks

So I found the solution I think (I should post more often)

On the client side (:3002), add

 XHR.withCredentials = true;

On the server side (:3000), add a credentials key

app.use(cors({
  origin: 'http://localist.com:3002',
  credentials: true
}));
1 Like

Perfect! Thanks for sharing it with the rest of community!

This topic was automatically closed 15 days after the last reply. New replies are no longer allowed.