<p>I was having the same issue... but given that there are 15 domains, having the client access the admin cp from each domain isn't really an option.</p>

<p>The key appears to be making sure that you have the following in both the admin cp domain and in the domain being previewed's .htaccess file:</p>

<pre><code>Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Headers "origin, x-requested-with, content-type"
Header set Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS"
</code></pre>

<p>...because you're setting there the origin is allowed.  Caveat regarding overriding CORS apply.</p>

CC BY-SA 3.0
2015-09-17T00:54:41.977Z
I think part of my complication is that the site (thank you MediaTemple) has apache and nginx both, and I need to figure out how to turn on cross-origin requests for both. Will post more if/when I get it solved. Meanwhile, I think you have it nailed for basic apache.
Marion Newlevant
CC BY-SA 3.0
2015-09-18T01:44:31.120Z
This should help you getting it configured with nginx -> http://serverfault.com/questions/162429/how-do-i-add-access-control-allow-origin-in-nginx
andrew.welch
CC BY-SA 3.0
2016-04-12T19:06:36.587Z
This isn't working as you need to be logged in. You get redirected to /login and still get a blank preview.
jlcharette
CC BY-SA 3.0
2015-09-13T16:29:23.337Z
2015-09-13T16:48:58.190Z
2015-09-13T16:48:58.190Z
andrew.welch
<p>Only setting headers in .htaccess doesn't fix the problem.
As <a href="https://craftcms.stackexchange.com/users/130/marion-newlevant">Marion Newlevant</a> points out in her <a href="https://craftcms.stackexchange.com/q/7187/4304">answer</a> the cross domain works with the headers set. But you still get a white page as a preview.</p>

<p>Looking further into the problem, I've found that the page tries to do a post request to the other domain.
It calls upon the action function <strong>actionPreviewEntry()</strong> in the <strong>EntriesController.php</strong> file (Location: <strong>/craft/app/controllers/</strong> )</p>

<p>But because the user isn't logged in on the other domain and anonymous access isn't allowed for this action. You get redirected to /login to login on that domain.</p>

<p>I came up with a quick solution for the problem. It's a bit dirty for now, but the authors of Craft aren't coming with a solution either.</p>

<p><strong>Solution</strong></p>

<ol>
<li><p>Delete (If you have set them) the headers for Access-Control-Allow in your .htaccess file. We don't need them.</p></li>
<li><p>Open the file EntriesController.php in the folder /craft/app/controllers/</p></li>
<li><p>Replace the code.</p>

<p>protected $allowAnonymous = array('actionViewSharedEntry');</p></li>
</ol>

<p>With:</p>

<pre><code>protected $allowAnonymous = array('actionViewSharedEntry','actionPreviewEntry');
</code></pre>

<ol start="4">
<li><p>Add the following code in the public function actionPreviewEntry():</p>

<pre><code>// Set a boolean for logout admin user if cross-domain access
$crossDomainAccess = FALSE;

// Check if the user isn't logged in. Likely meaning that the action is called from another domain.
if ( !craft()-&gt;userSession-&gt;isLoggedIn() ) {

  // Get allowed origins
  $locales = array('en','nl');
  $allowedOrigins = array();
  foreach ( $locales as $locale ) {
    $allowedOrigins[] = craft()-&gt;config-&gt;getLocalized('siteUrl', $locale);
  }

  // Check origin and give access if allowed
  $httpOrigin = $_SERVER['HTTP_ORIGIN'];
  if ( in_array($httpOrigin, $allowedOrigins) ) {
    header('Access-Control-Allow-Origin: ' . $httpOrigin);
    header('Access-Control-Allow-Credentials: true');
    craft()-&gt;userSession-&gt;loginByUserId(1);
    $crossDomainAccess = TRUE;
  }
}
</code></pre></li>
</ol>

<p><em>Explanation of the code:</em></p>

<p>As you can see I set the locales to <strong>en</strong> and <strong>nl</strong>. Because that's the only locales for my website.</p>

<pre><code>$locales = array('en','nl');
</code></pre>

<p>The domains that are allowed to communicate with each other are set in the general config file under siteUrl. See step 4 of the <a href="http://buildwithcraft.com/docs/localization-guide" rel="nofollow noreferrer">localization guide</a> for more information.
We will fetch them here and put them in an array for checking.</p>

