iCloud calendar: Getting unauthorized error from CalDav server - calendar

I'm trying to PUT an event on iCloud calendar using CalDav. After several proper requests and responses and getting the user principal and calendars, when i try to PUT an event, the server returns Unauthorized error.
Here's the network log from fiddler:
Request:
OPTIONS https://p49-caldav.icloud.com/ HTTP/1.1
Authorization: Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2
Host: p49-caldav.icloud.com
Content-Length: 0
Connection: Keep-Alive
Response:
HTTP/1.1 200 OK
Server: AppleHttpServer/1.9.12/0643601
Date: Sat, 16 Jul 2016 15:38:55 GMT
Content-Type: text/plain; charset=UTF-8
Content-Length: 0
Connection: keep-alive
X-Apple-Jingle-Correlation-Key: X27XPFLXYFCYHGGADAAWWCKMJE
apple-seq: 0
apple-tk: false
X-Responding-Instance: caldavj:44900101:pv42p49ic-zteg05101201:8501:16D67:82b3920
Allow: ACL, COPY, DELETE, GET, HEAD, LOCK, MKCOL, MOVE, OPTIONS, PROPFIND, PROPPATCH, PUT, REPORT, UNLOCK
DAV: 1, access-control, calendar-access, calendar-schedule, calendar-auto-schedule, calendar-managed-attachments, calendarserver-sharing, calendarserver-subscribed, calendarserver-home-sync
X-Accept-Client-Encoding: gzip
Strict-Transport-Security: max-age=31536000; includeSubDomains
via: icloudedge:br30p01ic-ztde01120601:7401:16D44:Berlin
X-Apple-Request-UUID: bebf7795-77c1-4583-98c0-18016b094c49
X-Apple-Xrail: false
access-control-expose-headers: X-Apple-Request-UUID
access-control-expose-headers: Via
Request:
PROPFIND https://p49-caldav.icloud.com/ HTTP/1.1
Authorization: Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2
Depth: 0
Host: p49-caldav.icloud.com
Content-Type: text/xml
Content-Length: 89
<propfind xmlns="DAV:">
<prop>
<current-user-principal />
</prop>
</propfind>
Response:
HTTP/1.1 207 Multi-Status
Server: AppleHttpServer/1.9.12/0643601
Date: Sat, 16 Jul 2016 15:38:55 GMT
Content-Type: text/xml
Content-Length: 350
Connection: keep-alive
ETag: "B40001-1B000-578A54FB"
Last-Modified: Sat, 16 Jul 2016 15:38:35 GMT
DAV: 1, access-control, calendar-access, calendar-schedule, calendar-auto-schedule, calendar-managed-attachments, calendarserver-sharing, calendarserver-subscribed, calendarserver-home-sync
Accept-Ranges: bytes
X-Responding-Server: pv42p49ic-zteg04102301 21 a63660a6f7d1a25b5a7ed66dab0da843
X-Transaction-Id: b8d02729-1bcd-4df1-a1ce-3c2a545ed3f0
Vary: accept-encoding
Strict-Transport-Security: max-age=31536000; includeSubDomains
via: icloudedge:br30p01ic-ztde01120601:7401:16D44:Berlin
X-Apple-Request-UUID: b8d02729-1bcd-4df1-a1ce-3c2a545ed3f0
X-Apple-Xrail: false
access-control-expose-headers: X-Apple-Request-UUID
access-control-expose-headers: Via
<?xml version='1.0' encoding='UTF-8'?>
<multistatus xmlns='DAV:'>
<response>
<href>/</href>
<propstat>
<prop>
<current-user-principal>
<href>/10430699202/principal/</href>
</current-user-principal>
</prop>
<status>HTTP/1.1 200 OK</status>
</propstat>
</response>
</multistatus>
Request:
PROPFIND https://p49-caldav.icloud.com/10430699202/principal/ HTTP/1.1
Authorization: Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2
Depth: 0
Host: p49-caldav.icloud.com
Content-Type: text/xml
Content-Length: 122
<propfind xmlns="DAV:">
<prop>
<calendar-home-set xmlns="urn:ietf:params:xml:ns:caldav" />
</prop>
</propfind>
Response:
HTTP/1.1 207 Multi-Status
Server: AppleHttpServer/1.9.12/0643601
Date: Sat, 16 Jul 2016 15:38:56 GMT
Content-Type: text/xml
Content-Length: 446
Connection: keep-alive
DAV: 1, access-control, calendar-access, calendar-schedule, calendar-auto-schedule, calendar-managed-attachments, calendarserver-sharing, calendarserver-subscribed, calendarserver-home-sync
Accept-Ranges: bytes
X-Responding-Server: pv42p49ic-zteg04102001 22 a63660a6f7d1a25b5a7ed66dab0da843
X-Transaction-Id: 9b4aa58d-69d9-4e82-bd90-48380b1650cc
Vary: accept-encoding
Strict-Transport-Security: max-age=31536000; includeSubDomains
via: icloudedge:br30p01ic-ztde01120601:7401:16D44:Berlin
X-Apple-Request-UUID: 9b4aa58d-69d9-4e82-bd90-48380b1650cc
X-Apple-Xrail: false
access-control-expose-headers: X-Apple-Request-UUID
access-control-expose-headers: Via
<?xml version='1.0' encoding='UTF-8'?>
<multistatus xmlns='DAV:'>
<response>
<href>/10430699202/principal/</href>
<propstat>
<prop>
<calendar-home-set xmlns='urn:ietf:params:xml:ns:caldav'>
<href xmlns='DAV:'>https://p49-caldav.icloud.com:443/10430699202/calendars/</href>
</calendar-home-set>
</prop>
<status>HTTP/1.1 200 OK</status>
</propstat>
</response>
</multistatus>
Request:
PUT https://p49-caldav.icloud.com/10430699202/calendars/ee451a47-c242-40c1-b295-4f1251a5d0cd.ics HTTP/1.1
Authorization: Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2
Host: p49-caldav.icloud.com
If-None-Match: *
Content-Type: text/calendar
Content-Length: 302
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//tracky/iCal//FUBU v1.0//EN
BEGIN:VEVENT
UID:ee451a47-c242-40c1-b295-4f1251a5d0cd
DESCRIPTION:
DTEND:20160716T202635
DTSTAMP:20160716T155652Z
DTSTART:20160716T202635
LAST-MODIFIED:20160716T155652Z
SEQUENCE:1468684613
SUMMARY:
END:VEVENT
END:VCALENDAR
Response:
HTTP/1.1 301 Moved Permanently
Server: AppleHttpServer/1.9.12/0643601
Date: Sat, 16 Jul 2016 15:56:53 GMT
Content-Type: text/html;charset=utf-8
Content-Length: 216
Connection: keep-alive
Location: https://p49-caldav.icloud.com/10430699202/calendars/ee451a47-c242-40c1-b295-4f1251a5d0cd.ics/
X-Responding-Server: pv42p49ic-zteg04092901 6 a63660a6f7d1a25b5a7ed66dab0da843
X-Transaction-Id: e537a470-ddf6-4a8f-a059-580d52075840
Strict-Transport-Security: max-age=31536000; includeSubDomains
via: icloudedge:br30p01ic-ztde01130201:7401:16D44:Berlin
X-Apple-Request-UUID: e537a470-ddf6-4a8f-a059-580d52075840
X-Apple-Xrail: false
access-control-expose-headers: X-Apple-Request-UUID
access-control-expose-headers: Via
<html><head><title>Moved Permanently</title></head><body><h1>Moved Permanently</h1><p>Document moved to https://p49-caldav.icloud.com/10430699202/calendars/ee451a47-c242-40c1-b295-4f1251a5d0cd.ics/.</p></body></html>
The server redirects me and removes the authorization header causing the unauthorized error:
PUT https://p49-caldav.icloud.com/10430699202/calendars/ee451a47-c242-40c1-b295-4f1251a5d0cd.ics/ HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2
If-None-Match: *
Content-Type: text/calendar
Host: p49-caldav.icloud.com
Content-Length: 302
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//tracky/iCal//FUBU v1.0//EN
BEGIN:VEVENT
UID:ee451a47-c242-40c1-b295-4f1251a5d0cd
DESCRIPTION:
DTEND:20160716T202635
DTSTAMP:20160716T155652Z
DTSTART:20160716T202635
LAST-MODIFIED:20160716T155652Z
SEQUENCE:1468684613
SUMMARY:
END:VEVENT
END:VCALENDAR
Response:
HTTP/1.1 401 Unauthorized
Server: AppleHttpServer/1.9.12/0643601
Date: Sat, 16 Jul 2016 15:56:53 GMT
Content-Type: text/html;charset=utf-8
Content-Length: 141
Connection: keep-alive
WWW-Authenticate: x-mobileme-authtoken realm="MMCalDav"
WWW-Authenticate: basic realm="MMCalDav"
X-Responding-Server: pv42p49ic-zteg05101701 1 a63660a6f7d1a25b5a7ed66dab0da843
X-Transaction-Id: 25cf8cf5-3c86-4c11-915f-f51ee9c79c86
Strict-Transport-Security: max-age=31536000; includeSubDomains
via: icloudedge:br30p01ic-ztde01130201:7401:16D44:Berlin
X-Apple-Request-UUID: 25cf8cf5-3c86-4c11-915f-f51ee9c79c86
X-Apple-Xrail: false
access-control-expose-headers: X-Apple-Request-UUID
access-control-expose-headers: Via
<html><head><title>Unauthorized</title></head><body><h1>Unauthorized</h1><p>You are not authorized to access this resource.</p></body></html>
When I targeted the redirecting URL encountered another error:
<html><head><title>Conflict</title></head><body><h1>Conflict</h1><p>cannot PUT to non-existent parent</p></body></html>
What am I doing wrong?

