Python 客户端通过 Nextcloud 上的 OAuth2 访问 CalDAV
Python client to access CalDAV via OAuth2 on Nextcloud
使用 CalDAV 的规范 examples 始终使用 username/password 身份验证。但是 Nextcloud 支持 OAuth2,因此我想通过 oauth 使用 CalDAV。
我已经对 Google 日历 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 结合使用的文档也很少。我找到了 this posting,但仍然不清楚什么地方去了。
让我们从配置开始。在 Nextcloud 中,转到安全设置(https://mycloud.example.com/settings/admin/security). There is a section OAuth 2.0 clients
. Add a client. You can use any name, e.g. calendar
, but it is important that the redirect URI is http://localhost:8080
. Why? tools.run_flow()
will instantiate an http server to receive the authentication call on this address by default. Click "add". You should now see a new client ID. Copy the client ID and the secret (click the eye icon to reveal) to 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 实例并且应该有一条消息说“您即将授予 calendar 访问您的 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
现在,我们不再像 Google 中的原始示例那样调用 credentials.authorize(http=build_http())
,而是编写
caldav_client = caldav.DAVClient(
"https://mycloud.example.com/remote.php/dav/",
auth=OAuth(credentials))
就是这样!我们现在可以写
principal = caldav_client.principal()
calendars = principal.calendars()
使用 CalDAV 的规范 examples 始终使用 username/password 身份验证。但是 Nextcloud 支持 OAuth2,因此我想通过 oauth 使用 CalDAV。
我已经对 Google 日历 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 结合使用的文档也很少。我找到了 this posting,但仍然不清楚什么地方去了。
让我们从配置开始。在 Nextcloud 中,转到安全设置(https://mycloud.example.com/settings/admin/security). There is a section OAuth 2.0 clients
. Add a client. You can use any name, e.g. calendar
, but it is important that the redirect URI is http://localhost:8080
. Why? tools.run_flow()
will instantiate an http server to receive the authentication call on this address by default. Click "add". You should now see a new client ID. Copy the client ID and the secret (click the eye icon to reveal) to 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 实例并且应该有一条消息说“您即将授予 calendar 访问您的 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
现在,我们不再像 Google 中的原始示例那样调用 credentials.authorize(http=build_http())
,而是编写
caldav_client = caldav.DAVClient(
"https://mycloud.example.com/remote.php/dav/",
auth=OAuth(credentials))
就是这样!我们现在可以写
principal = caldav_client.principal()
calendars = principal.calendars()