So I know there's a lot of CORS posts out there, and I'm just adding to them, but I can't find any with answers that help me out. So I'm building an angular 4 application that relies on my php api. Working locally it's fine, the moment I toss it up on the domain with the app at app.example.com
, and the api at api.example.com
, I can't get past my login, because I get the following error:
XMLHttpRequest cannot load http://api.example.com/Account/Login. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://app.example.com' is therefore not allowed access.
My php code looks like this:
$http_origin = $_SERVER['HTTP_ORIGIN'];
$allowed_domains = array(
'http://example.com',
'https://example.com',
'http://app.example.com',
'https://app.example.com',
'http://www.example.com',
'https://www.example.com'
);
if (in_array(strtolower($http_origin), $allowed_domains))
{
// header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Origin: $http_origin");
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Max-Age: 86400');
}
// Access-Control headers are received during OPTIONS requests
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
header("Access-Control-Allow-Headers: Authorization, Content-Type,Accept, Origin");
exit(0);
}
My Angular post looks like this:
public login(login: Login): Observable<LoginResponse> {
let headers = new Headers();
headers.append('Content-Type', 'application/x-www-form-urlencoded');
headers.append('Authorization', 'Basic ' + btoa(login.Username + ':' + login.Password));
return this.http.post(this.apiBaseUrl + '/Account/Login', "grant_type=client_credentials", { headers: headers })
.map(response => {
// code
});
}
If I run the request through postman, which doesn't bother with CORS, I get:
{ "error": "invalid_client", "error_description": "Client credentials were not found in the headers or body" }
I've tried setting origin to '*
' just to test and see if that was the core of the issue, and it still fails the same way.
Edit Just updating from information below. Changing casing in headers had no effect, and pulling the code out of their if statements had no effect.
I debugged the php by telling my live app to go to my local api, and the php is working as expected. It's setting the headers and making it into each of the if statements.
Edit take 2 I could really use some help on this one, if someone has any ideas, I'd really appreciate it.
Edit take 3 If I set all the header stuff in my .htaccess rather than my php, it lets me through. However, now I'm stuck on the error listed above that I always get when using postman, however now it's while using the actual site.
{"error":"invalid_client","error_description":"Client credentials were not found in the headers or body"}
My response headers are like so
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:authorization, content-type, accept, origin
Access-Control-Allow-Methods:GET, POST, OPTIONS
Access-Control-Allow-Origin:*
I'll be changing it from * to only my domains once I have it working. But for now i'll leave it as *.
My headers as requested.
Allow:POST,OPTIONS,GET,HEAD,TRACE Connection:keep-alive Content-Length:0 Content-Type:text/plain Date:Sun, 11 Jun 2017 02:41:43 GMT Keep-Alive:timeout=30 Server:Apache/2
Request:Accept:*/* Accept-Encoding:gzip, deflate Accept-Language:en-US,en;q=0.8,ca;q=0.6 Access-Control-Request-Headers:authorization Access-Control-Request-Method:POST Connection:keep-alive Host:api.example.com Origin:http://app.example.com Referer:http://app.example.com/login
– Lindbom$http_origin
on your server? There's noAccess-Control-Allow-Origin
on the response headers you posted, so that explains why your browser is kicking up a fuss. It actually doesn't appear that any of your headers are being sent, therefore I don't even think either of thoseif
statements are true. Having a dynamicAccess-Control-Allow-Origin
based on$_SERVER['http_origin']
is a little strange. You should consider sending the actual domains you accept with each request, or making that an environment setting (to avoid hard coding domains) – Moreheadhttp://app.example.com
, and I'm limiting access to those domains because I know exactly the domains I want to be able to access my api. But I have tried just wild carding it (*), with no luck. It's like I don't even get to my code when on the server. When the api call is directed towards my local version of the api, the code runs fine, and since it's a .com address to a localhost address, it triggers all the cors just the same as live. – Lindbom