跳转到主要内容

简单而灵活的Python OAuth 2.0设备流认证

项目描述

loctocat

PyPI - Python Version PyPI GitHub release (latest SemVer including pre-releases) PyPI - License

loctocat将简单而灵活的OAuth 2.0设备流认证引入Python。它具有内置的asyncio支持,并为流行的服务预定义了认证器。此外,它完全符合RFC 8628,使其与任何正确实现标准的OAuth2支持服务兼容。

安装

pip install loctocat

基本用法

Authenticator

每个认证流程都从loctocat的Authenticator类开始。

from loctocat import Authenticator

authenticator = Authenticator(
    client_id="your_client_id",
    auth_url="https://example.com/oauth2/authorize",
    token_url="https://example.com/oauth2/token",
    scopes=["list", "of", "scopes"],
)

很简单——只需用您的客户端ID、授权URL(您将在其中获取设备和用户代码)、令牌URL(您将在其中轮询授权服务器以获取访问令牌)和任何您需要的范围列表实例化该类。

一旦您有了Authenticator,获取访问令牌就像这样简单

token = authenticator.authenticate()

哇。这很简单。

Authenticator.authenticate() 将按顺序

  1. 从授权服务器获取设备和用户代码
  2. 提示用户访问验证URL并输入用户代码
  3. 轮询授权服务器以获取访问令牌
  4. 将访问令牌作为字符串返回

这是使用Authenticator与GitHub进行认证的示例

# https://githubdocs.cn/en/developers/apps/building-oauth-apps/authorizing-oauth-apps#device-flow

from loctocat import Authenticator

authenticator = Authenticator(
    client_id="github_client_id",  # Replace this with your app's actual client ID, obviously.
    auth_url="https://github.com/login/device/code",
    token_url="https://github.com/login/oauth/access_token",
    scopes=["repo"],  # https://githubdocs.cn/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps
)

token = authenticator.authenticate()

就像我说的那样,很简单。除非您正在构建异步应用程序,在这种情况下,这根本不起作用,因为Authenticator.authenticate()是一个阻塞调用。幸运的是,loctocat已经为您解决了这个问题。

AsyncAuthenticator

AsyncAuthenticatorAuthenticator 的一个子类,其功能完全相同,只是所有方法都是异步的(因此必须使用 await 来调用)。以下是一个 AsyncAuthenticator 的使用示例

from loctocat import AsyncAuthenticator

authenticator = AsyncAuthenticator(
    client_id="your_client_id",
    auth_url="https://example.com/oauth2/authorize",
    token_url="https://example.com/oauth2/token",
    scopes=["list", "of", "scopes"],
)

token = await authenticator.authenticate()

哇。这很简单。

AsyncAuthenticator.authenticate() 将——等等,我好像有似曾相识的感觉。

高级用法

也许 Authenticator.authenticate() 对于你来说太简单了。也许你更愿意,我不知道,自己处理用户界面的身份验证提示,或者控制 loctocat 开始轮询访问令牌的时间。幸运的是,loctocat 已经为你考虑到了。

(请注意,AsyncAuthenticatorAuthenticator 的一个子类,并继承其所有方法和属性。)

Authenticator.ping()

Authenticator.ping() 从授权服务器请求设备和用户代码,返回一个类似这样的 LoctocatAuthInfo 对象

class LoctocatAuthInfo:
    device_code: str
    user_code: str
    verification_uri: str
    expires_in: int
    interval: int

非常直观。你可以用这些信息做任何你想做的事情(除了更改它们——LoctocatAuthInfo 的属性是只读的)。例如,你可以使用包含用户代码和验证 URI 的自定义文本提示用户

auth_info = authenticator.ping()

print(f"Check it out, yo! This is some epic text telling YOU to go {auth_info.verification_uri} and enter {auth_info.user_code}! Swag!")

Authenticator.poll()

Authenticator.poll() 轮询授权服务器以获取访问令牌,并将其作为字符串返回。你不需要将 Authenticator.ping() 返回的 LoctocatAuthInfo 对象传递给 Authenticator.poll() ——授权信息会自动由 Authenticator 记忆。你只需调用该方法即可

# Authenticator.ping() must have been called on the Authenticator object already or this will not work.

token = authenticator.poll()

哇。这很简单。

(有趣的事实:Authenticator.authenticate() 只是 ping()poll() 的包装器。)

专业用法