<pre><code>$allowedOrigins = array();
foreach ( $locales as $locale ) {
    $allowedOrigins[] = craft()-&gt;config-&gt;getLocalized('siteUrl', $locale);
}
</code></pre>

<p>We check the origin of the request and if it's allowed to communicate with this domain. If so, then set the header to allow cross-domain access.</p>

<p>And automatically login as the admin user to get full access for the preview page to load as if you are logged in on the other domain.</p>

<pre><code>$httpOrigin = $_SERVER['HTTP_ORIGIN'];
if ( in_array($httpOrigin, $allowedOrigins) ) {
    header('Access-Control-Allow-Origin: ' . $httpOrigin);
    header('Access-Control-Allow-Credentials: true');
    craft()-&gt;userSession-&gt;loginByUserId(1);
    $crossDomainAccess = TRUE;
}
</code></pre>

<ol start="5">
<li><p>Next we need to logout the admin user on the other domain. Add the following code:</p>

<p>if ( $crossDomainAccess == TRUE ) {
  craft()->userSession->logout();
}</p></li>
</ol>

<p>Before the line (In the same function, public function actionPreviewEntry()):</p>

<pre><code>$this-&gt;_showEntry($entry);
</code></pre>

<p>And that's it. A quickfix for anyone that has come across this problem and wants to fix it quick but dirty for now.</p>

<p>Note: If you update your craft cms, then this code will get deleted, so you have to add it again after you updated.</p>

<p><strong>If you're using baseCpUrl</strong></p>

<p>Slight modification if you're using the baseCpUrl setting and/or have paths in your settings file:</p>

<pre><code>if ( !craft()-&gt;userSession-&gt;isLoggedIn() ) {

  // Get allowed origins
  $allowedOrigins = array(
          parse_url(craft()-&gt;config-&gt;get('baseCpUrl'), PHP_URL_HOST),
          parse_url(craft()-&gt;config-&gt;getLocalized('siteUrl', 'en_us'), PHP_URL_HOST)
  );

  // Check origin and give access if allowed
  $httpOrigin = parse_url($_SERVER['HTTP_ORIGIN'], PHP_URL_HOST);
  if ( in_array($httpOrigin, $allowedOrigins) ) {
          header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']);
          header('Access-Control-Allow-Credentials: true');
          craft()-&gt;userSession-&gt;loginByUserId(1);
          $crossDomainAccess = TRUE;
  }
}
</code></pre>

<p>Here I've hard-coded the language in, but it can be combined with the answer above instead.</p>

CC BY-SA 3.0
2016-04-13T12:16:26.680Z
Where do you add the first bit of code inside function actionPreviewEntry() ? At the very beginning ?
jlcharette
CC BY-SA 3.0
2016-05-24T15:36:24.457Z
Something has changed in that time in the Craft?
Vitaliy  Badalov
CC BY-SA 3.0
2015-11-05T13:06:00.907Z
2016-02-08T02:12:26.003Z
2017-04-13T12:51:00.303Z
Ruben Webs
<p>I have a multi-locale site set up with the different locales in different domains</p>

<ul>
<li>phoseon.craft.dev - English site</li>
<li>phoseon.it.craft.dev - Italian site</li>
</ul>

<p>etc.</p>

<p>I am having problems getting Live Preview to work with a locale other than English.</p>

<p>The page I am trying to get this to work on, <code>test-single</code>, is a single, with a template that just displays the title (so no complexity there).</p>

<p>When I try to use Live Preview in a locale other than English, I get this error in the console:</p>

<blockquote>
  <p>Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at <a href="http://phoseon.it.craft.dev/" rel="nofollow noreferrer">http://phoseon.it.craft.dev/</a>. This can be fixed by moving the resource to the same domain or enabling CORS.</p>
</blockquote>

<p>And no Live Preview, just a white screen.</p>

<p>Based on <a href="https://craftcms.stackexchange.com/a/430/130">this answer</a> I added this to .htaccess for <a href="http://phoseon.it.craft.dev" rel="nofollow noreferrer">http://phoseon.it.craft.dev</a></p>

<pre><code>Header add Access-Control-Allow-Origin "http://phoseon.craft.dev"
</code></pre>

<p>And now I see these requests, and still a white screen for the Live Preview:</p>

