保护全局 API 资源
使用 Logto 的基于角色的访问控制 (RBAC) 保护产品范围内的 API。分配全局角色和权限,以控制你应用中所有用户和客户端的访问。
什么是全局 API 资源?
全局 API 资源是你应用中所有用户都可以访问的端点或服务,无论属于哪个组织或租户。这些通常是面向公众的 API、核心产品服务,或任何不限定于特定组织的端点。
使用场景包括
- 在你的用户群体中共享的公共 API 或端点。
- 不绑定多租户的微服务。
- 所有客户都使用的核心应用 API(如
/api/users、/api/products)。
Logto 允许你结合 OAuth 2.1 和灵活的基于角色的访问控制来保护这些 API。
在 Logto 中如何工作
- API 资源和权限是全局注册的:你想要保护的每个 API 都用唯一的资源指示器(URI)和一组控制访问的权限(scopes)进行定义。
- 访问由全局角色控制:你可以将权限分配给角色,然后将角色分配给用户或客户端。
- 与组织级权限分离:全局 API 资源没有组织上下文。但如有需要,可以与组织角色结合使用,提供额外的上下文层。要保护组织级 API,请参见 保护组织级 API 资源。
实现概览
- 注册你的 API 资源 并在 Logto 中定义其权限。
- 定义角色,为访问 API 分配所需权限。
- 分配角色 给用户或客户端。
- 使用 OAuth 2.0 授权流程 获取 API 的访问令牌(resource 参数必须与注册的 API 标识符一致)。
- 在你的 API 中验证访问令牌,以强制执行权限。
理解资源指示器
Logto 按照 RFC 8707: OAuth 2.0 的资源指示器 建模 API 资源。资源指示器 是唯一标识所请求目标 API 或服务的 URI。
要点
- 资源指示器必须是绝对 URI(如
https://api.example.com) - 不包含片段部分;尽量避免使用查询字符串。
- 资源指示器支持受众限制令牌和多 API 架构。
示例
- Management API:
https://my-tenant.logto.app/api - 自定义全局 API:
https://api.yourapp.com
授权流程:认证 (Authentication) 并保护你的 API
以下流程适用于交互式用户认证 (Authentication)(浏览器 / 应用)和后端机器对机器 (M2M) 场景。
请注意,该流程未包含所有必需参数或头信息的详细说明,重点展示关键步骤。继续阅读以了解实际流程。
用户认证 (Authentication) = 浏览器 / 应用。M2M = 使用客户端凭证的后端服务或脚本。
resource 参数必须与 Logto 中注册的 API 标识符(资源指示器)完全一致。
实现步骤
注册你的 API 资源
- 前往 控制台 → API 资源。
- 创建新的 API 资源(如
https://api.yourapp.com/org),并定义其权限(scopes)。
完整配置步骤见 定义带权限的 API 资源。
设置全局角色
- 前往 控制台 → 角色。
- 创建与你 API 权限对应的角色(如
read:products、write:products)。 - 将这些角色分配给需要访问 API 的用户或客户端。
完整配置步骤见 使用全局角色。
获取全局 API 资源的访问令牌
在访问全局 API 资源前,你的客户端必须获取访问令牌。Logto 会为全局 API 资源签发 JSON Web Token (JWT) 作为访问令牌。通常使用 OAuth 2.0 授权码流程、刷新令牌流程 或 客户端凭证流程 完成。
授权码或刷新令牌流程
所有 Logto 官方 SDK 都原生支持使用刷新令牌流程获取全局 API 资源的访问令牌。你也可以用标准 OAuth 2.0 / OIDC 客户端库实现该流程。
- Logto SDK
- OAuth 2.0 / OIDC client library
初始化 Logto 客户端时,将资源指示器添加到 resources 参数(数组),然后将所需权限(scopes)添加到 scopes 参数。
用户认证 (Authentication) 后,请在请求访问令牌时(如调用 getAccessToken())传递资源指示器到 resource 参数或类似参数中。
各 SDK 详情见 快速开始。
配置 OAuth 2.0 客户端或初始化授权码流程时,确保在授权请求中包含 resource 参数和所需 scopes。
部分库可能不原生支持 resource 参数,但通常允许你在授权请求中传递额外参数。具体请查阅你的库文档。
以下是带 resource 和 scope 参数的授权请求非规范示例:
GET /oidc/auth?response_type=code
&client_id=your-client-id
&redirect_uri=https://your-app.com/callback
&scope=openid profile offline_access read:products write:products
&resource=https://api.your-app.com
&code_challenge=abc123
&code_challenge_method=S256
&state=xyz
HTTP/1.1
Host: your.logto.endpoint
用户认证 (Authentication) 后,你将收到授权码。通过向 Logto 的 /oidc/token 端点发起 POST 请求,并在请求体中包含 resource 参数,将该授权码兑换为访问令牌。
以下是使用授权码模式的令牌请求非规范示例:
POST /oidc/token HTTP/1.1
Host: your.logto.endpoint
Content-Type: application/x-www-form-urlencoded
Authorization: Basic base64(client_id:client_secret)
grant_type=authorization_code
&code=authorization-code-received
&redirect_uri=https://your-app.com/callback
&resource=https://api.your-app.com
你也可以使用 refresh_token 模式,在请求中包含 resource 参数,无需用户交互即可获取新访问令牌。
以下是使用刷新令牌模式的令牌请求非规范示例:
POST /oidc/token HTTP/1.1
Host: your.logto.endpoint
Content-Type: application/x-www-form-urlencoded
Authorization: Basic base64(client_id:client_secret)
grant_type=refresh_token
&refresh_token=your-refresh-token
&resource=https://api.your-app.com
客户端凭证流程
对于机器对机器 (M2M) 场景,你可以使用客户端凭证流程获取全局 API 资源的访问令牌。通过向 Logto 的 /oidc/token 端点发起 POST 请求,使用你的客户端 ID 和密钥请求访问令牌。
请求中需包含两个关键参数:
resource:你要访问的 API 的资源指示器 URI(如https://api.yourapp.com)。scope:你要请求的 API 权限(如read:products write:products)。
以下是使用客户端凭证模式的令牌请求非规范示例:
POST /oidc/token HTTP/1.1
Host: your.logto.endpoint
Content-Type: application/x-www-form-urlencoded
Authorization: Basic base64(client_id:client_secret)
grant_type=client_credentials
&resource=https://api.yourapp.com
&scope=read:products write:products
在你的 API 中验证 JWT 访问令牌
Logto 签发的 JWT 包含你的 API 可用于强制授权 (Authorization) 的声明 (Claims)。
当你的 API 收到带有 Logto 签发的访问令牌的请求时,你应:
- 验证令牌签名(使用 Logto 的 JWKs)。
- 确认令牌未过期(
exp声明 (Claim))。 - 检查
iss(发行者 (Issuer))是否与你的 Logto 端点一致。 - 确保
aud(受众 (Audience))与你注册的 API 资源标识符一致(如https://api.yourapp.com)。 - 拆分
scope声明 (Claim)(以空格分隔),检查所需权限。
分步和特定语言指南见 如何验证访问令牌。
可选:处理用户权限变更
👷 功能开发中。🚧
最佳实践与安全建议
- 权限应以业务为驱动:使用能映射到实际操作的清晰名称。
- 令牌过期时间应短:如果令牌泄露可降低风险。
- 限制授予的权限 (Scopes):只给令牌实际需要的权限。
- 使用受众限制:始终验证
aud声明 (Claim),防止滥用。
常见问题
如果我的客户端不支持 resource 参数怎么办?{what-if-my-client-doesn-t-support-the-resource-parameter}
在 Logto 控制台设置默认 API 资源。当令牌请求中未指定 resource 参数时,令牌将默认使用该受众 (Audience)。
为什么我的 API 返回 401 未授权?{why-do-i-get-401-unauthorized-from-my-api}
请检查以下常见问题:
- 令牌签名:确认你的后端从 Logto 获取了正确的 JWKs
- 令牌过期:确保令牌未过期(
exp声明 (Claim)) - 受众 (Audience):确认
aud声明 (Claim) 与你注册的 API 资源指示器一致 - 所需权限 (Scopes):确认令牌的
scope声明 (Claim) 包含所需权限
如何在没有完整客户端的情况下测试?{how-do-i-test-without-a-full-client}
使用 个人访问令牌 模拟认证 (Authentication) 调用。这样你可以在不实现完整 OAuth 流程的情况下测试 API 端点。
请求权限时可以使用 scope 前缀或简写吗?{can-i-use-scope-prefixes-or-shortened-versions}
不可以。Scope 名称必须完全匹配你在 API 资源中定义的权限名称。前缀和简写不能作为通配符使用。
示例:
如果你的 API 资源定义了:
read:electionswrite:elections
你必须请求:
scopes: ["read:elections", "write:elections"]
这样不会生效:
scopes: ["read", "write"] // ❌ 不匹配权限名称
延伸阅读
如何验证访问令牌RBAC 实践:为你的应用实现安全授权 (Authorization)
自定义令牌声明 (Claims) RFC 8707: 资源指示器