20

(continuation of error message in title) " Origin 'http://127.0.0.1:4200' is therefore not allowed access."

I am unable to run the same Angular 5 site on two different domains when working with the same API.

This error message is coming from Chrome. The error in Firefox is:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://myapitest.local/v1/subscription/current/products. (Reason: CORS header ‘Access-Control-Allow-Origin’ does not match ‘http://127.0.0.1:4200’)

I noticed this when working on a white-labeled version of our Angular app that will be running on an alternative URL from our regular app, but still using the same Laravel api running on the same URL. I've added the appropriate CORS configuration to Laravel, this appears to be a browser issue - not sure how to get around it.

I have recreated this at localhost by changing from localhost:4200 to 127.0.0.1:4200 for instance.

Oddly, the preflight seems to be successful with correct CORS headers. enter image description here

However, on the GET, it seems to come back with the WRONG Access-Control-Allow-Origin header on the response.
enter image description here

Worth noting here that changing my Allowed Origins in the API to allow all ('*') does not fix this issue.

I'm not sure what other information or code I could provide to make this clearer. Thanks.

QuietSeditionist
  • 703
  • 4
  • 8
  • 18
  • I'm getting the same problem when accessing map tiles from geoserver from both localhost:4200 and our deployed site. Sometimes ctrl-f5 fixes it but not always in chrome. I've tried clearing application data from both sites in browser. Did you find a way around this @QuietSeditionist? – andyb Dec 09 '20 at 09:57
  • Fixed it by disabling cache temporarily in network tab of chrome dev tools. Weird, aggressive caching though. – andyb Dec 09 '20 at 10:12

7 Answers7

7

Let's assume your api runs on 8080 and your angular code on 4200.

In your angular app create a file called proxy.conf.json

{
    "/api/": {
        "target": "http://localhost:8080/",
        "secure": false,
        "changeOrigin": true
    }
}

Start angular app using this command

ng serve --port 4200 --proxy-config proxy.conf.json

With this configuration when you call localhost:4200/api you it will call 8080 and it won't have any CORS error

louisfischer
  • 1,968
  • 2
  • 20
  • 38
Mesut Gölcük
  • 134
  • 1
  • 6
  • 3
    This will not allow testing when crossing between domains, and it removes all security. –  Dec 11 '18 at 00:58
  • 2
    How does this method apply to a production environment? – QuietSeditionist Dec 13 '18 at 01:49
  • @QuietSeditionist After ng build --prod you can serve it with backend in production. This solves local development problem when two local application needs to communicate with each other. If you especially want to use ng serve you can create environment specific another file like proxy.conf.prod.json and call ng serve with that file. – Mesut Gölcük Dec 14 '18 at 08:50
  • This looks like a good approach for the **development-time** issue while testing the API and client on different ports/machines. By calling the API without schema/host/port, the same URL is usable in production without changes to the code - just skip the proxy (assuming in production environment, the API and client are deployed within one single site) – avat Jan 25 '23 at 07:38
1

i think you using web.php for this routes on the top of the file please use this and try

 <?php
  header('Access-Control-Allow-Origin: *');
  header('Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE');
  header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization, X-CSRF-Token");

Route::get('/login', 'Auth\LoginController@showLoginForm');
Hamelraj
  • 4,676
  • 4
  • 19
  • 42
  • 1
    1) I am using Laravel, so this is not applicable. 2) I already stated that I do not wish to allow access to the API from all origins and neither does including '*' solve the issue. -- How do you propose that this would solve my issue?? – QuietSeditionist Dec 05 '18 at 19:24
0

You can set proxy for the request provided by the angular webpack developement server. By using the proxy you can change the backend URL as originated from the angular domain hosted URL. This will be achieved by --proxy-config in your serve command or package.json. so that angular will be run in different URls with same backend service.

add a file named proxy.conf.json near the package.json. from your Request get URL add /proxy

In your proxy.conf file add this