也许 高级用法 对于你来说还不够高级。也许你正在使用一个需要超出 Authenticator 定义参数的授权服务器。也许你想要自定义 Authenticator.authenticate() 显示的提示和信息,而无需使用 Authenticator.ping()Authenticator.poll()。也许 loctocat 为你喜欢的服务提供了一个预定义的验证器,你想使用它。不幸的是,loctocat 并没有涵盖这些。

...

好吧,实际上 loctocat 确实为你考虑到了,但这些是 loctocat 未完成的文档网站的内容。重点是未完成。它还没有完成。

幸运的是,loctocat 已经为你考虑到了。loctocat 是一个相当小的库,它的公共模块和类都在源代码中有适当的文档,因此你可以通过示例学习,并四处看看。

或者你可以等到我完成文档网站。我不是你的妈妈。

常见问题解答

也许你对 loctocat 有一些问题,这些问题在本 README 的其他部分没有解答。也许你只是想看我自我对话,大概两段。幸运的是,loctocat 已经为你考虑到了。

问:loctowhat 现在怎么办

答:锁 + Octocat。loctocat 是由于我需要一个实现 GitHub OAuth 2.0 设备流身份验证的 Python 库而产生的。

问:我确信我可以使用 requests-oauthlib 或 [INSERT OAUTH LIBRARY HERE] 很好地完成这个任务

答:当然可以。事实上,loctocat 在底层使用 requests 和 oauthlib。所以让我们放下 loctocat,一起用 requests 和 oauthlib 编写一个用于通过 GitHub 进行身份验证的函数吧!

import time

import requests
from oauthlib.oauth2 import DeviceClient

def authenticate_with_github(client_id: str, scopes: list[str]) -> str:
    auth_url = "https://github.com/login/device/code"
    token_url = "https://github.com/login/oauth/access_token"
    client = DeviceClient(client_id=client_id, scope=scopes)
    
    ping_uri = client.prepare_request_uri(auth_url)
    response = requests.post(ping_uri, headers={"Accept": "application/json"}).json()
    
    poll_uri = client.prepare_request_uri(token_url, code=response["device_code"])
    while True:
        response = requests.post(poll_uri, headers={"Accept": "application/json"}).json()
        
        if "error" in response:
            if response["error"] in ["authorization_pending", "slow_down"]:
                time.sleep(response["interval"])
                continue
            else:
                raise RuntimeError(response["error"])
        else:
            return response["access_token"]

该死的,那个盘子能煮!

现在让我们用 loctocat 做同样的事情。

from loctocat.predefined import GitHubAuthenticator

def authenticate_with_github(client_id: str, scopes: list[str]) -> str:
    authenticator = GitHubAuthenticator(client_id=client_id, scopes=scopes)
    return authenticator.authenticate()

# "Hey, that's cheating!" Fine, let's do it the hard way.

from loctocat import Authenticator

def authenticate_with_github(client_id: str, scopes: list[str]) -> str:
    authenticator = Authenticator(
        client_id=client_id,
        auth_url="https://github.com/login/device/code",
        token_url="https://github.com/login/oauth/access_token",
        scopes=scopes
    )
    
    return authenticator.authenticate()

哇。这很简单。

我制作 loctocat 的部分原因是因为没有其他库能够像 loctocat 一样完成这项任务,而且完成得不好。第一个例子很糟糕。第二个例子很棒。案例结束。

问:loctocat 无法与 [INSERT SERVICE HERE] 一起工作,我非常沮丧 AAAAGGGGGGHHHHH

答:loctocat 与 OAuth 2.0 设备授权标准兼容,因此可能是服务的问题。请确保该服务确实支持设备流程,并且通常与 RFC 8628 兼容。如果你确定 loctocat 是问题所在,请 打开一个问题

问:哦我的天哪,谢谢你,我一直在寻找这样的库,你不知道我有多高兴

欢迎!😄

许可证

在开发者必须格外小心,避免侵犯他人知识产权的时代,您一定希望一个如此出色的库能够以宽松的许可协议提供。幸运的是,loctocat为您提供了保障。

loctocat遵循MIT许可协议

项目详情


下载文件

下载适合您平台的文件。如果您不确定该选择哪个,请了解更多关于安装包的信息。

源代码分发

loctocat-1.0.3.tar.gz (12.3 kB 查看哈希值)

上传时间 源代码

构建分发

loctocat-1.0.3-py3-none-any.whl (14.2 kB 查看哈希值)

上传时间 Python 3

支持