<pre><code>POST http://phoseon.it/craft.dev/test-single 302 Found
  Request Headers:
    Accept  */*
    Accept-Encoding gzip, deflate
    Accept-Language en-US,en;q=0.5
    Content-Length  198
    Content-Type  application/x-www-form-urlencoded; charset=UTF-8
    Host  phoseon.it.craft.dev
    Origin  http://phoseon.craft.dev
    Referer http://phoseon.craft.dev/admin/entries/testSingle/1742-testsingle/it_it
    User-Agent  Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:35.0) Gecko/20100101 Firefox/35.0
  Response Headers:
    Access-Control-Allow-Orig...  http://phoseon.craft.dev
    Cache-Control no-store, no-cache, must-revalidate, post-check=0, pre-check=0
    Connection  Keep-Alive
    Content-Encoding  gzip
    Content-Length  2346
    Content-Type  text/html
    Date  Mon, 16 Feb 2015 20:38:14 GMT
    Expires Thu, 19 Nov 1981 08:52:00 GMT
    Keep-Alive  timeout=5, max=100
    Location  http://phoseon.it.craft.dev/login
    Pragma  no-cache
    Server  Apache/2.2.26 (Unix) DAV/2 PHP/5.4.30 mod_ssl/2.2.26 OpenSSL/0.9.8zc
    Set-Cookie  CraftSessionId=gtm75r2a9it49820uueam9hpe2; path=/; HttpOnly
    Vary  User-Agent,Accept-Encoding
    X-Powered-By  PHP/5.4.30

  And the response is the site's 404 page

GET http://phoseon.it.craft.dev/login 404 Not Found
  Request Headers:
    Accept  */*
    Accept-Encoding gzip, deflate
    Accept-Language en-US,en;q=0.5
    Content-Type  application/x-www-form-urlencoded; charset=UTF-8
    Host  phoseon.it.craft.dev
    Origin  http://phoseon.craft.dev
    Referer http://phoseon.craft.dev/admin/entries/testSingle/1742-testsingle/it_it
    User-Agent  Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:35.0) Gecko/20100101 Firefox/35.0
  Response Headers:
    Access-Control-Allow-Orig...  http://phoseon.craft.dev
    Cache-Control no-store, no-cache, must-revalidate, post-check=0, pre-check=0
    Connection  close
    Content-Encoding  gzip
    Content-Length  42163
    Content-Type  text/html; charset=utf-8
    Date  Mon, 16 Feb 2015 20:38:14 GMT
    Expires Thu, 19 Nov 1981 08:52:00 GMT
    Pragma  no-cache
    Server  Apache/2.2.26 (Unix) DAV/2 PHP/5.4.30 mod_ssl/2.2.26 OpenSSL/0.9.8zc
    Set-Cookie  CraftSessionId=isldd40afpu41mr9as659f6rs7; path=/; HttpOnly
    Vary  User-Agent,Accept-Encoding
    X-Powered-By  PHP/5.4.30
    charset utf-8

  And the response is agin the site's 404 page
</code></pre>

<p>Anyone else encountered this? Know what's going on? Recommended fixes?</p>

CC BY-SA 3.0
2015-04-27T07:54:25.450Z
Did this ever get resolved?
Patrick Nesbitt
CC BY-SA 3.0
2015-07-18T16:18:55.807Z
@PatrickNesbitt - still happening. work-around has been to use the control panel through the locale's url: http://phoseon.it.craft.dev/admin
Marion Newlevant
<htaccess><live-preview>
Multi locale, multi-domain Live Preview failing
# Multi locale, multi-domain Live Preview failing

(Asked by: username_0 on 2015-02-16)

I have a multi-locale site set up with the different locales in different domains

phoseon.craft.dev - English site
phoseon.it.craft.dev - Italian site

etc.
I am having problems getting Live Preview to work with a locale other than English.
The page I am trying to get this to work on, test-single, is a single, with a template that just displays the title (so no complexity there).
When I try to use Live Preview in a locale other than English, I get this error in the console:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://phoseon.it.craft.dev/. This can be fixed by moving the resource to the same domain or enabling CORS.

And no Live Preview, just a white screen.
Based on this answer I added this to .htaccess for http://phoseon.it.craft.dev
Header add Access-Control-Allow-Origin "http://phoseon.craft.dev"

