core: caldav doesn't work with public calendars

The problem

I have a public calendar shared from iCloud, but I can’t get it to work with the caldav platform - the logs suggest the request is Unauthorized, but it shouldn’t need to be authorized, and indeed I can wget the calendar URL without any login details.

I don’t particularly want to give Home Assistant credentials for my iCloud account, and the calendar in question doesn’t contain any personal information, so anonymous access seems appropriate. Am I doing something wrong with the configuration?

What version of Home Assistant Core has the issue?

2022.4.5

What was the last working version of Home Assistant Core?

No response

What type of installation are you running?

Home Assistant Container

Integration causing the issue

caldav

Link to integration documentation on our website

https://www.home-assistant.io/integrations/caldav/

Diagnostics information

No response

Example YAML snippet

calendar:
  - platform: caldav
    url: https://p102-caldav.icloud.com/published/2/LOTSOFLETTERSANDNUMBERS

Anything in the logs that might be useful for us?

2022-04-17 21:25:40 ERROR (MainThread) [homeassistant.components.calendar] Error while setting up caldav platform for calendar
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 249, in _async_setup_platform
    await asyncio.shield(task)
  File "/usr/local/lib/python3.9/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/usr/src/homeassistant/homeassistant/components/caldav/calendar.py", line 87, in setup_platform
    calendars = client.principal().calendars()
  File "/usr/local/lib/python3.9/site-packages/caldav/davclient.py", line 350, in principal
    self._principal = Principal(client=self, *largs, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/caldav/objects.py", line 399, in __init__
    cup = self.get_property(dav.CurrentUserPrincipal())
  File "/usr/local/lib/python3.9/site-packages/caldav/objects.py", line 174, in get_property
    foo = self.get_properties([prop], **passthrough)
  File "/usr/local/lib/python3.9/site-packages/caldav/objects.py", line 197, in get_properties
    response = self._query_properties(props, depth)
  File "/usr/local/lib/python3.9/site-packages/caldav/objects.py", line 141, in _query_properties
    return self._query(root, depth)
  File "/usr/local/lib/python3.9/site-packages/caldav/objects.py", line 159, in _query
    ret = getattr(self.client, query_method)(
  File "/usr/local/lib/python3.9/site-packages/caldav/davclient.py", line 398, in propfind
    return self.request(url or self.url, "PROPFIND", props,
  File "/usr/local/lib/python3.9/site-packages/caldav/davclient.py", line 618, in request
    raise ex
caldav.lib.error.AuthorizationError: AuthorizationError at 'https://p102-caldav.icloud.com/published/2/LOTSOFLETTERSANDNUMBERS', reason 'Unauthorized'

Additional information

No response

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 1
  • Comments: 18 (4 by maintainers)

Most upvoted comments

I think that if the HomeAssistant module was working with ICS feeds earlier, then I think we ought to look into that and get it to work again - but I don’t have the capacity today at least, and I think the problem is in the HA-module (which I haven’t looked much into), not with the python caldav library (which I’m taking some responsibility for) 😃

For the clarification - caldav is a two-way standard for communicating with a calendar server (retrieve events, search a calendar for some specific date range, get a list of updated events, save changes, add events, etc). All calendar data passed will be in the ICS (icalendar) format. Most modern calendar servers also allows an ICS feed to be published (for calendars that are public), basically allowing a client to get a complete copy of the full calendar, but this is not a part of the caldav standard, and should be accessible even without using the caldav library.

Try to use just https://caldav.icloud.com/ as the URL, and it should work.

There seems to be a regression somewhere that the caldav integration earlier worked also for ics feeds and not only caldav URLs. I’m not sure if this regression is in the python caldav library (which I’m maintaining) or if it’s in the home assistant plugin, and I don’t have capacity to do research on that now. I can only point out that there should be no need of using the caldav library at all when utilizing a ics feed 😃

FWIW I have a “local calendar” integration in the works https://github.com/allenporter/home-assistant-core/tree/local-calendar/homeassistant/components/local_calendar that can read ICS files that i’m working on getting ready for core.

I’m not sure that it’s going to be able to sync with remote calendar calendar, but maybe a one-time import…

Tbh, when checking out the Caldav code it’s indeed pretty clear that it’s not made at all for just reading ICS files.

The python caldav library or the home assistant module?

I haven’t looked into the home assistant module yet, but I think it would make sense to have one calendar module for home assistant that would accept both caldav and an ics feed.

I have the same issue with an Outlook published calendar. It also seems to be a duplicate of #66599

The cause of the issue seems to be this line of code return self.request(url or self.url, "PROPFIND", props, {'Depth': str(depth)}) in the caldav client itself (https://github.com/python-caldav/caldav/blob/master/caldav/davclient.py#L392). This method seems to be using PROPFIND as the method for the request and most likely the servers only allow GET requests.

Not sure if there’s a way around this

//edit: dug a bit deeper in some other issues here and it seems like there’s a big release on it’s way for the webdav client: https://github.com/home-assistant/core/issues/65804#issuecomment-1098551298 . Not sure if it’s going to resolve this issue but I’d rather wait and see if it works with that branch prior to start digging in the code to see how I could get this working 😃