eBay Trading API CORS issue - web-services

I am trying to make a GetOrders call on eBay Trading API, and am getting CORS error:
XMLHttpRequest cannot load https://api.ebay.com/ws/api.dll.
No 'Access-Control-Allow-Origin' header is present on the requested
resource. Origin '' is therefore not allowed
access.
These are the headers :
Request URL:https://api.ebay.com/ws/api.dll, Request Method:OPTIONS
Status Code:200 OK Request Headersview source Accept:*/*
Accept-Encoding:gzip,deflate,sdch Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:x-ebay-api-siteid, x-ebay-api-dev-name, content-type, x-ebay-api-cert-name, accept, x-ebay-api-request-encoding, x-ebay-api-call-name, x-ebay-api-app-name, x-ebay-api-compatibility-level
Access-Control-Request-Method:POST Connection:keep-alive
Host:api.ebay.com Origin:<mydomain.com>
Referer:<mydomain.com> User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36
Response Headers:
Allow:GET, HEAD, POST, TRACE, OPTIONS
Connection:keep-alive
Content-Length:0
Date:Sun, 19 Jan 2014 18:15:10 GMT
Server:Apache-Coyote/1.1
X-EBAY-ESB-GUID:urn:uuid:UUIDDDODSDFLSDKLSDKFJKS
X-EBAY-ESB-SITEID:0
Does eBay need to explicitly "allow" my domain for CORS ? I have searched internet, and eBay API documentation, and there is no indication of this. If I use curl, the API call is successfully run, though the eBay trading API does not return Access-Control-Allow-Credentials: true.

In practice, all browsers enforce the Cross-Origin Resource Sharing restrictions described in the CORS standard which includes sending the preflight OPTIONS request like you're seeing. The check is not mandatory, though and non-browser user agents such as curl, Android/iOS HTTP clients, etc. generally do not enforce this check.
There is no eBay developer process for allowing particular domains to make cross-domain resource requests. The CORS support is somewhat patchy across the different APIs. For example, the finding API call findItemsByKeywords works fine cross-domain (see here), while other services don't allow it (see a very old but still unanswered request here).
This is not a great answer, but you can always use a backend proxy to make your calls. In this way, your backend can make the calls with curl or the like, and you also get the benefit of being able to hide your appID, user tokens and other secrets from local inspection of your javascript.
You may also want to file a request with eBay, but some of those tickets have been languishing for some time.

Related

rejected by cors when using withCredentials, despiete access-control-allow-credentials and origin are set

I'm using AWS lambdas and cloudfront to serve a SPA.
Now that my lambdas are setting a cookie, I want to include that cookie in the requests I made to the backend (the cookie is HttpOnly and Secure).
Using Axios I set the withCredentials option to true and all my request are now being rejected because CORS.
The web app is being served from the main domain, while the backend lambdas are on the usual lambda weird UUID url. The lambdas are returning the proper headers, as you can see in the screenshot: access-control-allow-origin is set to the domain the web-app is being served from and access-control-allow-credentials is true. The screenshot is from the app without the withCredentials option activated, so it is being triggered from the web-app 100% sure.
Everything is being served over https with a valid certificate (I want to test this also on localhost, but that is a different story)
This is the error I'm getting on the console. One weird thing is that it claims that Access-Control-Allow-Credentials is set to '', which is not true
Access to XMLHttpRequest at 'https://p3doiszvgg.execute-api.eu-central-1.amazonaws.com/dev/sessions'
from origin 'https://pento.danielo.es' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check:
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'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
Is there anything missing?
EDIT:
This are the headers that I'm sending. The problem with this headers is that they are obtained without the withCredentials flag, because if I add such flag the only headers I can see are the provisional headers.
:authority: p3doiszvgg.execute-api.eu-central-1.amazonaws.com
:method: POST
:path: /dev/sessions
:scheme: https
accept: application/json, text/plain, */*
accept-encoding: gzip, deflate, br
accept-language: en-GB,en;q=0.9,es-ES;q=0.8,es;q=0.7,en-US;q=0.6
authorization: Bearer the.bearer.token
cache-control: no-cache
content-length: 58
content-type: application/json;charset=UTF-8
origin: https://pento.danielo.es
pragma: no-cache
referer: https://pento.danielo.es/
sec-fetch-dest: empty
sec-fetch-mode: cors
sec-fetch-site: cross-site
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36
Here is a provisional headers screenshot:
The cookie sent by the server looks something like this:
Set-Cookie: refresh_token=uuid-string-with-letters-numbers; HttpOnly; Secure;
Finally I found the problem and a temporary solution (I'm not very happy with it).
The problem was not my lambda response, that was correct and including the required headers, the problem was with the preflight request. Your browser will send a preflight request almost for every CORS request you made, and, while that request was being successful it was missing some headers. This can be very confusing because the request that it is failing is your actual request (that is what the browser flags as failed) but the problem is on the preflight response.
To be fair, the error on the console was already pointing this out:
Response to preflight request doesn't pass access control check
But it is abit buried, easy to miss and the documentation about it is sparse.
The way I fixed it is by adding some extra props to the CORS definition of my serverless template:
authEcho:
handler: src/users/me.handler
events:
- http:
path: me
method: get
cors:
origin: https://frontend.domain.es
allowCredentials: true # <-- this is the key part
It is not clear on the serverless documentation, but those will be merged with the final response, so you don't need to specify everything or all the headers. The only thing I don't like is that I have to hardcode the origin, while on the actual labmda responses I can calculate it dynamically.

AWS API Gateway set up for Lambda Email Function Persistent 403 On Options Pre-fetch

I have been tearing my hair out trying to get API Gateway to be the front door and trigger for a Lambda function.
I set up a Lambda, called "ContactFormLambda" that accepts a POST, with the details:
{
"subject": "Enquiry from ZenithWebFoundry",
"name": "contact.name",
"number": "contact.number",
"email": "*******#gmail.com",
"comment": "this is a test"
}
Now, in the API Gateway, I created a new API called "contact" and created a new rescource called "contactformlambda", set it up as a proxy to the lambda and defined a POST method (because that's all I'd be doing.
I tested this through the gateway and it works.
This is the API Gateway settings under the Lambda (from the above work):
I then wanted to be able to POST to the gateway from a form, so I realised that I'd need CORS, so I enabled CORS on the resource. This created an OPTIONS method with the three headers on it:
access-control-allow-headers
access-control-allow-methods
access-control-allow-origin
Then I tried to submit the form, but the options pre-fetch fails with a 403. I have followed the instructions here to do all of this. I have tried lots of variations and nothing seems to work.
Having said that, one of the times, it did work, but it let everything through not just the domains that I had specified in the Access-Control-Allow-Origin field. I can't see what I did differently here. It feels like each time I set it up, it does something different. I'm obviously inept at this, can anyone clear this up?
I got this somewhere towards working. Basically, Ignore the "Enable CORS" Action from the Actions menu in API Gateway: it doesn't work, instead follow this guide.
Also, the persistent 403 for me was caused by the url to the resource being case sensitive. I was trying to hit:
https://ovo5xmxf7e.execute-api.ap-southeast-2.amazonaws.com/prod/ContactFormLambda
but the actual url was:
https://ovo5xmxf7e.execute-api.ap-southeast-2.amazonaws.com/prod/contactformlambda
crazy huh?
I said, "somewhere toward working", because basically CORS works a little too well. I specified:
Access-Control-Allow-Origin: 'http://zenithwebfoundry.com'
And despite this coming back in the POST response:
General
Request URL:https://ovo5xmxf7e.execute-api.ap-southeast-2.amazonaws.com/prod/contactformlambda
Request Method:POST
Status Code:200
Remote Address:54.230.243.227:443
Referrer Policy:no-referrer-when-downgrade
Response Headers
access-control-allow-headers:Content-Type,X-Amz-Date,Authorization,X-Api-Key,x-requested-with
access-control-allow-methods:POST,OPTIONS
access-control-allow-origin:http://zenithwebfoundry.com
content-length:0
content-type:application/json
date:Mon, 12 Feb 2018 10:36:17 GMT
status:200
via:1.1 fda24eb25587b7e25d4fa1c50a862ba0.cloudfront.net (CloudFront)
x-amz-cf-id:b7DscV6b6qWl_mHUsEi77nRjICECZD3bd2iXiFv89A1d_xrDvfBQ0Q==
x-amzn-requestid:8d5578fc-0fe0-11e8-9e16-65a7dc0a72e4
x-amzn-trace-id:sampled=0;root=1-5a816e1f-aeeb63ef8590ed3868fe4149
x-cache:Miss from cloudfront
x-requested-with:*
Request Headers
:authority:ovo5xmxf7e.execute-api.ap-southeast-2.amazonaws.com
:method:POST
:path:/prod/contactformlambda
:scheme:https
accept:application/json, text/plain, */*
accept-encoding:gzip, deflate, br
accept-language:en-US,en;q=0.9
cache-control:no-cache
content-length:147
content-type:text/plain
origin:http://localhost:4200
pragma:no-cache
referer:http://localhost:4200/contact
user-agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36
It still completed the action even though my origin was clearly not http://zenithwebfoundry.com. So why is the
access-control-allow-origin:http://zenithwebfoundry.com
setting ignored?
Also, another observation, I have noticed that the pre-fetch is no longer happening. I have tracked it down to the fact that I am no longer sending any CORS disallowed headers (I was sending Access-Control-Allow-Origin in a mistaken belief that I had to send it in the request). I have now started sending "x-requested-with:*", which now forces the preflight check to see if "x-requested-with" is allowed to be sent.
I was hoping the pre-flight check would also prevent execution of the post from localhost, but it doesn't.

Heroku SSL Cloudfront Missing Key-Pair-Id 403 error

I am trying to serve all assets through cloudfront on my Rails 4.2 app hosting on Heroku. I have been successful using cloudfront before using heroku apps that have somename.herokuapp.com, but this one has a custom domain and a wildcard SSL. I cannot get any of the assets to serve, they all have 403
I have tried uploading my SSL on AWS & also tried using the Default CloudFront Certificate (*.cloudfront.net) (which works for my non-custom domain apps).
I have made sure my SSL is in the region on AWS that AWS wants it to be (N.Virginia).
I have made sure I'm only using HTTP/1.1, HTTP/1.0.
I have made sure my distribution is 'enabled'.
My SSL is a wildcard so it looks like this '*.mydomain.com'
When I uploaded it to AWS and added it to my distribution, I see that it is in use.
I have made sure that my aws_id/aws_key are valid. However, there is some sort of Cloudfront key/pair, but I don't know where I would put that on my site, I only have ENV variables for aws_id/aws_secret_key.
Request URL:https://mycloudfrontdistn.cloudfront.net/assets/subfolder/secondfolder/gift-52db27eb2ced10800db38fbd74ec2ef40704d8c55d49b2654f7fe014e4bd1eff.png
Request Method:GET
Status Code:403 Forbidden
Remote Address:REDACTED (I don't know if this is sensitive)
Response Headers
view source
Connection:keep-alive
Content-Length:146
Content-Type:text/xml
Date:Fri, 04 Nov 2016 23:06:47 GMT
Server:CloudFront
Via:1.1 somebignumber.cloudfront.net (CloudFront)
X-Amz-Cf-Id:myAmazonKey==
X-Cache:Error from cloudfront
Request Headers
view source
Accept:image/webp,image/*,*/*;q=0.8
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:en-US,en;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Host:mycloudfrontdist.cloudfront.net
Referer:https: https//www.mysite.com
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36
This error occurs if you enable Restrict Viewer Access on the cache behavior on the distribution, but you are not actually using CloudFront signed URLs because the content is public.
If you want requests for objects that match the PathPattern for this cache behavior to use public URLs, choose No.

Error 401 on WEB API 2 when there is lot of request from Android device

I’m developing an Android App and a Web Service that communicate. My Web Service is in WEB API 2 with token bearer authentication.
My problem is that when I send too many requests (~20 request in 15 seconds) to my Web Service from my Android App, the WS response with
“401” : “Authorization has been denied for this request”
This happen ONLY on the production server (Amen hoster) AND from the Android Device. For example, if I try with Postman, everything works fine. So it’s related to my production server and/or my android app request.
The code for access to the Web Service
URL obj = new URL(SERVEUR_URL + url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
con.setRequestProperty("Authorization", "Bearer " + token);
con.setRequestProperty("Content-Type", "application/json");
int responseCode = con.getResponseCode();
String responseMessage = con.getResponseMessage();
The authentication provider on my Web Service is the default one. No modifications.
The request from my Android App (not work every time)
GET http://api.xxxx.com/api/Weesps/GetAvailableWeesps HTTP/1.1
Authorization: Bearer XXXX
Content-Type: application/json
User-Agent: Dalvik/2.1.0 (Linux; U; Android 6.0; Google Nexus 5X - 6.0.0 - API 23 - 1080x1920 Build/MRA58K)
Host: api.xxxx.com
Connection: Keep-Alive
Accept-Encoding: gzip
The request from Postman (work every time)
GET http://api.xxxx.com/api/Weesps/GetAvailableWeesps HTTP/1.1
Host: api.xxxx.com
Connection: keep-alive
Authorization: Bearer XXXX
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36
Postman-Token: bca55154-775d-9709-7a8b-4793393890ad
Accept: */*
Accept-Encoding: gzip, deflate, sdch
Accept-Language: fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4
Cookie: dadaproaffinity=14ff51cc869a14d3552485cb4ceee1faa1be7165cc5d4b0e2b19370f11afcbea
What I have tried:
Reproduce this error in local : it works fine on local server (web and SQL servers) from android app or from Postman
I check that the token was sent correctly in every requests
The request from Android is the same every time
Tried to add missing header to my android app request
I spend two days on this problem and read many stackoverflow posts but no one helps me.
Thanks for your help.
UPDATE 1 :
With Fiddler I saw that in GET request from Postman, they were a Cookie header. This cookie is sent when we ask for a bearer token.
Example of token response from the server
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 691
Content-Type: application/json;charset=UTF-8
Expires: -1
Server: Microsoft-IIS/8.5
Set-Cookie: .AspNet.Cookies=XXXX; path=/; HttpOnly
X-Powered-By: ASP.NET
X-Powered-By: ARR/2.5
Date: Tue, 31 May 2016 16:55:39 GMT
{"access_token":"XXXX","token_type":"bearer","expires_in":1209599,"userName":"Foo",".issued":"Tue, 31 May 2016 16:55:40 GMT",".expires":"Tue, 14 Jun 2016 16:55:40 GMT"}
Fiddler and Postman saved this cookie and they automatically put it in requests to API (example on the “The request from Postman” code block). When I remove the cookie from the Postman GET request, it doesn’t work (just like my android app).
Now, the question is: why WEB API 2 send a cookie instead of only using the token ? And why the token work great in the first requests and don’t work properly for the following requests ?
According to ASP.NET WebAPI2 flow you can see on the bottom of that page, it seems your requests are always authenticated but sometimes fail to get authorized.
So imo, the AuthorizationFilter[Authorize] rejects some of your requests for an unknown reason. What I would suggest is to dump the request your API receives as well as the claims identity attached to the token. Try to see if there is differences between them when you have a successful response and when you have a 401.
That way, you may be able to determine either it is your request that got malformed, if it is the claims identity that is not good or if it is the AuthorizationFilter that refuses you for another reason (like too much queries or else).
Good luck !
UPDATE 1
According to your new input, I think that your Web API is configured to use both token and cookie authentication.
What I see here is you have two solutions :
1°/ Store the returned cookie in your Android application and use it for next calls. Simplest and fastest way to solve your problem without changing all your API, but you store an authorization cookie : it can leads to security problem (CSRF attacks).
2°/ You can check how your authentication and authorization filters are set to disable cookie authentication and only rely on token authentication : it will hence forces all the requests and your API to only use token and will prevents you from suffering CSRF attacks. More complex because you have to dig into your web API configuration.
Check the following links (sorry, as I don't have enough reputation yet to post more than 2 links per post, you'll find them as text at the end of my answer) :
ASP.net Secure a Web API 2.2[2] : From the chapter "Configuring the Authorization Server" at the bottom
MSDN article on Web API security[3] : More general and technical information about web api security, how to secure it and CRSF attacks
StackOverflow .NET cookie and token authentication[4] : Check David Banister's answer, I think it is exactly what you want to do : Only use token for all your API calls.
StackOverflow Authorize filter and authentication[5] : More information about such mechanisms for your API
And finally
Cookie authentication with web API and 401 codes[6] : Sounds like your actual problem, isn't it ?
I hope it helps you, good luck !
// Links
2: www.asp.net/web-api/overview/security/individual-accounts-in-web-api
3: msdn.microsoft.com/en-us/magazine/dn201748.aspx
4: stackoverflow.com/questions/22568409/mvc-net-cookie-authenticated-system-acessing-a-web-api-with-token-authenticatio
5: stackoverflow.com/questions/21231751/authorize-filter-and-authentication
6: brockallen.com/2013/10/27/using-cookie-authentication-middleware-with-web-api-and-401-response-codes/
Finally, I got my answer:
My Web Service send a Cookie named “dadaproaffinity” the first time I ask for a request. This Cookie was automatically put on the following request by Postman but not by Android HttpUrlConnection. So, I just take this Cookie and now I just add this Cookie on every requests with the Token.
But : This cookie is send by IIS, not by my Web Service ! That’s why it works on local but not on the production server. I googled this cookie and there are very few responses about that. The only one that I find in English is :
Technical Cookie of IIS Server hosting the site.
Need to route to the correct server session, in order to keep it active
Does anyone have more information about this IIS Cookie ?

Non persistent Authentication cookie in a SPA AngularJS / Django REST

I have been wrestling with this issue for several hours:
I have a Single-Page Application written in Angular which communicates with a DjangoREST backend. I am trying to implement an auth fonction with session Cookies. The way I see it is:
1/ Show any unlogged visitor a login page
2/ Make a POST to url/login with the credentials
3/ Obtain a "sessionid" cookie and writing in a service that the user is logged
4/ Redirect vistor towards reserved content and used get & post to access contents with the cookie
The login endpoint is already set and works. When I make a post, I receive a HTTP 200 response with user info and a Set-Cookie, but subsequent calls do not contain the Cookie:
Request URL: ...
Request Method:POST
Status Code:200 OK
Request Headersview source
Accept:application/json, text/plain, */*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4
Connection:keep-alive
Content-Length:38
Content-Type:application/x-www-form-urlencoded; charset=UTF-8
Host:devinify1.herokuapp..
Origin:http://mobilevinify.herokuapp...
Referer:http://mobilevinify.herokuapp...
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36
Form Dataview sourceview URL encoded
username:felix#vinify.co
password:test
Response Headersview source
Access-Control-Allow-Origin:*
Connection:keep-alive
Content-Length:189
Content-Type:application/json
Date:Sat, 14 Dec 2013 20:45:14 GMT
Server:gunicorn/18.0
Set-Cookie:sessionid=ijz27zy655qn0cwmlnvr66609hsyvdub; expires=Sat, 28-Dec-2013 20:45:14 GMT; Max-Age=1209600; Path=/
Vary:Cookie
My code is a very simple adaptation of the angular-app example:
https://github.com/FelixLC/MobileWebApp/blob/master/app/scripts/security/security.js
I have tried this on localhost et on heroku. The server and the client are on different domains, CORS are allowed.
When I try to make calls, I receive an error from Django
TypeError at /vinibarwines/
int() argument must be a string or a number, not 'AnonymousUser'
Should I try to get this cookie and put it in the headers with angularJS?
You can try to login at http://mobilevinify.herokuapp.com/#/login with felix#vinify.co & test. Then Click on Vinibar, there is a 500 internal error on the GET request
Any help much appreciated
Felix
Here is the full layout of how I actually do my authentication. Django/Angular Authentication. It's a pretty extensive response, I'm more than happy to answer further questions you might have.