And now I see these requests, and still a white screen for the Live Preview:
POST http://phoseon.it/craft.dev/test-single 302 Found
  Request Headers:
    Accept  */*
    Accept-Encoding gzip, deflate
    Accept-Language en-US,en;q=0.5
    Content-Length  198
    Content-Type  application/x-www-form-urlencoded; charset=UTF-8
    Host  phoseon.it.craft.dev
    Origin  http://phoseon.craft.dev
    Referer http://phoseon.craft.dev/admin/entries/testSingle/1742-testsingle/it_it
    User-Agent  Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:35.0) Gecko/20100101 Firefox/35.0
  Response Headers:
    Access-Control-Allow-Orig...  http://phoseon.craft.dev
    Cache-Control no-store, no-cache, must-revalidate, post-check=0, pre-check=0
    Connection  Keep-Alive
    Content-Encoding  gzip
    Content-Length  2346
    Content-Type  text/html
    Date  Mon, 16 Feb 2015 20:38:14 GMT
    Expires Thu, 19 Nov 1981 08:52:00 GMT
    Keep-Alive  timeout=5, max=100
    Location  http://phoseon.it.craft.dev/login
    Pragma  no-cache
    Server  Apache/2.2.26 (Unix) DAV/2 PHP/5.4.30 mod_ssl/2.2.26 OpenSSL/0.9.8zc
    Set-Cookie  CraftSessionId=gtm75r2a9it49820uueam9hpe2; path=/; HttpOnly
    Vary  User-Agent,Accept-Encoding
    X-Powered-By  PHP/5.4.30

  And the response is the site's 404 page

GET http://phoseon.it.craft.dev/login 404 Not Found
  Request Headers:
    Accept  */*
    Accept-Encoding gzip, deflate
    Accept-Language en-US,en;q=0.5
    Content-Type  application/x-www-form-urlencoded; charset=UTF-8
    Host  phoseon.it.craft.dev
    Origin  http://phoseon.craft.dev
    Referer http://phoseon.craft.dev/admin/entries/testSingle/1742-testsingle/it_it
    User-Agent  Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:35.0) Gecko/20100101 Firefox/35.0
  Response Headers:
    Access-Control-Allow-Orig...  http://phoseon.craft.dev
    Cache-Control no-store, no-cache, must-revalidate, post-check=0, pre-check=0
    Connection  close
    Content-Encoding  gzip
    Content-Length  42163
    Content-Type  text/html; charset=utf-8
    Date  Mon, 16 Feb 2015 20:38:14 GMT
    Expires Thu, 19 Nov 1981 08:52:00 GMT
    Pragma  no-cache
    Server  Apache/2.2.26 (Unix) DAV/2 PHP/5.4.30 mod_ssl/2.2.26 OpenSSL/0.9.8zc
    Set-Cookie  CraftSessionId=isldd40afpu41mr9as659f6rs7; path=/; HttpOnly
    Vary  User-Agent,Accept-Encoding
    X-Powered-By  PHP/5.4.30
    charset utf-8

  And the response is agin the site's 404 page

Anyone else encountered this? Know what's going on? Recommended fixes?

**Tags:** htaccess, live-preview

> **Comments:**
> **username_1**: Did this ever get resolved?  
> **username_0**: @PatrickNesbitt - still happening. work-around has been to use the control panel through the locale's url: http://phoseon.it.craft.dev/admin  

---

## 2 answers

### Answer by username_2 on 2015-09-13. Score: 1 | Accepted answer

I was having the same issue... but given that there are 15 domains, having the client access the admin cp from each domain isn't really an option.
The key appears to be making sure that you have the following in both the admin cp domain and in the domain being previewed's .htaccess file:
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Headers "origin, x-requested-with, content-type"
Header set Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS"

...because you're setting there the origin is allowed.  Caveat regarding overriding CORS apply.

> **Comments:**
> **username_0**: I think part of my complication is that the site (thank you MediaTemple) has apache and nginx both, and I need to figure out how to turn on cross-origin requests for both. Will post more if/when I get it solved. Meanwhile, I think you have it nailed for basic apache.  
> **username_2**: This should help you getting it configured with nginx -> http://serverfault.com/questions/162429/how-do-i-add-access-control-allow-origin-in-nginx  
> **username_3**: This isn't working as you need to be logged in. You get redirected to /login and still get a blank preview.  

---

### Answer by username_4 on 2015-11-05. Score: 3

