I have a SOAP b2b web service to consume. I'm trying to understand the basic elements of the call and eventually consume it without an app.config / wsdl import and will be using c#.
I imported the wsdl to SOAP UI entered some dummy values for the request data and typed in the password to the request properties. I returned a 500 error, details restricted to local machines.
1 strange aside properties say Authentication Type: No Authorization but without the correct credential I do get a 401.
The Raw SOAP UI Call
GET https://b2b.example.com/yyyb2b/zzz.asmx HTTP/1.1
Host: b2b.example.com
Accept-Encoding: gzip,deflate
Content-Type: text/xml;charset=UTF-8
SOAPAction: "http://www.example.com/yyy/GDDA"
Content-Length: 424
Host: b2b.example.com
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)
So I tried to replicate the call in fiddler to see if I could get any better information:
The headers there:
POST /yyyb2b/zzz.asmx HTTP/1.1:
Host: b2b.example.com
Content-Type: text/xml; charset=utf-8
Content-Length: 419
SOAPAction: "http://www.example.com/yyy/GDDA"
Authentication: Basic base64(username:Password)
Fiddler returns a 302 (found) and then a 400 saying bad request - Invalid Header
I tried removing POST /yyyb2b/zzz.asmx HTTP/1.1: as the 'bad header' and got redirected to sign into the gui portion of the web app. The other possible difference I see is the method of authentication.
Why am I getting different errors?
Related
I have an application that has been successfully using HTTP batch requests to insert, edit, and delete events via the Google Calendar API. In the last couple of days, the individual requests within the batches have started returning 404 errors (although the batch itself gets a 200 success response). Making those same requests as individual requests using the same authorization header is still working.
I'm pretty sure that this isn't related to the forthcoming shutdown of Google's global HTTP batch endpoints because we're using https://www.googleapis.com/batch/calendar/v3 as our endpoint.
Here's an example of what I'm trying to do:
https://www.googleapis.com/batch/calendar/v3
Authorization: Bearer your_auth_token
Content-Type: multipart/mixed; boundary=batch_google_calendar
--batch_google_calendar
Content-Type: application/http
Content-ID: <item-0-batchevent#example.com>
POST calendar/v3/calendars/your_calendar_id#group.calendar.google.com/events
Content-Type: application/json
{"summary":"batch API test","start":{"date":"2020-07-31"},"end":{"date":"2020-07-31"}}
--batch_google_calendar--
And the response is:
--batch_3J6sfuPtVQbjZLcpUe06245gKlO31YnC
Content-Type: application/http
Content-ID: <response-item-0-batchevent#example.com>
HTTP/1.1 404 Not Found
Vary: Origin
Vary: X-Origin
Vary: Referer
Content-Type: application/json; charset=UTF-8
[{
"error": {
"code": 404,
"message": "URL path: /v3/calendars/your_calendar_id#group.calendar.google.com/events could not be resolved. Maybe there is an error parsing the batch item.",
"status": "NOT_FOUND"
}
}
]
--batch_3J6sfuPtVQbjZLcpUe06245gKlO31YnC--
And here's an example of an individual request that's working:
https://www.googleapis.com/calendar/v3/calendars/your_calendar_id#group.calendar.google.com/events
Authorization: Bearer your_auth_token
Content-Type: application/json
{"summary":"API test","start":{"date":"2020-07-31"},"end":{"date":"2020-07-31"}}
Why might the individual request be succeeding but the batch request fail?
Google gave a helpful reply via their issue tracker: there was an error in the way that batch entry paths were specific in my application. This had worked without errors until last week, so I think something must have changed at their end to make it less tolerant of mistakes.
The error we had made was omitting the leading slash in the path in each batch entry. Here's what we were doing:
POST calendar/v3/calendars/your_calendar_id#group.calendar.google.com/events
And here's what we should have been doing:
POST /calendar/v3/calendars/your_calendar_id#group.calendar.google.com/events
I hope that this might be helpful to anyone else who ever finds themselves in a similar situation!
I have a CORS-enabled Spring Boot API that runs on Google Cloud Run and a Vue.js front end that runs on Firebase and uses Axios to make the calls to the back end.
The Problem is that when the front end wants to access the back end (Browser --> Google Clud), it fails with:
Access to XMLHttpRequest at 'https://<backend>' from origin 'https://<frontend>' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
If I access from LOCAL front end (also Browser) to a LOCAL back end, it works: The error above is not shown in the Browser console and I get the data).
If I make the OPTIONS or GET call from Postman to the Google Cloud back end, it works.
I noticed, that with Postman I need to include the Authorization header in the OPTIONS request to send the Bearer token to Google to make it work. The Browser does not send any Authorization header in the OPTIONS call, even if I add withCredentials: true to the Axios config like this:
const response = await axios({
method: 'post',
withCredentials: true,
url: 'https://<backend>',
headers: {
'Authorization': 'Bearer ' + gCloudToken
},
data: {
// data...
}
});
Isn't that a security problem, to send the token in the header? I mean, everyone can see the headers and then fake a call to the server.
Can anybody show how to send the Authorization header in the OPTIONS call via Axios or tell how to correctly handle this problem?
UPDATE 1:
The request from the browser looks like this:
OPTIONS /path/to/api HTTP/2
Host: <backend>-ew.a.run.app
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Access-Control-Request-Method: POST
Access-Control-Request-Headers: authorization,content-type
Referer: https://frontend.web.app/
Origin: https://frontend.web.app
Connection: keep-alive
And this is the response:
HTTP/2 403 Forbidden
date: Tue, 07 Jul 2020 23:57:27 GMT
content-type: text/html; charset=UTF-8
server: Google Frontend
content-length: 320
alt-svc: h3-29=":443"; ma=2592000,h3-27=":443"; ma=2592000,h3-25=":443"; ma=2592000,h3-T050=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
X-Firefox-Spdy: h2
As you can see, no CORS headers (like e.g. access-control-allow-origin) are present.
The cause of this issue is that by not allowing unauthenticated calls the CORS preflight are always rejected with a 403 error message.
There is already a feature request for Cloud Run in orther to support CORS and authentication with Cloudrun.
The Workaround I would see so far is to allow unauthenticated calls on the CloudRun and implement the authentication on your code, However this can have security disadvantages.
I am currently working on development of a caldav synchronization server layer for my calendar application. I am able to answer all the initial requested by the calendar client and currently stuck with the REPORT method.
When PROPFIND is done on Calendar, it asks for CTag and Sync-Token. I do answer this query by providing a CTag and Sync-Token (currently to mock the server, I dynamically generate these value and serve the client).
In the next query, the requested method is REPORT on the calendar as shown below:
Request from client:
REPORT URI /users/admin%40a.de/calendar/ PROTOCOL HTTP/1.1
----------------------------------------
Accept-encoding gzip, deflate
Accept */*
Connection keep-alive
Prefer return=minimal
Host **************
Brief t
User-agent Mac+OS+X/10.10.5 (14F27) CalendarAgent/316.1
Depth 1
Authorization Basic YWRtaW5AYS5kZTpwYXNz
Accept-language en-us
Content-type text/xml
Content-length 260
Request body: <?xml version="1.0" encoding="UTF-8"?>
<A:sync-collection xmlns:A="DAV:">
<A:sync-token>http://calserver.org/ns/sync-token/1</A:sync-token>
<A:sync-level>1</A:sync-level>
<A:prop>
<A:getcontenttype/>
<A:getetag/>
</A:prop>
</A:sync-collection>
Response from the Server:
Response header
Content-type: text/calendar; charset=UTF-8
Connection: keep-alive
Date Thu, 17 Dec 2015 19:35:40 GMT
Transfer-encoding chunked
Http/1.1 207 Multi-Status
Response body
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<D:multistatus xmlns:D=\"DAV:\" xmlns:C=\"urn:ietf:params:xml:ns:caldav\" xmlns:E=\"urn:ietf:params:xml:ns:carddav\">
<D:response>
<D:propstat>
<D:href>/calendar/2601ddd19c1001.ics</D:href>
<D:prop>
<D:getcontenttype>text/calendar</D:getcontenttype>
<D:getetag>"334411222s12"</D:getetag>
</D:prop>
<D:status>HTTP/1.1 200 OK</D:status>
</D:propstat>
</D:response>
</D:multistatus>
Now my question is, In the server-response, I answer the REPORT method that a new event has been created by providing a new ETag value, but the data is not requested by the Client ??
How and when should I serve the calendar data of the new event and what would be the request from client ???
Content-type should not be text/xml, It should be text/calendar.
The etag needs to be surrounded by double-quotes.
I'm pretty sure it's a bad idea to use a + in the uri the way you did. If you want to encode a space, use %20 instead, but it's probably even better to completely avoid any sort of special encoding.
The response to a sync-collection report also must have the current sync-token in the response body. See https://www.rfc-editor.org/rfc/rfc6578#section-6.4
Rather confused by the multiple edits but the content-type in the response header should definitely be text/xml
Content-type: text/xml; charset=UTF-8
I am getting the following error message on my angular/asp.net web api project.
XMLHttpRequest cannot load http://localhost:7291/api/products. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:7305' is therefore not allowed access. The response had HTTP status code 500.
I know it has something to do with CORS not being implemented correctly, but I'm not sure what I'm doing wrong. I'm following a tutorial and as far as I can tell I've got everything right?
Here's the info from the network tab in chrome debug.
Remote Address:[::1]:7291
Request URL:http://localhost:7291/api/products
Request Method:GET
Status Code:500 Internal Server Error
Response Headers
(8)
Request Headers
view source
Accept:application/json, text/plain, /
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Host:localhost:7291
Origin:http://localhost:7305
Referer:http://localhost:7305/
User-Agent:Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36
Here is where I map the API url.
(function () {
"use strict";
angular
.module("common.services", ["ngResource"])
.constant("appSettings",
{
serverPath: "http://localhost:7291/"
})
}());
And this is how I'm setting up the EnableCOrsAttribute:
[EnableCorsAttribute("http://localhost:7305", "*", "*")]
Can anyone see what I'm doing wrong? If more code is needed please let me know. Thanks.
First Step, use a tool like Postman or Fiddler to verify your service endpoint first to ensure functionality.
It looks as if this is not a CORS issue at all, due to the 500 response:
Status Code:500 Internal Server Error
A CORS issue on a normal success response is usually manifested as a status 0 or -1 in the client, but what you are experiencing is an error on the server side. I have seen this in my own code and suspect that your implementation on the server side is only injecting the CORS headers at the end of processing the request and as the processing abnormally aborted the CORS headers didn't make it in there.
Once you have confirmed functionality do an OPTIONS request on your endpoint to verify CORS:
OPTIONS / HTTP/1.1
Host: localhost:7291
Cache-Control: no-cache
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
Then inspect the headers of the response, if your CORS is enabled correctly on the server you should see Access-Control-Allow headers similar to this:
Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS, ETAG
Access-Control-Allow-Origin: http://localhost:7305
I am following linked in documentation to exchange a JSAPI token for a OAuth 1.0a token. (https://developer.linkedin.com/documents/exchange-jsapi-tokens-rest-api-oauth-tokens)
I got the following error during the exchange:
oauth_problem=signature_invalid&oauth_problem_advice=com.linkedin.security.auth.pub.LoginDeniedInvalidAuthTokenException%20while%20obtaining%20request%20token%20for%20%3APOST%26https%253A%252F%252Fapi.linkedin.com%252Fuas%252Foauth%252FaccessToken%26oauth_consumer_key%253D751oglji2r3e9e%2526oauth_nonce%253D1422656976%2526oauth_signature_method%253DHMAC-SHA1%2526oauth_timestamp%253D1422656976654%2526oauth_version%253D1.0%2526xoauth_oauth2_access_token%253DzdLOTq4fVfiSBS4WP_FkEgL942vbUkpsH4gH%0ACONN%3AO%7C4245561%7C3241891%7C7315878%7C4307091%7C%2A02%3A1422656976%3AgwtcYNp1ZiULkjvCXvnbOWM2fps%253D
I used the the LinkedIn OAuth test console to test my signature algorithm
(https://developer.linkedin.com/oauth-test-console)
and I confirmed that I am constructing the same base_string and got the same signature as the test-console.
However I am still getting the signature_invalid error which suggest that I might be constructing the HTTP POST request incorrectly.
This is what my request looks like:
POST /uas/oauth/accessToken HTTP/1.1
Authorization: OAuth oauth_consumer_key="751oglji2r3e9e", oauth_nonce="1422654439", oauth_signature="vif9BS8MFNdjTWCagrs%252Fn8gNa1Y%253D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1422654439035", oauth_version="1.0"
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache
Pragma: no-cache
User-Agent: Java/1.7.0_71
Host: api.linkedin.com
Accept: text/html, image/gif, image/jpeg, *; q=.2, /; q=.2
Connection: close
Content-Length: 63
xoauth_oauth2_access_token=AykDWuciDtpUQ_2tY4y3sKOOqOD6JXUSwuZR
I url encoded my signature because this is what some of the other post suggest. Is this the right way?
The error message from LinkedIn does not make it clear as to why the signature is invalid.
Re-examining the signature in the Authorization header, it appear that I made the mistake of URL encoding the signature twice when putting it in the Authorization header.
Once I fix this I was able to obtain the access token.