Keycloak基于OpenID与OAuth2.0配置指定用户/组访问客户端
单Realm多Client场景下基于OIDC/OAuth2的指定Client访问控制配置
这个需求是企业级IdP部署的常规场景,完全基于OpenID Connect、OAuth 2.0标准协议就能实现,不需要做二次协议开发,按下面步骤配就行,所有兼容标准协议的授权服务器(Keycloak、IdentityServer这类主流实现逻辑通用):
前置配置
- 先把所有需要做访问控制的Client的授权模式从默认的「全用户可访问」改成受限模式:机密客户端(Confidential Client)必须开启Client Secret校验,公开客户端(Public Client,比如纯前端SPA)要关闭“直接授权”“隐式流”这类不安全的授权模式,避免被绕开权限校验。
- 提前在Realm内整理好用户和用户组,按访问需求给用户分好组,后续批量授权直接给组配就行,不用挨个给用户改权限,省很多事。
两种落地方案,按需选
方案1:授权服务器侧硬拦截(推荐,最安全,协议层直接生效)
这是最稳妥的方案,拦截逻辑在OAuth2授权端点触发,没权限的用户根本拿不到对应Client的令牌,从根源上避免越权:
- 给每个需要管控的Client创建Client级专属访问角色,比如面向内部运营系统的Client建
ops-console-access角色,面向C端用户的Client建end-user-access角色,角色一定要归属到对应Client名下,别建Realm全局角色,很容易出现权限串扰。 - 给对应Client配置访问策略:将Client的授权资格和刚才建的专属角色绑定,只有持有该角色的用户、用户组,才能发起针对这个Client的授权请求。用户跳转到IdP输完账号密码后,IdP会先做权限校验,没权限直接返回标准的
access_denied错误,走不到发授权码、发Access Token的流程,完全符合OIDC/OAuth2的协议规范。 - 给用户组批量授权:把每个Client的专属访问角色直接映射给对应有权限的用户组,组内用户自动继承角色权限,后续人员调整只要把用户拉进/移出对应组就行,维护成本极低。
方案2:资源服务侧软拦截(适合自定义需求多的场景)
如果不想在IdP层做硬拦截,可以基于令牌Claim做校验:
- 在IdP侧给每个Client配置专属的Client Scope,把用户的访问权限、所属组、拥有的Client角色注入到对应Client签发的ID Token、Access Token里,比如给运营系统Client发的令牌里带上
allowed_clients: ["ops-console"]的自定义Claim。 - 在Client对应的后端资源服务里加全局拦截器:所有接口请求进来先校验Access Token的签名合法性,解析令牌内容确认当前用户有该Client的访问权限,没有的话直接返回403。
注意:这个方案必须在资源服务侧做令牌签名校验,绝对不能信任前端传来的未校验的令牌内容,否则很容易被伪造Claim绕开权限。
配置校验步骤
配完一定要做这几个校验,避免留漏洞:
- 拿没有目标Client权限的测试账号走标准OIDC授权码流程登录,确认会被直接拦截,拿不到有效访问令牌。
- 拿有权限的账号测试,确认能正常走完授权流程,拿到的令牌里包含对应的权限标识,能正常访问Client下的资源。
- 做跨Client越权测试:用只有A Client权限的账号,尝试申请B Client的访问令牌,确认IdP返回
access_denied,没有权限串扰的问题。
常见踩坑
- 别用Realm全局角色做Client访问控制,全局角色默认会注入到所有Client签发的令牌里,很容易出现权限过度分配的问题。
- 如果开了Client的服务账号(Service Account)能力,记得单独给服务账号配置访问权限,别默认给服务账号全量Client的访问权。
- 公开Client一定要在IdP侧做硬拦截,公开Client没法安全存储Client Secret,光靠前端侧的权限校验等于没设防。
内容的提问来源于stack exchange,提问作者Mario Rovelli
相关产品推荐
相关产品推荐

