0

I am writing an Angular app that runs on https://app.example.com:4202. I also have a running angular app that runs on https://app2.example.com:4203. Both of them are dependant on backend that runs at https://example.com.

On every backend php page, I have a test, that checks if user is authorized to access page contents:

if(!isset($_SESSION["id"])){
    http_response_code(403);
    die("Error. Unauthorized user.");  
}

Now, here comes the problem. In order for ajax requests to send cookie information I need to set withCredentials option to true

But because my development angular app runs on 4202 and by Apache backend at 443, I also need to set header('Access-Control-Allow-Origin: *'); in every php file. And thats something you are not allowed to do. I am getting an ajax error: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.

I also tried setting this in my apache example.com virtual host and deleted header('Access-Control-Allow-Origin: *'); in php file:

SetEnvIf Origin ^(https?://.+\.example\.com(?::\d{1,5})?)$   CORS_ALLOW_ORIGIN=$1
Header append Access-Control-Allow-Origin  %{CORS_ALLOW_ORIGIN}e   env=CORS_ALLOW_ORIGIN
Header merge  Vary "Origin"

but in this case, ajax request complains with an error:

The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'.

So my question is, what do you do, if you need user authentication using cookies and you want to have only 1 version of you application (both angular and backend)? The issue seems to be that angular app is running on 4202 and is considered to be of different origin as by backend, which runs on 443. Note that this problem only occurs during development, but I am really hesitant to have 1 version on my local machine and another on server.

potato
  • 4,479
  • 7
  • 42
  • 99

1 Answers1

1

You absolutely don't want to use a wildcard for Access-Control-Allow-Origin, unless you're specifically building a public API.

All you need to do is specify the exact addresses that should be allowed. Think of it as the backend server's white-list for all websites that should be allowed access. In your case, those are the two Angular sites.

So change your header to this:

header('Access-Control-Allow-Origin: https://app.example.com:4202,https://app2.example.com:4203');

That should do it.

While you're at it, add this to a PHP include that you can reuse, so you don't need to add it everywhere.

Edit

It turns out you also need a second header, to explicitly allow credentials.

header('Access-Control-Allow-Credentials: true');

This is needed because you're passing credentials. The Access-Control-Allow-Origin origin I showed before is needed any time you want to call a web service from the browser when the service and client are not hosted on the same server and host.

Cobus Kruger
  • 8,338
  • 3
  • 61
  • 106
  • hmm... I tried with a single url first: `header('Access-Control-Allow-Origin: https://app.example.com:4202');` and got an ajax error: `The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'`. I can see `Access-Control-Allow-Credentials` header in php response though.. – potato Oct 19 '18 at 16:58
  • @brumbrum For that one, the solution is in the error message. You need a header for `Access-Control-Allow-Credentials` that is set to `true`. I'll add it to my answer, for the sake of completeness. – Cobus Kruger Oct 19 '18 at 17:15
  • Ahhh, am such an idiot. Sorry, I totally misread it. They all look alike :D – potato Oct 19 '18 at 18:18