Only setting headers in .htaccess doesn't fix the problem.
As username_0 points out in her answer the cross domain works with the headers set. But you still get a white page as a preview.
Looking further into the problem, I've found that the page tries to do a post request to the other domain.
It calls upon the action function actionPreviewEntry() in the EntriesController.php file (Location: /craft/app/controllers/ )
But because the user isn't logged in on the other domain and anonymous access isn't allowed for this action. You get redirected to /login to login on that domain.
I came up with a quick solution for the problem. It's a bit dirty for now, but the authors of Craft aren't coming with a solution either.
Solution

Delete (If you have set them) the headers for Access-Control-Allow in your .htaccess file. We don't need them.
Open the file EntriesController.php in the folder /craft/app/controllers/
Replace the code.
protected $allowAnonymous = array('actionViewSharedEntry');

With:
protected $allowAnonymous = array('actionViewSharedEntry','actionPreviewEntry');


Add the following code in the public function actionPreviewEntry():
// Set a boolean for logout admin user if cross-domain access
$crossDomainAccess = FALSE;

// Check if the user isn't logged in. Likely meaning that the action is called from another domain.
if ( !craft()->userSession->isLoggedIn() ) {

  // Get allowed origins
  $locales = array('en','nl');
  $allowedOrigins = array();
  foreach ( $locales as $locale ) {
    $allowedOrigins[] = craft()->config->getLocalized('siteUrl', $locale);
  }

  // Check origin and give access if allowed
  $httpOrigin = $_SERVER['HTTP_ORIGIN'];
  if ( in_array($httpOrigin, $allowedOrigins) ) {
    header('Access-Control-Allow-Origin: ' . $httpOrigin);
    header('Access-Control-Allow-Credentials: true');
    craft()->userSession->loginByUserId(1);
    $crossDomainAccess = TRUE;
  }
}


Explanation of the code:
As you can see I set the locales to en and nl. Because that's the only locales for my website.
$locales = array('en','nl');

The domains that are allowed to communicate with each other are set in the general config file under siteUrl. See step 4 of the localization guide for more information.
We will fetch them here and put them in an array for checking.
$allowedOrigins = array();
foreach ( $locales as $locale ) {
    $allowedOrigins[] = craft()->config->getLocalized('siteUrl', $locale);
}

We check the origin of the request and if it's allowed to communicate with this domain. If so, then set the header to allow cross-domain access.
And automatically login as the admin user to get full access for the preview page to load as if you are logged in on the other domain.
$httpOrigin = $_SERVER['HTTP_ORIGIN'];
if ( in_array($httpOrigin, $allowedOrigins) ) {
    header('Access-Control-Allow-Origin: ' . $httpOrigin);
    header('Access-Control-Allow-Credentials: true');
    craft()->userSession->loginByUserId(1);
    $crossDomainAccess = TRUE;
}


Next we need to logout the admin user on the other domain. Add the following code:
if ( $crossDomainAccess == TRUE ) {
  craft()->userSession->logout();
}

Before the line (In the same function, public function actionPreviewEntry()):
$this->_showEntry($entry);

And that's it. A quickfix for anyone that has come across this problem and wants to fix it quick but dirty for now.
Note: If you update your craft cms, then this code will get deleted, so you have to add it again after you updated.
If you're using baseCpUrl
Slight modification if you're using the baseCpUrl setting and/or have paths in your settings file:
if ( !craft()->userSession->isLoggedIn() ) {

  // Get allowed origins
  $allowedOrigins = array(
          parse_url(craft()->config->get('baseCpUrl'), PHP_URL_HOST),
          parse_url(craft()->config->getLocalized('siteUrl', 'en_us'), PHP_URL_HOST)
  );

  // Check origin and give access if allowed
  $httpOrigin = parse_url($_SERVER['HTTP_ORIGIN'], PHP_URL_HOST);
  if ( in_array($httpOrigin, $allowedOrigins) ) {
          header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']);
          header('Access-Control-Allow-Credentials: true');
          craft()->userSession->loginByUserId(1);
          $crossDomainAccess = TRUE;
  }
}

Here I've hard-coded the language in, but it can be combined with the answer above instead.

> **Comments:**
> **username_3**: Where do you add the first bit of code inside function actionPreviewEntry() ? At the very beginning ?  
> **username_5**: Something has changed in that time in the Craft?  

---

