Missing Authorization in CORS headers of Cloud API

The CORS headers of the Cloud API do not allow for the Authorization header. It would be great if this could be fixed.

Access-Control-Allow-Headers:X-Requested-With, Content-Type, Accept
Access-Control-Allow-Methods:GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin:*
Access-Control-Max-Age:300

Not sure if it’s related but see here:

Yup, thanks @kennethlimcp! We’ve already committed the code to the Cloud internally, and Authorization will be accepted in CORS requests beginning the next time we deploy, sometime next week most likely.

Cheers!

I don’t know much about such stuff and never got that deep to the discussion you guys had over in the other thread but im always impressed!

Hopefully someday i’m good at what im learning too :slight_smile:

Hey there übergeek :stuck_out_tongue:

@zachary, on a separate matter…can you code a quick example of how to call the spark.function digitalwrite and pass D0, high in jquery? The args=D0, HIGH…are confusing. Haha! :wink:

2 Likes

Great, because I don’t see how to pass the token in the device flash operation.

I haven’t tried it, but according to the docs, the PUT request for Flashing a binary via the cloud API accepts an ?access_token= as part of the URI.

Or am I missing something?

####Where should the access token go by http request method type:
GET: In the url
POST: In the form / request body
PUT: In the form / request body

I suspect you can get away with putting the token in the uri for PUTs, but I think in general put/posts should have their params in the body. :smile:

Thanks,
David

@Dave … re the PUT comment you made. Naturally, I would tend to agree. However, this is a copy paste from the current Cloud API Documentation page …

# EXAMPLE REQUEST IN TERMINAL
# Flash a Core with a file called "my-firmware-app.cpp"
curl -X PUT -F file=@my-firmware-app.cpp \
  "https://api.spark.io/v1/devices/0123456789abcdef01234567?access_token=1234123412341234123412341234123412341234"

Perhaps that should ideally be changed then, to some thing like …

# EXAMPLE REQUEST IN TERMINAL
# Flash a Core with a file called "my-firmware-app.cpp"
curl -H "Authorization: Bearer 1234123412341234123412341234123412341234" \
   -X PUT -F file=@my-firmware-app.cpp \
  "https://api.spark.io/v1/devices/0123456789abcdef01234567"

Or, given the documentation as it stands right now, is it possible that the server actually only accepts the token in the URI at present (for flashing)? Seems unlikely, given what you have just stated. Worth double checking, maybe?

Actually the key confusing difference here is the content type of the request. While uploading a file, the content-type is multipart/form-data. That’s why we use the -F flag instead of -d. If you try to put the token in the body with an additional -F flag, you’ll see the server’s clear response:

{
  "code": 400,
  "error": "invalid_request",
  "error_description": "When putting the token in the body, content type must be application/x-www-form-urlencoded."
}

Which means you can either put it in the query string (weird exception to the good general rules @Dave mentioned), or, even better, in an authorization header as @gruvin suggested. It will work either way. From the authentication section of the docs:

There are three ways to send your access token in a request.

  • In an HTTP Authorization header (always works)
  • In the URL query string (only works with GET requests)
  • In the request body (only works for POST & PUT when body is URL-encoded)

When we’re uploading files to flash to a Core, the body is not URL-encoded.

In general, even though most internet users never see HTTP headers (so headers feel confusing to novice web coders), I’d recommend everyone get in the habit of just always sending tokens that way, since it always works. FTW:

curl -H "Authorization: Bearer MY_TOKEN_HERE" https://api.spark.io/v1/devices

Hope that helps @Peli!

Waiting for my spark device to test this out… spark.io, you would not happen to have a set of test devices online for API consumers to play with (until my device arrives :)?

Sounds like a total great idea!

I won’t mind sacrificing my core to do so if there’s really a need :smiley:

Oh! Right. Silly me. I didn’t read the code carefully enough to even see the -F and realise the obvious. You cannot have a token stuffed inside the content of the file you’re sending! (I was stuck in some previous context and skim reading. Never a wise move.)

Got it. Thanks.

Yeah, That might be a really good idea. It wouldn’t even need to be a real spark. Just a virtual demo spark, in the cloud. People who haven’t made a purchase decision yet could maybe play with such a thing, perhaps to see how it works in with their current knowledge and abilities or something.

Others, who write tutorials or books on the sparkcore could maybe use such a virtual test spark for their examples and what not.

Obviously not a high priority. But maybe useful for the future?

2 Likes

Unfortunately, I am still seeing issues with CORS. I tried to PUT code on a spark and it failed due to CORS headers.

XMLHttpRequest cannot load https://api.spark.io/v1/devices/55ff6c065yyyyyyyyy32391887. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://mydomain.com' is therefore not allowed access. 

Hi @Peli,

Hmm, that’s weird, that header should be included on all requests / and OPTIONS requests. Any chance you could send us a sample request / response? Are you developing directly on your domain, or are you running the file locally? Browsers do some weird stuff when you’re running them from a file, and not from a webserver, so it might be a local file browser security thing.

I hope that helps! :slight_smile:

Thanks,
David

Here is a repro that you can try to run from a browser. Insert your ‘device id’ and ‘access token’ to make it work.

I would expect the PUT to go through and return some warnings or success messages. Instead I’m getting a 403.

<html>
<body>
    <script>
        var url = "https://api.spark.io/v1/devices/<ENTER DEVICE ID>"
        var request = new XMLHttpRequest();
        request.open("PUT", url);
        request.setRequestHeader("Content-Type", "multipart/form-data")
        request.setRequestHeader("Authorization", "<ENTER ACCESS TOKEN>")
        var form = new FormData();
        form.append("file", "int main() {}")
        request.send(form)
    </script>
</body>
</html>

For an online editor, it would be easier to work with JSON rather then forms data.

Hi @Peli,

I think you’re running into the old “Uploading files with JavaScript” problem. I found a nice tutorial here that might help

I hope that helps :slight_smile:

Thanks!
David

Silly me. Not specifying the content-type fixed the CORS issue (code below). However, the PUT call never returns and eventually fails with an empty response.

PUT (failed) net::ERR_EMPTY_RESPONSE

sample code:

<html>
<head>
    <title></title>
    <script>
    function flash() {
        var url = "https://api.spark.io/v1/devices/<DEVICE ID>"
        var request = new XMLHttpRequest();
        request.open("PUT", url);
        request.setRequestHeader("Authorization", "Bearer <ACCESS TOKEN>")
        var form = new FormData();
        var input = document.getElementById('file');
        form.append("file", input.files[0])
        request.send(form)
    }
    </script>
</head>
<body>
    <input id="file" name="file" type="file">
    <input type="submit" value="Upload" onclick="flash()" />
</body>
</html>
1 Like

Thanks @Peli — I added this to our API backlog to fail requests like this quickly, cleanly, and with a clear error message. Cheers!

2 Likes

Any hint on the issue? Is it me, misusing the API / was it intermittent? / a crash on your side?