Python客户端在Nextcloud上通过OAuth2访问CalDAV

Python客户端在Nextcloud上通过OAuth2访问CalDAV,python,oauth-2.0,caldav,nextcloud,Python,Oauth 2.0,Caldav,Nextcloud,使用CalDAV的规范始终使用用户名/密码身份验证。但是Nextcloud支持OAuth2,因此我希望通过oauth使用CalDAV 我已经对Google calendar API做了同样的操作,但只是修改了Google提供的oauth2client示例: client_secrets = 'client_secrets.json' flow = client.flow_from_clientsecrets(client_secrets, scope="",

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

我已经对Google calendar API做了同样的操作,但只是修改了Google提供的
oauth2client
示例:

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一起使用的文档也很少。我已经找到了,但是仍然不清楚什么是正确的。

让我们从配置开始。在Nextcloud中,转到安全设置()。有一个部分是OAuth 2.0客户端。添加一个客户端。您可以使用任何名称,例如
日历
,但重定向URI必须是
http://localhost:8080
。为什么?<代码>工具。默认情况下,run_flow()将实例化http服务器以接收此地址上的身份验证调用。单击“添加”。您现在应该看到一个新的客户端ID。复制客户端ID和密码(单击眼睛图标以显示),然后将其显示为:

{
  "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帐户的访问权。”单击“授予访问权”。输入用户名和密码后,浏览器现在应该重定向到,您应该会看到消息“身份验证流已完成”

注:

  • 我发现
    client\u secrets.json
    是否以
    web
    或者安装了
    。然而,它必须是这两种情况之一
  • 显然,
    redirect\u uri
    可以保持为空
现在是编程问题(毕竟这是一个程序员论坛…)

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\u http())
,而是编写

caldav_client = caldav.DAVClient(
    "https://mycloud.example.com/remote.php/dav/",
    auth=OAuth(credentials))
就这样!我们现在可以写作了

principal = caldav_client.principal()
calendars = principal.calendars()

如中所示。

感谢您提供的示例。我可以知道我们是否可以在服务器端构建oauth进程,而不必在前端进行身份验证?