|
参数: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)。
🔄 令牌交换授权 (urn:ietf:params:oauth:grant-type:token-exchange)
令牌交换授权提供了强大的 interoperability(互操作性),允许将一个凭证或令牌交换为另一个不同的令牌,常用于服务之间的安全调用或身份映射。
⚙️ JWT持有者授权 (urn:ietf:params:oauth:grant-type:jwt-bearer)
这种授权类型允许客户端直接使用一个预先签名的JWT(JSON Web Token)作为断言(assertion)来获取访问令牌。
下面的表格清晰地对比了这三种授权类型的关键差异。
| 特性 |
设备代码授权 (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】
注意,当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
首次无订阅者和应用时,需要调用获取应用接口
- GET https://test-apim.pkulaw.com/api/am/devportal/v3/applications
- header Authorization bearer <token>
- 响应结果,没有应该会自动添加默认应用
{
"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()方法
作者:仓储大叔,张占岭,
荣誉:微软MVP QQ:853066980
支付宝扫一扫,为大叔打赏!
来源:https://www.cnblogs.com/lori/p/19532862 |