【免费下载链接】authlibThe ultimate Python library in building OAuth, OpenID Connect clients and servers. JWS, JWE, JWK, JWA, JWT included.项目地址https://gitcode.com/gh_mirrors/au/authlib点击查看免费下载本文以 Authlib 的authlib.oauth2.rfc7662模块为核心系统讲解如何基于 RFC 7662OAuth 2.0 Token Introspection在授权服务器上注册内省端点Introspection Endpoint以及如何在无法直连令牌数据库的资源服务器上通过IntrospectTokenValidator远程校验访问令牌。读完本文你将能够独立实现授权服务器发布内省接口 资源服务器远程验证令牌的完整链路并理解 Authlib 在此流程中的核心抽象与底层校验逻辑。RFC 7662 与 Token Introspection 的应用场景Token Introspection令牌内省机制定义在 RFC 7662 中其核心目的是让**资源服务器Resource Server**在不直接访问授权服务器令牌数据库的前提下通过调用授权服务器提供的 HTTP 内省端点获知某个令牌的当前状态与元数据如是否活跃、归属的客户端、scope、过期时间等。典型应用场景包括资源服务器与授权服务器分离部署资源服务器无法直接查询Token表授权服务器需要统一管理访问令牌与刷新令牌的活跃状态、过期与吊销信息资源服务器需要依据内省结果中的scope做细粒度授权判断。在 Authlib 中该协议的通用实现位于 authlib/oauth2/rfc7662主要导出三个对象IntrospectionEndpoint供授权服务器注册的内省端点基类IntrospectTokenValidator供资源服务器使用的远程令牌校验器IntrospectionToken一个兼容TokenMixin的字典子类用于以属性方式访问内省响应中的字段。下文将分别从授权服务器端与资源服务器端两个角度展开实战配置。在授权服务器上注册 Introspection EndpointAuthlib 的AuthorizationServer通过.register_endpoint方法即可扩展令牌类端点该方法在 Flask 与 Django 两种集成下均可用对应参考 Flask 端点文档 与 Django 端点文档。使用前必须先编写一个继承自IntrospectionEndpoint的子类并补齐三个必需的方法query_token、introspect_token与check_permission。from authlib.oauth2.rfc7662 import IntrospectionEndpoint class MyIntrospectionEndpoint(IntrospectionEndpoint): def query_token(self, token, token_type_hint): if token_type_hint access_token: tok Token.query.filter_by(access_tokentoken).first() elif token_type_hint refresh_token: tok Token.query.filter_by(refresh_tokentoken).first() else: # without token_type_hint tok Token.query.filter_by(access_tokentoken).first() if not tok: tok Token.query.filter_by(refresh_tokentoken).first() return tok def introspect_token(self, token): return { active: True, client_id: token.client_id, token_type: token.token_type, username: get_token_username(token), scope: token.get_scope(), sub: get_token_user_sub(token), aud: token.client_id, iss: https://server.example.com/, exp: token.expires_at, iat: token.issued_at, } def check_permission(self, token, client, request): # for example, we only allow internal client to access introspection endpoint return client.client_type internal # register it to authorization server server.register_endpoint(MyIntrospectionEndpoint)注册完成后为内省端点配置路由即可对外提供响应。由于IntrospectionEndpoint继承自 TokenEndpoint内省请求按规范要求以POSTapplication/x-www-form-urlencoded提交app.route(/oauth/introspect, methods[POST]) def introspect_token(): return server.create_endpoint_response(MyIntrospectionEndpoint.ENDPOINT_NAME)其中ENDPOINT_NAME在 introspection.py 中被定义为introspection。若是 Django 集成写法与之对应例如from django.views.decorators.http import require_http_methods require_http_methods([POST]) def introspect_token(request): return server.create_endpoint_response(MyIntrospectionEndpoint.ENDPOINT_NAME, request)三个必须实现的方法及其职责对照 introspection.py 源码三个方法的职责如下query_token(token, token_type_hint)根据令牌字符串与类型提示从存储中查询令牌对象。基类中该方法抛出NotImplementedError必须由开发者实现。类型提示支持access_token与refresh_token两种取值未提供提示时Authlib 推荐的策略是先按访问令牌查询未命中再按刷新令牌查询该逻辑与 sqla_oauth2/functions.py 中create_query_token_func生成的行为完全一致。introspect_token(token)读取令牌对象并返回符合 RFC 7662 Section 2.2 的内省元数据字典。返回字段中若未显式包含active框架会在 create_introspection_payload 中自动补为True。check_permission(token, client, request)判断发起内省请求的客户端是否有权查看该令牌。返回False时令牌将被视为不可内省响应中active为false。内省请求的入参与校验流程基类IntrospectionEndpoint.authenticate_token的实现见 introspection.py说明了请求参数规范tokenREQUIRED待内省的令牌字符串。访问令牌对应access_token值刷新令牌对应refresh_token值token_type_hintOPTIONAL令牌类型提示仅允许access_token与refresh_token即TokenEndpoint.SUPPORTED_TOKEN_TYPES。check_params会做两类校验introspection.py缺少token参数时抛出InvalidRequestError错误码invalid_requesttoken_type_hint取值不在支持范围内时抛出UnsupportedTokenTypeError错误码unsupported_token_type。完整的create_endpoint_response流程为先通过authenticate_endpoint_client校验调用方客户端凭据默认使用client_secret_basic即 HTTP Basic 认证见 token_endpoint.py再查询并校验令牌最后生成 200 响应与 JSON 体。响应语义何时返回 activefalse在 create_introspection_payload 中以下三种情况都会返回{active: false}令牌不存在query_token返回None令牌已过期token.is_expired()为真令牌已被吊销token.is_revoked()为真。只有通过上述检查后才会调用开发者实现的introspect_token生成完整元数据。内省端点始终以 HTTP 200 返回 JSON令牌状态由响应体中的active布尔值表达这是 RFC 7662 的典型语义。结合测试验证端点行为仓库中的 tests/flask/test_oauth2/test_introspection_endpoint.py 完整验证了上述行为无效客户端凭据缺失、非法 Basic 头、错误 client id/secret均返回invalid_client缺少token参数返回invalid_request非法token_type_hint返回unsupported_token_type对不存在的令牌返回{active: false}使用有效 Basic 凭据 token_type_hintaccess_token时响应体包含client_id等元数据test_introspection_endpoint.py。对于使用 SQLAlchemy 的 Flask/Django 项目还可以直接用 create_query_token_func 生成query_token避免手写查询逻辑测试中即采用此方式见 test_introspection_endpoint.py。在资源服务器中使用 Introspection 校验令牌当资源服务器无法访问授权服务器的令牌数据库时可以将内省端点作为令牌校验的后端。Authlib 为此提供了IntrospectTokenValidator使用方法如下import requests from authlib.oauth2.rfc7662 import IntrospectTokenValidator from your_project import secrets class MyIntrospectTokenValidator(IntrospectTokenValidator): def introspect_token(self, token_string): url https://example.com/oauth/introspect data {token: token_string, token_type_hint: access_token} auth (secrets.internal_client_id, secrets.internal_client_secret) resp requests.post(url, datadata, authauth) resp.raise_for_status() return resp.json()随后将其实例注册进资源保护器require_oauth ResourceProtector() require_oauth.register_token_validator(MyIntrospectTokenValidator())需要注意使用IntrospectTokenValidator时require_oauth装饰器注入的current_token将是一个dict内省响应 JSON而不是数据库令牌对象。IntrospectTokenValidator 的校验逻辑对照 token_validator.py 源码IntrospectTokenValidator继承自 TokenValidator其工作方式为TOKEN_TYPE bearer即只处理Authorization: Bearer token形式的请求authenticate_token直接调用开发者实现的introspect_token把令牌字符串交给远端内省端点validate_token中先检查token是否存在且token[active]为真否则抛出InvalidTokenError对应 rfc6750/errors.py 中定义的 401invalid_token并生成WWW-Authenticate: Bearer ...响应头随后通过基类的scope_insufficient静态方法resource_protector.py将内省响应中的scope与资源端点要求的 scope 集合做比对不满足时抛出InsufficientScopeError403insufficient_scope。ResourceProtector在 validate_request 中依次执行解析Authorization头 → 调用validate_request→ 调用authenticate_token获取内省结果 → 调用validate_token做活跃性与 scope 校验最终把内省字典返回给受保护视图。内省响应元数据与 IntrospectionToken 便捷访问RFC 7662 Section 2.2 规定的响应元数据包括active、scope、client_id、username、token_type、exp、iat、nbf、sub、aud、iss、jti。Authlib 在 models.py 中提供了IntrospectionToken类它既是dict子类又混入TokenMixin并重写了__getattr__因此可以对上述 12 个字段以token.exp、token.client_id等属性方式访问访问不存在的属性则会正常抛出AttributeError。对应的单元测试见 tests/core/test_oauth2/test_rfc7662.py覆盖了client_id、scope、exp/get_expires_at、全部 12 个字段的属性访问以及非法属性抛AttributeError的行为。与 JWT 访问令牌RFC 9068的扩展结合在 Authlib 中Token Introspection 还被 RFC 9068JWT 访问令牌模块复用。JWTIntrospectionEndpoint继承自IntrospectionEndpoint见 authlib/oauth2/rfc9068/introspection.py自动完成 JWT 签名校验、iss/exp等声明校验并直接生成内省响应它要求开发者实现get_jwks可选实现get_username。其完整行为含过期令牌返回active: false、issuer 不匹配、无效声明返回 401invalid_token等分支由 tests/flask/test_oauth2/rfc9068/test_token_introspection.py 覆盖。这说明IntrospectionEndpoint设计上支持通过子类化扩展出面向不同令牌格式的内省能力。客户端侧的 Token Introspection 调用除了服务器两端Authlib 的 OAuth 2.0 客户端也封装了内省调用能力。在 docs/oauth2/client/http/index.rst 中可以看到OAuth2Session与AsyncOAuth2Client均提供introspect_token(token_endpoint, tokentoken)方法另有配套的revoke_token方便客户端在拿到令牌后主动查询其状态。相关 API 签名可参考 docs/oauth2/client/http/api.rst。小结与关键参考授权服务器端继承IntrospectionEndpoint实现query_token/introspect_token/check_permission通过server.register_endpoint(...)注册再用create_endpoint_response暴露为POST接口资源服务器端继承IntrospectTokenValidator并实现introspect_token发起远端 HTTP 调用注册进ResourceProtector后即可用require_oauth保护 API注意此时current_token为 dict语义要点无效/过期/吊销/无权内省的令牌统一返回{active: false}HTTP 状态始终为 200常用字段active、client_id、scope、sub、aud、iss、exp、iat、username、token_type、nbf、jti。进一步阅读可参考RFC 7662 文档、资源服务器总览、Flask 资源服务器示例以及核心实现 introspection.py、token_validator.py 与 models.py。赞分享【免费下载链接】authlibThe ultimate Python library in building OAuth, OpenID Connect clients and servers. JWS, JWE, JWK, JWA, JWT included.项目地址https://gitcode.com/gh_mirrors/au/authlib点击查看免费下载相关推荐Everywhere 安装部署指南在 Windows 上快速用上屏幕感知 AI 助手Everywhere 安装部署指南在 Windows 上快速用上屏幕感知 AI 助手 Everywhere 是一款屏幕感知型的桌面 AI 助手它能直接读懂你Authlib Flask OAuth 2.0 授权服务器令牌端点注册实战Revocation 与 Introspection 深度解析Authlib Flask OAuth 2.0 授权服务器令牌端点注册实战Revocation 与 Introspection 深度解析 本篇技术指南聚焦于RFC 7009 撤销端点实战指南Authlib 中 OAuth 2.0 Token Revocation 的完整实现与接入RFC 7009 撤销端点实战指南Authlib 中 OAuth 2.0 Token Revocation 的完整实现与接入 output_article上一篇APOLLO routined模块深度解读从Cloud.sqlite提取iOS学习位置与到访历史下一篇SciPy 仓库中的 PRIMA Python 移植版 pyprimaCOBYLA 无导数优化器的忠实翻译与实战指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考