{
  "/proxy": {
  "target": "http://localhost:3000",
  "secure": false,
  "pathRewrite": {
  "^/proxy": ""
 }
}

change your serve command as

ng serve --proxy-config proxy.conf.json --port 4200 --host 0.0.0.0

or

in your angular.json change the serve target

"architect": {
    "serve": {
    "builder": "@angular-devkit/build-angular:dev-server",
    "options": {
    "browserTarget": "your-application-name:build",
    "proxyConfig": "proxy.conf.json"
 },

Note: make sure to add /proxy in your Http service URL and Proxy configuration in only for the development purpose

For the production environment You should configure in the webservers.

esakki
  • 153
  • 1
  • 9
  • Thanks for the obvious effort @esakki, but can you help me understand: 1) What is the intent behind setting up a proxy? and 2) how to configure that in a deployment? – QuietSeditionist Dec 05 '18 at 14:51
  • CORS error occurs where your request is from one domain to outside the domain or different port. from proxy pass your backend API call URL will be modified with the replacement of request originated domain ex; [http://localhost:8080/profile/rootData] is modified as [http://localhost:4200/proxy/profile/rootData] – esakki Dec 06 '18 at 09:19
  • for deployment you can configure in your web servers for apache using mod_proxy ServerName localhost DocumentRoot /var/www/html/dist ProxyPass /proxy/* http://localhost:8080/ ProxyPassReverse /proxy/* http://localhost:8080/ – esakki Dec 06 '18 at 09:27
0

Setup a reverse proxy server and configure paths for both the domains.
Nginx Guide

This will allow you to access everything via http://localhost/
Let's assume:
A -> Angular App (localhost:4200)
B -> Your other domain API (myapitest.local)

Example Flow:
- Browser Request(http://localhost/angular) -> Nginx -> A
- Load Data from backend -> Nginx -> B

So, with the help of Nginx, you will be able to access "A" from http://localhost/ and "B" also from http://localhost/
Since, the origin is same, there will be no CORS error.

Saddam Pojee
  • 1,518
  • 9
  • 14
0

The problem is in the Name mapping. Since a server pool may have multiple IP addresses, most browsers map the IP address to a name. This is normally done through the requested DNS name. In your case there is no name, so it is looking up the IP address in the hosts file(/etc/hosts on Linux or C:\Windows\System32\Drivers\etc\Hosts on Windows) and returning the name from there.

Since you need to test across domains(act as 2 separate servers), add a line to your hosts file pointing myapitest.local to 127.0.0.2 . And a line myapitest2.local to 127.0.0.3 . This will allow your local naming to match the IP addresses and with proper configuration(specifying a specific listening address to bind to, for each server instance) each server instance can then run on port 80.

Use names in all Cross origin requests and authorizations.

Edit

The wildcard does not work due to Access-Control-Allow-Credentials: true.

On the dev-api.ourdomain.com server: Add a Response Header to the route file Routes/api.php that builds the Access-Control-Allow-Origin: header for approved domains. You can also apply this as Middleware, but for simplicity, I will demonstrate with simple routes. This must also be done for the preflight routes.

Route::get('/method/{id}', function (Request $request, $id) {
    $retval = method($id);
    $origin_allowed = $request->header('HTTP_ORIGIN');
    $allowed = array("dev.ourdomain.com", "dev.alternatedomain.com");
    if(in_array($origin_domain, $allowed))
        return ($retval)->header('Access-Control-Allow-Origin:',$origin_domain);
    else 
        return "Unauthorized";
});

This is just example code to demonstrate the concept.

Make sure you are clearing HTTP authorizations and csrf tokens on logout.

  • This solution does not use proxies and can simulate a production environment. –  Dec 11 '18 at 01:02
  • how does this apply to a deployment environment? When I first discovered this issue, it was in our integration environment where I would run into the issue when accessing the app via (as an example) dev.ourdomain.com and then attempting to log out and in to the white label version of the app at dev.alternatedomain.com. Both of these access the api at the same URL, dev-api.ourdomain.com. – QuietSeditionist Dec 11 '18 at 14:10
  • @QuietSeditionist, I feel like I either, missed the question or the last comment. If you could be more clear on the outcome you are looking for, it would be helpful. –  Dec 12 '18 at 02:13
  • 1
    Laravel takes care of all of this. I only configure the allowed origins, which is done. The issues comes when Chrome refuses to even make the call to the API based on its cached (apparently) origin header from a previous call. – QuietSeditionist Dec 13 '18 at 01:51
0

You may have installed HTTPS Everywhere extension. Make sure you Disable HTTPS Everywhere on Localhost. That's what was causing me this problem.

-3

add this in your public/index.php file

header('Access-Control-Allow-Origin: *');
Shailendra Gupta
  • 1,054
  • 6
  • 15
  • Then you have to put exact route to allow origin – Shailendra Gupta Oct 31 '18 at 16:38
  • I already have all of the acceptable origins specified in the Laravel API. – QuietSeditionist Oct 31 '18 at 17:10
  • Thank you for the snippet, which might provide some limited, immediate help. A proper explanation would greatly improve its [long-term value](https://meta.stackexchange.com/q/114762/206345) by describing why this is a good solution to the problem, and would make it more useful to future readers with other similar questions. Please edit your answer to add some explanation, including the assumptions you've made. – sepehr Oct 31 '18 at 17:27