Клиент Python для доступа к CalDAV через OAuth2 в Nextcloud
Канонические примеры использования CalDAV всегда используют аутентификацию по имени пользователя и паролю. Однако Nextcloud поддерживает OAuth2, поэтому я бы хотел использовать CalDAV через oauth.
Я уже сделал то же самое с API календаря Google, но просто адаптировал oauth2client
образец предоставлен Google:
client_secrets = 'client_secrets.json'
flow = client.flow_from_clientsecrets(client_secrets, scope="",
message=tools.message_if_missing(client_secrets))
storage = file.Storage('calendar_credentials.dat')
credentials = storage.get()
if credentials is None or credentials.invalid:
credentials = tools.run_flow(flow, storage)
http = credentials.authorize(http=build_http())
заменив build_http()
по примеру caldav.DAVClient
не работает. внутренний request()
API-интерфейсы совершенно разные, и вызов любого метода клиента caldav будет с треском провален, когда обернут authorize()
, Итак, вопрос: как интегрировать caldav.DAVClient
с oauth2client
?
Также нет документации по использованию OAuth с nextCloud. Я нашел это сообщение, но до сих пор не очевидно, что и где.
1 ответ
Давайте начнем с конфигурации. В Nextcloud перейдите в настройки безопасности ( https://mycloud.example.com/settings/admin/security). Есть раздел OAuth 2.0 clients
, Добавьте клиента. Вы можете использовать любое имя, например calendar
, но важно, чтобы URI перенаправления был http://localhost:8080
, Зачем? tools.run_flow()
создаст экземпляр http-сервера для получения вызова аутентификации по этому адресу по умолчанию. Нажмите "Добавить". Теперь вы должны увидеть новый идентификатор клиента. Скопируйте идентификатор клиента и секрет (нажмите значок глаза, чтобы открыть его) в client_secrets.json, который должен выглядеть следующим образом:
{
"web": {
"client_id": "stuff copied from Client Identifier",
"client_secret": "stuff copied from secret",
"auth_uri": "https://mycloud.example.com/index.php/apps/oauth2/authorize",
"token_uri": "https://mycloud.example.com/index.php/apps/oauth2/api/v1/token",
"redirect_uris": []
}
}
Теперь, когда вы запускаете пример из раздела вопросов, ваш браузер должен автоматически перейти к экземпляру mycloud.example.com, и должно появиться сообщение "Вы собираетесь предоставить доступ к календарю своей учетной записи mycloud.example.com". Нажмите "Предоставить доступ". После ввода вашего имени пользователя и пароля браузер должен быть перенаправлен на http://localhost:8080/, и вы должны увидеть сообщение "Процесс аутентификации завершен".
Заметки:
- Я не нашел разницы
client_secrets.json
начинается сweb
или сinstalled
, Это должен быть один из этих двух, как бы то ни было. - по-видимому,
redirect_uris
может оставаться пустым.
Теперь вопрос программирования (это ведь форум программиста...)
Конструктор caldav.DAVClient
позволяет auth
параметр, который должен быть экземпляром requests.auth.AuthBase
, Итак, давайте создадим один:
from requests.auth import AuthBase
class OAuth(AuthBase):
def __init__(self, credentials):
self.credentials = credentials
def __call__(self, r):
self.credentials.apply(r.headers)
return r
Сейчас вместо звонка credentials.authorize(http=build_http())
как в оригинальном примере от Google, мы пишем
caldav_client = caldav.DAVClient(
"https://mycloud.example.com/remote.php/dav/",
auth=OAuth(credentials))
Это оно! Теперь мы можем написать
principal = caldav_client.principal()
calendars = principal.calendars()
как в оригинальном примере.