惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V2EX - 技术
V2EX - 技术
P
Privacy International News Feed
Security Latest
Security Latest
H
Hacker News: Front Page
T
Tenable Blog
The Hacker News
The Hacker News
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
S
Security @ Cisco Blogs
Project Zero
Project Zero
O
OpenAI News
AI
AI
Spread Privacy
Spread Privacy
C
CERT Recently Published Vulnerability Notes
The Last Watchdog
The Last Watchdog
G
GRAHAM CLULEY
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Scott Helme
Scott Helme
Application and Cybersecurity Blog
Application and Cybersecurity Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
C
CXSECURITY Database RSS Feed - CXSecurity.com
NISL@THU
NISL@THU
A
Arctic Wolf
T
Threat Research - Cisco Blogs
PCI Perspectives
PCI Perspectives
N
News and Events Feed by Topic
C
Cyber Attacks, Cyber Crime and Cyber Security
C
Cybersecurity and Infrastructure Security Agency CISA
Simon Willison's Weblog
Simon Willison's Weblog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Know Your Adversary
Know Your Adversary
Google Online Security Blog
Google Online Security Blog
罗磊的独立博客
L
LINUX DO - 最新话题
U
Unit 42
S
Security Affairs
有赞技术团队
有赞技术团队
WordPress大学
WordPress大学
博客园 - 【当耐特】
T
The Exploit Database - CXSecurity.com
S
Schneier on Security
月光博客
月光博客
Engineering at Meta
Engineering at Meta
腾讯CDC
F
Full Disclosure
Cyberwarzone
Cyberwarzone
S
SegmentFault 最新的问题
Recorded Future
Recorded Future
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
博客园 - 司徒正美
The Cloudflare Blog

博客园 - 张占岭

springboot~关于构造方法注入和字段注入的选择 apisix~OpenResty各阶段的介绍 keycloak~aud受众字段的作用及如何生成 wso2~关于workbuddy中mcp在wso2中的授权端点 k8s~避免调度资源碎片化 WEB安全~csrf介绍 WEB安全~DPoP的介绍 WEB安全~csp的介绍 什么是中间人攻击 WEB安全~xss的介绍 k8s~pod资源限制和JVM的XMX配置 关于对wso2和keycloak的token交换的调研 keycloak~实现OAuth 2.0 Token Exchange backstage~实体的介绍及它们的关系 backstage~openapi的接入与protobuf的对比 backstage~将java服务添加到backstage backstage~对接github和gitlab backstage~开始一个backstage应用 apisix~graphQL的支持 wso2几个核心项目介绍 docker~BuildKit的介绍 k8s~secret资源的使用 算法~时间戳计算两个日期是否为同天同时同分 wso2~4.5升级到4.6需要更新的数据表 backstage~Backstage的概述 springboot~jpa优雅的软删除能力 springboot~ImportBeanDefinitionRegistrar在自定义RPC框架中的使用 keycloak~深入了解DefaultSegmentedDataContainer对象解决内存泄漏 keycloak~分布式部署中会话过期清理机制 jmeter进行接口压测 Keycloak~infinispan中MergedUpdate中lifespanMs和maxIdleTimeMs wso2~添加mcp服务的注意点
wso2~通过三方IDP的token置换wso2的token
张占岭 · 2026-01-26 · via 博客园 - 张占岭

参数:https://datatracker.ietf.org/doc/html/rfc7523

oauth2.0中的三方另类授权

了解OAuth 2.0中特定的授权类型(Grant Type)对于构建安全的认证流程至关重要。下面为你详细介绍这三种基于URN声明的扩展授权类型。

🔐 设备代码授权 (urn:ietf:params:oauth:grant-type:device_code)

这种授权模式专为输入能力受限或没有浏览器的设备设计,比如智能电视、游戏机、IoT设备或命令行工具(CLI)。

  • 工作原理:其核心是一个两步过程。

    1. 设备获取代码:设备上的应用首先向授权服务器(如 Microsoft Entra ID)的 /devicecode 端点发起请求。服务器会返回一组信息,包括一个简短的 user_code(用户代码)和一个 verification_uri(验证网址)。
    2. 用户授权:设备将 user_codeverification_uri 显示给用户,并提示用户在其他设备(如个人手机或电脑)上打开浏览器,访问该网址并输入代码。用户在授权服务器的正规页面上完成身份验证(可能包括多因素认证)并同意授权。在此期间,设备应用会定期轮询授权服务器的令牌端点,直到用户完成操作后获取访问令牌和刷新令牌。
  • 安全风险与防御:需要注意的是,此流程可能被用于进行高迷惑性的网络钓鱼攻击(称为“设备代码钓鱼”)。攻击者会诱导用户在真实的微软登录页面输入由攻击者生成的设备代码,从而授权一个恶意应用。防御措施包括在服务器端严格限制应用同意策略、实施条件访问策略(如要求来自合规设备),以及对用户进行安全教育。

