0

Here is the call I make the Parse.com's API to login the user:

var deferred = $q.defer();
$http({
    method: "GET",
    url: "https://api.parse.com/1/login",
    headers: {
        "X-Parse-Application-Id": PARSE_CREDENTIALS.APP_ID,
        "X-Parse-REST-API-Key": PARSE_CREDENTIALS.REST_API_KEY,
        "Content-Type": "application/json"
    },
    data: {
        "username": credentials.username.toLowerCase(),
        "password": credentials.password
    }
}).success(function(data) {
    deferred.resolve(data);
}).error(function() {
    deferred.reject("error")
});
return deferred.promise;

When I trigger this Angular service method, I get the following error in my console:

XMLHttpRequest cannot load https://api.parse.com/1/login. Request header field Access-Control-Allow-Headers is not allowed by Access-Control-Allow-Headers.

I'm not sure how to resolve this. Here are the current contents of the common headers object for my Angular app:

Object {Accept: "application/json, text/plain, */*", Access-Control-Allow-Headers: "origin, content-type, accept"}

I implement the $http service almost exactly the same for my custom classes without error. The only difference is the URL. Can anyone provide an answer as to why I am getting this error?

EDIT: From this other question, I've gathered that the header field error is the result of the header in the Parse.com response, not in my request. But I am not sure how to proceed now.

EDIT 2: Attached is an image of the HTTP request and response headers that I get when I ping the login API URL.

enter image description here

Community
  • 1
  • 1
Caleb Faruki
  • 2,577
  • 3
  • 30
  • 54

2 Answers2

0

Are you setting these headers for all http requests somewhere in your angular app?

I'm not sure how to resolve this. Here are the current contents of the common headers object for my Angular app:

Object {Accept: "application/json, text/plain, */*", Access-Control-Allow-Headers: "origin,

These should come from the server only (response headers), so if they are being set somewhere in the request, then the server would error due to extra headers it was not expecting.

Austin Greco
  • 32,997
  • 6
  • 55
  • 59
  • Are you referring to an interceptor? If so, then no. – Caleb Faruki Jun 03 '15 at 01:05
  • hmm, can you check out the request headers and see if there's anything that shouldn't be there? it really sounds like there's some request headers that shouldn't be there – Austin Greco Jun 03 '15 at 04:58
  • I added the Access-Control-Allow-Headers property myself. It was suggested in another question. – Caleb Faruki Jun 03 '15 at 13:18
  • Can you try removing any extra headers not needed by parse. Here's a successful response I tried http://i.stack.imgur.com/hDGxu.png – Austin Greco Jun 03 '15 at 17:30
  • Removing the extra headers did not resolve it. I got a 200 status code since I had correct login creds. But the XMLHttpRequest error remains the same. – Caleb Faruki Jun 03 '15 at 17:45
0

So here is the relevant part of the documentation from AngularJS about using the $http dependency.

params – {Object.<string|Object>} – Map of strings or objects which will be turned to ?key1=value1&key2=value2 after the url. If the value is not a string, it will be JSONified.
data – {string|Object} – Data to be sent as the request message data.

So I conflated params with data. Parse.com expects an URL-parameterized string of the username and password. My confusion was partly because I thought there was a mismatch of request and response headers. But this was not the case.

var deferred = $q.defer();
$http({
    url: "https://api.parse.com/1/login",
    headers: {
        "X-Parse-Application-Id": PARSE_CREDENTIALS.APP_ID,
        "X-Parse-REST-API-Key": PARSE_CREDENTIALS.REST_API_KEY,
        "Content-Type": "application/json; charset=utf-8"
    },
    params: {
        "username": credentials.username.toLowerCase(),
        "password": credentials.password
    }
}).success(function(data, status, headers, config) {
    deferred.resolve(data);
}).error(function(data, status, headers, config) {
    deferred.reject("error")
});

Additional note: For any Angular developers out there who are concerned about the security of user credentials, you will need to set up SSL for your site to ensure that this data does not fall victim to a man-in-the-middle attack. For information on how to set up SSL with Parse.com, read this article.

If, you do not want to pay for an SSL certificate as DigiCert prescribes (e.g. this app is not for customers, but for internal purposes), check out this article for information on how to create your own SSL certificate and save yourself +$100/year.

Caleb Faruki
  • 2,577
  • 3
  • 30
  • 54