You are trying to PUT an event into the calendar homeset collection:
PUT https://p49-caldav.icloud.com
/10430699202 # user scope
/calendars # calendar home
/??? # calendar
/ee451a47-c242-40c1-b295-4f1251a5d0cd.ics # event
A calendar homeset contains calendars, not events. So the next step is selecting the calendar you want to put your event into (e.g. the default calendar).
You can list the available calendars (and todo lists) with another PROPFIND Depth:1 on the homeset.

Related

How do you add a cookie given after a post request in C?

I am trying to create a program that logs into a website for me. The problem is, when I follow the redirection the website supplies a unique cookie that I can't figure out how to add to the post request. I have been going through each of the libcurl options on the man page, but I can't find anything that will do this. So far this is the post request function that I have.
void webpost(char* url, char* postdata) {
CURL *handler = curl_easy_init();
CURLcode err;
long size = sizeof(postdata);
if (handler) {
curl_easy_setopt(handler, CURLOPT_URL, url);
curl_easy_setopt(handler, CURLOPT_POSTFIELDSIZE, 50L);
curl_easy_setopt(handler, CURLOPT_POSTFIELDS, postdata);
curl_easy_setopt(handler, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(handler, CURLOPT_VERBOSE, 1L);
err = curl_easy_perform(handler);
if (err != CURLE_OK) {
printf("ERROR POST: %s returned (%s)\n", url, curl_easy_strerror(err));
}
curl_easy_cleanup(handler);
}
}
When this function runs, I get the following result.
* Trying 10.10.10.10...
* TCP_NODELAY set
* Connected to website.com (10.10.10.10) port 2048 (#0)
> POST /login HTTP/1.1
Host: website.com
Accept: */*
Content-Length: 50
Content-Type: application/x-www-form-urlencoded
* upload completely sent off: 50 out of 50 bytes
* Mark bundle as not supporting multiuse
< HTTP/1.1 302 Moved temporarily
< Date: Wed, 26 Aug 2020 05:59:50 GMT
< Server: EZproxy
< Expires: Mon, 02 Aug 1999 00:00:00 GMT
< Last-Modified: Wed, 26 Aug 2020 05:59:50 GMT
< Cache-Control: no-store, no-cache, must-revalidate
< Cache-Control: post-check=0, pre-check=0
< Pragma: no-cache
< Set-Cookie: ezproxy=uRZWAo3IsKyR9O0; Path=/; Domain=.website.com
< Location: http://website.com/connect?session=suRZWAo3IsKyR9O0&url=menu
< Connection: close
<
* Closing connection 0
* Issue another request to this URL: 'http://website.com/connect?session=suRZWAo3IsKyR9O0&url=menu'
* Switch from POST to GET
* Hostname website.com was found in DNS cache
* Trying 10.10.10.10...
* TCP_NODELAY set
* Connected to website.com (10.10.10.10) port 2048 (#1)
> GET /connect?session=suRZWAo3IsKyR9O0&url=menu HTTP/1.1
Host: website.com
Accept: */*
* Mark bundle as not supporting multiuse
< HTTP/1.1 302 Moved temporarily
< Date: Wed, 26 Aug 2020 05:59:50 GMT
< Server: EZproxy
< Expires: Mon, 02 Aug 1999 00:00:00 GMT
< Last-Modified: Wed, 26 Aug 2020 05:59:50 GMT
< Cache-Control: no-store, no-cache, must-revalidate
< Cache-Control: post-check=0, pre-check=0
< Pragma: no-cache
< Set-Cookie: ezproxy=uRZWAo3IsKyR9O0; Path=/; Domain=.website.com
< Location: http://website.com/connect?session=ruRZWAo3IsKyR9O0&url=menu
< Connection: close
<
* Closing connection 1
* Issue another request to this URL: 'website.com/connect?session=ruRZWAo3IsKyR9O0&url=menu'
* Hostname website.com was found in DNS cache
* Trying 10.10.10.10...
* TCP_NODELAY set
* Connected to website.com (10.10.10.10) port 2048 (#2)
> GET /connect?session=ruRZWAo3IsKyR9O0&url=menu HTTP/1.1
Host: website.com
Accept: */*
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Wed, 26 Aug 2020 05:59:50 GMT
< Server: EZproxy
< Content-Type: text/html
< Connection: close
<
<html>
<head>
<title>Cookie Required</title>
</head>
<body>
<p>
Licensing agreements for these databases require that access be extended
only to authorized users. Once you have been validated by this system,
a "cookie" is sent to your browser as an ongoing indication of your authorization to
access these databases. This cookie only needs to be set once during login.
</p>
<p>
If you are using a firewall or network privacy program, you may need
reconfigure it to allow cookies to be set from this server.
</p>
<p>
As you access databases, they may also use cookies. Your ability to use those databases
may depend on whether or not you allow those cookies to be set.
</p>
<p>
To login again, click here.
</p>
</body>
</html>
* Closing connection 2
simply add a header in the next request to a site matching the domain and path parameters of the Set-cookie: header that says:
Cookie: ezproxy=uRZWAo3IsKyR9O0
That will be enough for the server to recognize and locate the session you come from, so it can locate the data belonging to your session.
You can read HTTP for a description of the status management mechanism and read about the Cookie and Set-Cookie headers.
Thank you, I was able to get it working by saving the cookie to a file and loading it in the same request.
curl_easy_setopt(handler, CURLOPT_COOKIEJAR, "cookies.txt");
curl_easy_setopt(handler, CURLOPT_COOKIEFILE, "cookies.txt");

Missing Csrf token cookie

I'm relatively new to CakePHP (v3.7). I have an application in which I'm getting a "Missing Csrf Token Cookie" error.
In Application.php, I have:
$options = []; // I'm fine with the default options.
$csrf = new CsrfProtectionMiddleware($options);
$middlewareQueue->add($csrf);
The form page has a hidden form element with the _csrfToken in it.
I'm confused as to why it's not being found on the POST?
Digging further, I found that in CsrfProtectionMiddleware.php, the _validateToken() function below behaves as follows:
$cookies is null (there are no cookies set.)
thus, $cookie is null.
$post actually contains the content of the _csrfToken parameter from the hidden parameter on the page. However the function never looks at it. Because $cookie is null,
the if(!$cookie) statement causes an InvalidCsrfTokenException to be thrown.
protected function _validateToken(ServerRequest $request)
{
$cookies = $request->getCookieParams();
$cookie = Hash::get($cookies, $this->_config['cookieName']);
$post = Hash::get($request->getParsedBody(), $this->_config['field']);
$header = $request->getHeaderLine('X-CSRF-Token');
if (!$cookie) {
throw new InvalidCsrfTokenException(__d('cake', 'Missing CSRF token cookie'));
}
if (!Security::constantEquals($post, $cookie) && !Security::constantEquals($header, $cookie)) {
throw new InvalidCsrfTokenException(__d('cake', 'CSRF token mismatch.'));
}
}
}
Obviously, the middleware is expecting an actual cookie, in addition to a hidden parameter. Where is this cookie set (or supposed to be set?)
Update:
I checked on the browser side. The cookie is being set, but the browser isn't returning it on the POST request.
Here's CakePHP's RESPONSE to the original GET request to populate the page:
Connection: Keep-Alive
Content-Length: 3013
Content-Type: text/html; charset=UTF-8
Date: Wed, 08 May 2019 23:07:31 GMT
Keep-Alive: timeout=5, max=100
Server: Apache/2.4.33 (Unix) PHP/7.1.1
Set-Cookie: csrfToken=b553dd2e06e57f6d514ee41a120e1c60084adafddfbaa6f72db1f7f590fcf50143876ac817d29d6f1cf9a786031d6235ba21e265b9d3b2a0ee4535854f048b66; path=/webroot/
X-Powered-By: PHP/7.1.1
Note the csrfToken cookie.
... and here's the POST that the browser sends back with the form data
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cache-Control: no-cache
Connection: keep-alive
Content-Length: 184
Content-Type: application/x-www-form-urlencoded
DNT: 1
Host: *************
Origin: ****************
Pragma: no-cache
Referer: ***************
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36
Query String Parameters
redirect: /Users/login
Form Data
_method: POST
_csrfToken: b553dd2e06e57f6d514ee41a120e1c60084adafddfbaa6f72db1f7f590fcf50143876ac817d29d6f1cf9a786031d6235ba21e265b9d3b2a0ee4535854f048b66
username: xxxxxxxxxx
password: xxxxxxxxxx
Note that it's sending back the hidden form parameter _csrfToken, but NOT the cookie.
Thanks for any help...
This turned out to be a problem with the DOCUMENT_ROOT directory setting in Apache. It was set to the parent directory of webroot, instead of to webroot itself. When I changed it everything worked.

How to resolve entitlement error in ibm watson nlc?

I am trying to train the IBM Watson NLC locally on my computer and after it trains for few mins it shows me this error
{
"code" : 400,
"error" : "Entitlement error",
"description" : "This user or service instance has the maximum number of classifiers."
}
(mytestenv) (base) C:\Users\mohana.kalyan\Desktop\ibm3\nlc-icd10-classifier>curl -i -u "apikey:#####################################" -F training_data=#C:\Users\mohana.kalyan\Desktop\ibm3\nlc-icd10-classifier\data\weather_data_train.csv -F training_metadata="{\"language\":\"en\",\"name\":\"ICD_classifier\"}" "https://gateway-fra.watsonplatform.net/natural-language-classifier/api/v1/classifiers"
HTTP/1.1 100 Continue
X-Note: Gateway Ack
HTTP/1.1 400 Bad Request
X-Backside-Transport: FAIL FAIL
Content-Type: application/json
X-XSS-Protection: 1
Content-Security-Policy: default-src 'none'
X-Content-Type-Options: nosniff
Cache-Control: no-cache, no-store
Pragma: no-cache
Expires: 0
x-global-transaction-id: 0e7fa6da5c6a722c37a4550d
X-DP-Watson-Tran-ID: gateway-fra-dp02-933516557
X-DP-Transit-ID: gateway-fra-dp02-933516557
Strict-Transport-Security: max-age=31536000;
Content-Length: 141
Date: Mon, 18 Feb 2019 08:51:56 GMT
Connection: close
{
"code" : 400,
"error" : "Entitlement error",
"description" : "This user or service instance has the maximum number of classifiers."
}

With Angularjs, $http post return response error in Microsoft Edge

Well, while I develop an admin page for test,
a weird problem occurred in Microsoft Edge.
Here's part of source code to fetch response from server of loginCtrl.js
$http({
method: 'POST',
url: Define.apiUrl + 'admin/login',
data: {
user_id: $scope.login_email,
password: $scope.login_password
}
})
.then(function (response) {
if (response.data.success) {
$cookieStore.put(Define.userInfo, response.data.info);
$cookieStore.put(Define.userToken, response.data.token);
}
}, function (data) {
console.log('errors!');
console.log(data);
});
This works well in Chrome and IE
But in Microsoft Edge, This returns error like below
data = null
status = -1
statusText = ""
and below are each status of related files.
# loginCtrl.js
## Chrome response status
Accept-Ranges:bytes
Cache-Control:public, max-age=0
Connection:keep-alive
Content-Length:1877
Content-Type:application/javascript
Date:Fri, 18 Aug 2017 04:06:49 GMT
ETag:W/"755-15df385a23e"
Last-Modified:Fri, 18 Aug 2017 04:06:47 GMT
## Chrome request status
Accept:'*/*'
Accept-Encoding:gzip, deflate, br
Accept-Language:ko-KR,ko;q=0.8,en-US;q=0.6,en;q=0.4
Connection:keep-alive
Host:localhost:9000
If-Modified-Since:Fri, 18 Aug 2017 02:51:00 GMT
If-None-Match:W/"6f5-15df340413d"
Referer:http://localhost:9000/
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/60.0.3112.101 Safari/537.36
## Edge response status
Accept-Ranges: bytes
Cache-Control: public, max-age=0
Connection: keep-alive
Content-Length: 1807
Content-Type: application/javascript
Date: Fri, 18 Aug 2017 02:06:14 GMT
ETag: W/"70f-15df3173adf"
Last-Modified: Fri, 18 Aug 2017 02:06:12 GMT
## Edge request status
Accept: application/javascript, '*/*'; q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: ko-KR
Connection: Keep-Alive
Host: localhost:9000
Referer: http://localhost:9000/
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/52.0.2743.116 Safari/537.36 Edge/15.15063
I wonder why only Edge cannot get right responses.
I tried to make headers like 'Content-Type', 'Cache-Control' or add config like cache : false.
But these couldn't fix this problem.
Did I miss something??
Plz any handsome or pretty programmer save me
I've tried to find solution of this, and finally I got one.
Some answers suggested adding tags like
<meta http-equiv="Cache-Control" content="no-cache" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="Mon, 26 Jul 1997 05:00:00 GMT" />
or adding code into config like
$httpProvider.defaults.headers.get['If-Modified-Since'] = 'Mon, 26 Jul 1997 05:00:00 GMT';
// extra
$httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache';
$httpProvider.defaults.headers.get['Pragma'] = 'no-cache';
but these couldn't solve this.
Finally I saw one answer said this may occurred by a kind of policy handling caches in Edge.
This may occur when I use local server to send requests or get responses.
And it will gonna disappear when test on other server not on local.
Actually, I'm still using local server, so I don't know whether this work or not.

AngularJS / Alfresco / CORS filter issue: No 'Access-Control-Allow-Origin' header

I have some problem with Alfresco (5.0.d), my AngularJS (1.4.3) client and the CORS settings (typical cross-domain / No'Access-Control-Allow-Origin' header is present on the requested resource problem).
I am calling the Alfresco REST API from an AngularJS application running on localhost:3000, to an Alfresco instance running on localhost:8080 (Tomcat, no reverse-proxy in front).
This XHR call works fine:
http://localhost:8080/alfresco/service/slingshot/live-search-docs?t=Project&u=admin&pw=admin&alf_ticket=TICKET_9d9780c83b8b9525c7acb9d3d8da66c5c902fb76
This one
http://localhost:8080/alfresco/service/api/login?u=admin&pw=admin
only works fine in Internet Explorer 11, but in Chrome and Firefox, I am getting status code 200 returned with 0 bytes and the error in the JS console:
XMLHttpRequest cannot load
http://localhost:8080/alfresco/service/api/login?u=admin&pw=admin. No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:3000' is therefore not allowed
access.
In the Alfresco web.xml, I have enabled the CORS filter as follows:
<!-- CORS Filter Mappings Begin -->
<filter-mapping>
<filter-name>CORS</filter-name>
<url-pattern>/api/*</url-pattern>
<url-pattern>/service/*</url-pattern>
<url-pattern>/s/*</url-pattern>
<url-pattern>/cmisbrowser/*</url-pattern>
</filter-mapping>
<!-- CORS Filter Mappings End -->
<!-- CORS Filter Begin -->
<filter>
<filter-name>CORS</filter-name>
<filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
<init-param>
<param-name>cors.allowGenericHttpRequests</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>cors.allowOrigin</param-name>
<!-- <param-value>http://localhost:3000 http://localhost:8081 http://localhost:8080 https://localhost</param-value> -->
<param-value>*</param-value>
</init-param>
<init-param>
<param-name>cors.allowSubdomains</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>cors.supportedMethods</param-name>
<param-value>GET, HEAD, POST, PUT, DELETE, OPTIONS</param-value>
</init-param>
<init-param>
<param-name>cors.supportedHeaders</param-name>
<param-value>origin, authorization, x-file-size, x-file-name, content-type, accept, x-file-type</param-value>
</init-param>
<init-param>
<param-name>cors.supportsCredentials</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>cors.maxAge</param-name>
<param-value>3600</param-value>
</init-param>
</filter>-->
<!-- CORS Filter End -->
The calls from within Angular:
The one that works fine:
$http.get('http://localhost:8080/alfresco/service/slingshot/live-search-docs?t=Project&alf_ticket=TICKET_9d9780c83b8b9525c7acb9d3d8da66c5c902fb76').then(function(response) {
console.log('DATA LOADED: ' + response.items);
$scope.contents = response.items;
});
Response headers:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Cache-Control: no-cache
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Pragma: no-cache
Content-Type: application/json;charset=UTF-8
Content-Length: 85
Date: Thu, 13 Aug 2015 06:37:24 GMT
The one that fails:
$http.get('http://localhost:8080/alfresco/service/api/login?u=' + $scope.user.email + '&pw=' + $scope.user.password).
then(function(response) {
console.log('ALF_TICKET: ' + response.data.ticket);
$scope.alfTicket = response.data.ticket;
$state.go('admin-panel.default.introduction');
}, function(response) {
console.log('LOGIN FAILED');
});
Response headers:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:3000
Vary: Origin
Cache-Control: no-cache
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Pragma: no-cache
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Thu, 13 Aug 2015 06:38:36 GMT
I have the $httpProvider configured in my AngularJS app, just to be sure:
.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
}
A CURL request simulated from a different host works fine, interestingly though, I do not get a Access-Control-Allow-Origin header back in the response despite the CORS filter enabled in Alfresco:
curl -H "Origin: http://www.microsoft.com" --verbose "http://alfresco.mycompany.ch:8080/alfresco/service/api/login?u=admin&pw=12#echo"
* Hostname was NOT found in DNS cache
* Trying 10.10.0.183...
* Connected to alfresco.mycompany.ch (10.10.0.183) port 8080 (#0)
> GET /alfresco/service/api/login?u=admin&pw=12#echo HTTP/1.1
> User-Agent: curl/7.37.1
> Host: alfresco.mycompany.ch:8080
> Accept: */*
> Origin: http://www.microsoft.com
>
< HTTP/1.1 200 OK
* Server Apache-Coyote/1.1 is not blacklisted
< Server: Apache-Coyote/1.1
< Cache-Control: no-cache
< Expires: Thu, 01 Jan 1970 00:00:00 GMT
< Pragma: no-cache
< Content-Type: application/json;charset=UTF-8
< Content-Length: 85
< Date: Thu, 13 Aug 2015 08:11:15 GMT
<
{
"data":
{
"ticket":"TICKET_7d07634afbb25a7e823c0348d907e0790eeff97e"
}
}
* Connection #0 to host alfresco.mycompany.ch left intact
therefore I think it's client/AngularJS related.
=== Update 1: ===
I tried to add an interceptor to the $httpProvider as below, but it doesn't help. I don't see the headers I am setting there in any of the responses, although the interceptor gets called.
$httpProvider.interceptors.push(function() {
return {
'request': function(request) {
return request;
},
'response': function(response) {
console.log('Interceptor called.');
response.config.headers['MyTestHeader'] = '12345';
response.config.headers['Access-Control-Allow-Origin'] = '*';
return response;
}
};
});
=== Update 2: ===
Some more findings, but now a bit weird on the Alfresco side. I am doing two almost similar API calls, to the following two urls:
http://localhost:8080/alfresco/service/api/login
http://localhost:8080/alfresco/service/api/whatever
You can see, they only differ at the end. The one with /whatever returns a Access-Control-Allow-Origin response header, the one with /login does not. It must be related to the Alfresco config / webscript, but I have not yet found the origin of it.
curl -H "Origin: http://www.microsoft.com" --verbose "http://localhost:8080/alfresco/service/api/login"
* Trying ::1...
* Connected to localhost (::1) port 8080 (#0)
> GET /alfresco/service/api/login HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.43.0
> Accept: */*
> Origin: http://www.microsoft.com
>
< HTTP/1.1 400 Bad Request
< Server: Apache-Coyote/1.1
< Cache-Control: no-cache
< Expires: Thu, 01 Jan 1970 00:00:00 GMT
< Pragma: no-cache
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Thu, 13 Aug 2015 12:49:46 GMT
< Connection: close
<
But this one:
curl -H "Origin: http://www.microsoft.com" --verbose "http://localhost:8080/alfresco/service/api/whatever"
* Trying ::1...
* Connected to localhost (::1) port 8080 (#0)
> GET /alfresco/service/api/whatever HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.43.0
> Accept: */*
> Origin: http://www.microsoft.com
>
< HTTP/1.1 404 Not Found
< Server: Apache-Coyote/1.1
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Origin: http://www.microsoft.com
< Vary: Origin
< Cache-Control: no-cache
< Expires: Thu, 01 Jan 1970 00:00:00 GMT
< Pragma: no-cache
< Content-Type: text/html;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Thu, 13 Aug 2015 12:52:15 GMT
<
I also tried the CORS filter of Tomcat instead, same result.
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Questions:
(1) Am I missing something on the client/AngularJS $http side? Should I use a angular-http-interceptor? (Sorry, pretty new to AngularJS). I think that this is most probably the reason here, but not sure what's missing.
(2) I don't see why the CORS filter would not add the 'Access-Control-Allow-Origin' header to both responses but only to the one API call, since both API urls start with /alfresco/service, which should be handled by the CORS filter as per <url-pattern>/service/*</url-pattern>
(And why does it work for one API url, but for the other it does not? Only difference I see is that in one case, I am already authenticated and use an alf_ticket, in the other case I am not. But even if I add an (unnecessary) alf_ticket to the login call, it does not make any difference.)
(3) Why does it work in IE then at all? (by the way: with the Chrome extension https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi it also works in Chrome.)
Related SO question: cross domain call using REST Alfresco
I have the same issue, for some reason the login api "GET" call does not return "Access-Control-Allow-Origin" in the headers. WORKAROUND: The "POST" call works fine!
I faced similar issue and got it resolved by using "/alfresco/s/" instead of "/alfresco/service/".
In your case, try hitting using
http://localhost:8080/alfresco/s/api/login?u=admin&pw=admin.
Try if this works.

Resources