🔄 令牌交换授权 (urn:ietf:params:oauth:grant-type:token-exchange)

令牌交换授权提供了强大的 interoperability(互操作性),允许将一个凭证或令牌交换为另一个不同的令牌,常用于服务之间的安全调用或身份映射。

  • 核心概念:它遵循 OAuth Token Exchange 规范,使得客户端能够使用一个现有的 subject_token(主体令牌)来换取一个新的、针对不同受众或资源的 access_token(访问令牌)。

  • 常见场景

    • 服务间调用:后端服务A可以使用自己持有的令牌,换取一个具有适当权限的、用于调用服务B的访问令牌。
    • 权限降级:一个高权限的应用在需要调用一个低信任度的服务时,可以换一个权限受限的令牌,以提升安全性。
    • 外部身份提供商集成:将外部IDP(如Google、Facebook)签发的令牌交换为内部系统的令牌,从而实现跨域身份联合。
    • 用户模拟:在严格管控下,服务可以换取一个代表特定用户身份的令牌(即模拟用户)。
  • 实施要点:令牌交换功能通常默认不开启,需要在服务器端(如Red Hat Single Sign-On)为客户端显式配置精细的权限策略。

⚙️ JWT持有者授权 (urn:ietf:params:oauth:grant-type:jwt-bearer)

这种授权类型允许客户端直接使用一个预先签名的JWT(JSON Web Token)作为断言(assertion)来获取访问令牌。

  • 基本流程:客户端向授权服务器的令牌端点发起POST请求,在请求体中,grant_type 参数设置为 urn:ietf:params:oauth:grant-type:jwt-bearer,并同时提供用作断言的 assertion 参数(即JWT本身)。授权服务器会验证该JWT的签名、有效期、颁发者等信息,验证通过后即颁发所请求的访问令牌。

  • 典型应用场景

    • 服务账户认证:在机器对机器(M2M)的通信中,一个服务可以使用事先配置好的JWT(通常基于私钥签名)来获取访问令牌,无需用户交互。这在CI/CD流水线或后台服务中非常常见。
    • 微服务架构:在微服务网络中,一个服务在收到访问令牌后,可以利用此流程向认证服务器换取一个范围(scope)更窄、专用于访问另一个特定微服务的令牌。

下面的表格清晰地对比了这三种授权类型的关键差异。

特性 设备代码授权 (device_code) 令牌交换授权 (token-exchange) JWT持有者授权 (jwt-bearer)
主要目的 方便输入受限设备上的用户授权 实现令牌之间的安全转换和身份委托 客户端使用已有的JWT直接获取访问令牌
令牌流 轮询机制 直接交换 断言式请求
典型应用 智能电视、IoT设备、CLI工具 服务间调用、权限降级、身份联合 机器对机器通信、服务账户、微服务

💎 总结与安全考量

选择哪种授权类型完全取决于你的具体应用场景。设备代码授权优化了受限设备的用户体验,令牌交换授权为复杂的服务间信任链提供了灵活性,而JWT持有者授权则是机器对机器通信的简洁高效方案。

在实施这些授权流程时,务必关注以下安全最佳实践:

  • 严格控制权限:遵循最小权限原则,只为应用授予其必需的最少权限。
  • 验证与监控:服务器端必须严格验证所有令牌和断言(如JWT的签名和有效期),并建立日志审计和异常行为监控机制。
  • 保护令牌:访问令牌和刷新令牌是敏感凭证,在传输和存储过程中必须加以保护。

wso2中的实战

wso2 sp的配置

Keycloak中客户端授权范围wso2-role中,添加aud的硬编码

图片

配置认证grant_type类型

图片

keycloak idp的配置

keycloak中为客户端开启roles之后,如果有用户有客户端的角色,会在jwt中多出来aud数组字段,也可以为wso2客户端添加自定义的client scope,然后为它添加aud的cliams

IDP名称必须与IDP中token的Issuer相同

图片

测试

curl -X POST 'https://test-apim.xxx.com/oauth2/token' -H 'Content-Type: application/json' -H 'Content-Type: application/json' -u 'wso2-sp-client-id:wso2-sp-client-secret' --basic -d '{
"grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
"assertion": "abc.abc.abc",
"scope": "apim:subscribe"
}'

scope参数如果不传,默认是default,对于apim的开发者平台,这个值必须传,否则无权限添加应用和订阅api

这块功能scope使用你认证能数里的scope,还是使用默认的default,主要在IDP的Claim Configuration配置中进行设置,如图:

如果keycloak_token过期,就返回这个400错误

{
"error_description": "JSON Web Token is expired., Expiration Time(ms) : 1769413736000, TimeStamp Skew : 0, Current Time : 1769413748585. JWT Rejected and validation terminated",
"error": "invalid_grant"
}

如果成功,会返wso2平台的token,需要注意这个返回值里scope,如果它是default,那是没有操作application的权限的

