No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access


#1

I am trying to use omniauth to direct my client to an external services authorization page. My client uses ember.js and my server is a rails server. As things stand, I am able to make the call with little problem on my server side, but my client will not redirect, throwing me an error reading

Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access. The response had HTTP status code 404.

Doing some research has shown that I need to use CORS, which I have installed and configured. Now I just need to know where and how I apply the access-control-allow-origin header to my code. my adapter:

  recieve_donation(params){
    const api = this.get('host');
    const url = `${api}/auth/coinbase`;
    // , {data: params}
    return this.ajax(url, 'GET');
  },

I assume that I need to apply the header here, but I am not sure what the syntax would look like. Can anyone help me with this problem?


#2

You only have to add the Access-Control-Allow-Origin: * on your server. On the Ember side we only do something like this:

Ember.$.getJSON('https://www.martinic.com/eurprice/', {store: store, product: product}, (result) => {
  let euroPrice = result.data[0].attributes.price;
  this.set('euroPrice', euroPrice);
});

It should work with your code without a change.


#3

I have set this on my server (and my server is going to the authorization url and hangs, waiting for the client to catch up). I know that I am broadly in the correct conceptual neighborhood, but I am not sure how to actually redirect ember to the url. My ideal solution would be to simply plug the authorization URL into window.location.replace(‘authorizationURL’), but I do not know if this is even possible (as the generation of this URL is a side effect of my server, not the main element).

When I check my network tab after the request is made, however, the origin is still listed as null. I have tried to apply the following to my adapter, but the browser throws out the headers when I try to send the request:

recieve_donation(params){
    const api = this.get('host');
    const url = `${api}/auth/coinbase`;
    const headers = {
      'Origin': api
    };
    // , {data: params}
    return this.ajax(url, 'GET');
  },

This has been a super frustrating error, because it feels like the more research and testing I do, the less clear the solution becomes


#4

If I understand you correctly you have CORS enabled on your server but it is not enabled on the Auth server. You can’t access the Auth server with Ember is this case.

You then have 2 options. Let your server handle the communication with the Auth server and let your Ember App only talk to your server. Or create a Proxy on your server that adds the CORS header. You can test if Proxy works for you with

  const url = `https://crossorigin.me/${api}/auth/coinbase`;

If it does write your own Proxy because crossorigin.me is sometimes down.


#5

This hits the nail on the head. The problem is that the request made by coinbase (the site I am trying to authorize my app to use) has an Origin header of null, meaning I need to find some way to get my client to accept this request and redirect to the auth site.

The first option is ideal, but I cannot really implement it unless I can find some way to send my browser to the auth URL, which means using the auth URL and redirecting away from my ember application. Seeing as the generation of this auth url is a side effect, I do not even know if it is possible to do this (I am also using the rails omniauth Gem, which streamlines the process; I am not entirely sure if it can be broken up on the client side while continuing to function in the same way server-side).

Either way, the solution to my problem seems to be on the server side. If there is a simple client side solution that would allow me to redirect to the auth landing page despite the request’s null origin, I would love to hear about it.


#6

There really is no client side solution. Stop searching :wink:


#7

I just found this file buried in the template (I am using a preconfigured ember template, rather than vanilla ember):

<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
  <!-- Read this: www.adobe.com/devnet/articles/crossdomain_policy_file_spec.html -->

  <!-- Most restrictive policy: -->
  <!-- <site-control permitted-cross-domain-policies="none"/> -->

  <!-- Least restrictive policy: -->

  <site-control permitted-cross-domain-policies="all"/>
  <allow-access-from domain="*" to-ports="*" secure="false"/>
  <allow-http-request-headers-from domain="*" headers="*" secure="false"/>

</cross-domain-policy>

I thought that setting the least restrictive policy would negate this error, but it is still here. Do I need to specify further regarding access controls? Or if I have the unrestricted policy turned on, is it just a matter of reconfiguring my back end until it can stick?

EDIT: I just realized what you were talking about re:using a proxy. I am proxying ember over the server. I am getting the same error, but the origin of the request is no longer null; it is now coming from my localhost. Does this mean I now need to reconfigure cors in such a way that it can accept requests from my localhost on the back end?


#8

I am talking about using a proxy that adds the Access-Control-Allow-Origin: * to access the ${api}/auth/coinbase. Did changing it to https://crossorigin.me/${api}/auth/coinbase work?


#9

Changing it to use crossorigin causes a 405 no method error, but does effectively establish the origin as the client side localhost. When I switch to this URL, however, neither my client nor server is directed to the third party API I am trying to use. I cannot figure out if this is a step forward or backwards. Is there some configuration I need to do at crossorigin.me?


#10

No you don’t need configuration. I think that if this does not work work with coinbase you will have to go for option 1 and manage the Auth part on your own server.


#11

I don’t know if you have any experience in rails, but is it even possible for my server to just jump over the client and force the browser to redirect to the auth page? If I knew how to do this, it would be far simpler, as I would not really need to deal with AJAX.

Also, for the sake of clarity Here is the client side output logs/network requests when I attempt to make the cross domain request. This may make it easier to illustrate the problem I am facing/diagnose it.


#12

This is something different than accessing an API with this.ajax(url, 'GET'); This will work without CORS. You can setup the login in Ember but you still need some server side part to hide your API access tokens. After your login you still can’t access the API from Ember if it does not support CORS.


#13

That’s what I figured. The problem here is that the authorization page is not a static URL; it is being defined by an omniauth initializer on my back end:

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :coinbase, ENV['CLIENT_ID'], ENV['CLIENT_SECRET'],
  scope: 'wallet:user:read wallet:user:email wallet:accounts:read wallet:transactions:send wallet:transactions:send:bypass-2fa',
  :meta => {'send_limit_amount' => 5}
end

Which produces a URL like this (I am pretty sure this is the callback created in my routes):

https://www.coinbase.com/oauth/authorize?client_id=56816398d4a5299e4c5ddcfcfafd7f85a6e1ba2617b2fb1ce42cbe5fa32f8ac3&meta%5Bsend_limit_amount%5D=5&redirect_uri=http%3A%2F%2Flocalhost%3A4741%2Fauth%2Fcoinbase%2Fcallback&response_type=code&scope=wallet%3Auser%3Aread+wallet%3Auser%3Aemail+wallet%3Aaccounts%3Aread+wallet%3Atransactions%3Asend+wallet%3Atransactions%3Asend%3Abypass-2fa&state=9cdc89c0f64cdb330d0c3247281ab32c8f5fb26cc81b74db

Ideally, I’d like to be able to take this url and simply redirect the app with window.location.replace, but I am not sure if this is even possible.