1

使用 CalDAV的规范示例始终使用用户名/密码身份验证。但是 Nextcloud 支持 OAuth2,因此我想通过 oauth 使用 CalDAV。

我已经对 Google 日历 API 做了同样的事情,但只是修改了oauth2clientGoogle 提供的示例:

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

此外,关于在 nextCloud 中使用 OAuth 的文档也很少。我找到了这个帖子,但仍然不清楚去哪里。

4

1 回答 1

2

让我们从配置开始。在 Nextcloud 中,转到安全设置 ( https://mycloud.example.com/settings/admin/security )。有一节OAuth 2.0 clients。添加客户端。您可以使用任何名称,例如calendar,但重要的是重定向 URI 是http://localhost:8080。为什么?tools.run_flow()默认情况下,将实例化一个 http 服务器以接收对该地址的身份验证调用。点击“添加”。您现在应该会看到一个新的客户端 ID。将客户端 ID 和密钥(单击眼睛图标以显示)复制到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()

原来的例子一样。

于 2018-05-09T17:09:34.470 回答