{
"access_token": "8b23bf56-f8d2-33fa-9962-f298a797ce94",
"refresh_token": "aad2555-30b0-3591-8c70-b2cdc042cc41",
"scope": "apim:subscribe openid",
"id_token": "",
"token_type": "Bearer",
"expires_in": 3185
}

用户登录成功后,会初始化用户表,需要注意的是,这种urn:ietf:params:oauth:grant-type:jwt-bearer首次登录添加的用户,它位于wso2am_db.idn_auth_user表,user_name同样是三方社区token中的sub字段;而标准oauth的授权码认证后,除了在wso2am_db.idn_auth_user表初始化外,还在wso2am_share_db.um_user表也会添加一份用户数据。

【添加的用户没有订阅者角色,导致用户建立的应用无法订阅API】

  • 对于上面的um_user中的用户,它在carbon平台是可以查询到的,它默认是没有subscribe权限的,只有everyone权限
  • 这时,它建立的应用,应用是无法订阅api的,我们需要同时为um_user的用户初始化角色subscribe
  • 这块功能由product-is系统提供,所以在共享库wso2am_shared_db里,数据表为um_hybrid_roleum_hybrid_user_role
  • 调整源码cargin-apimgt项目org.wso2.carbon.apimgt.impl.issuers.configureForJWTGrantOrExchangeGrant()方法
  • 再执行FederatedUserSyncUtil.syncFederatedUserToUMUser(tenantDomain, userName)方法,为期添加初始化um_hybrid_user_role的脚本

注意,当wso2am_share_db.um_user表没有这个用户数据时,你再为应用生成consumer_key时调用generate-keys接口,会出现错误,所以,我们需要想办法,在wso2am_share_db.um_user表表初始化一条用户数据,um_user_name与wso2am_db.idn_auth_user表的user_name保持一致即可,即三方IDP的user_id即可

默认应用如何创建

通过获取用户应用的接口,完成后,如果没有默认应用,会为用户自动创建,即初始化下面两张表

  • am_subscriber
  • am_application

首次无订阅者和应用时,需要调用获取应用接口

    {
      "count": 1,
      "list": [
        {
          "applicationId": "46fd899d-5612-4708-82f7-a768c9d94678",
          "name": "默认应用",
          "throttlingPolicy": "Unlimited",
          "description": "系统为您创建的默认应用,xxxx",
          "status": "APPROVED",
          "groups": [],
          "subscriptionCount": 0,
          "attributes": {},
          "owner": "819b3483-d859-4f41-854a-907aec27a068",
          "tokenType": "DEFAULT",
          "createdTime": "1771910083000",
          "updatedTime": "1771910083000"
        }
      ],
      "pagination": {
        "offset": 0,
        "limit": 25,
        "total": 1,
        "next": "",
        "previous": ""
      }
    }

为应用生成consumer_key和consumer_secret接口

前提,先为用户初始化wso2am_share_db.um_user表,否则会出现错误,consumer_key为空等问题

{
  "code": 900967,
  "message": "General Error",
  "description": "Server Error Occurred",
  "moreInfo": "",
  "error": []
}

当接口执行成功后,会初始化下面三个数据表

  • am_application_registration

  • am_application_key_mapping

  • idn_oauth_consumer_apps

  • GET /applications/application_uuid/generate-keys

{
  "keyType": "PRODUCTION",
  "grantTypesToBeSupported": [
    "password",
    "client_credentials"
  ],
  "callbackUrl": "",
  "additionalProperties": {
    "application_access_token_expiry_time": "36000",
    "user_access_token_expiry_time": "36000",
    "refresh_token_expiry_time": "36000",
    "id_token_expiry_time": "36000",
    "pkceMandatory": "false",
    "pkceSupportPlain": "false",
    "bypassClientCredentials": "false"
  },
  "keyManager": "aefd5cd3-c18a-47f8-91c9-2fa42767b4bf",
  "validityTime": 3600,
  "scopes": [
    "default"
  ]
}

生成的am_application_key_mapping表中,consumer_key是非空的,这个很重要。

自动添加默认应用的原理[这些在源码里已经实现],这块不需要调整的源码已支持应用添加,consumer_key的生成需要手动调用接口

为用户添加了订阅者,默认应用,应用的consumerKey和consumerSecret等,用户可以手动为应该生成token

SubscriberRegistrationInterceptor是添加订阅者的入口

  • org.wso2.carbon.apimgt.rest.api.util.interceptors.SubscriberRegistrationInterceptor
    • handleMessage方法,订阅被注册后,如果没有应用,会添加默认认证
      • apiConsumer.addSubscriber(username, groupId);
        • org.wso2.carbon.apimgt.impl.AbstractAPIManager.addSubscriber()

添加默认应用的方法优化

  • org.wso2.carbon.apimgt.impl.AbstractAPIManager.addDefaultApplicationForSubscriber()方法