管理keycloak和spring rest api中的用户权限

时间:2018-06-04 00:16:58

标签: spring rest spring-security keycloak oidc

  

TL; DR

     
      
  • 目标:管理api权限:      
        
    • OIDC授权直接授权流程
    •   
    • 用户联合和身份验证来源:LDAP
    •   
    • 权限存储:遗留数据库
    •   
    • 客户端管理和身份验证:Keycloak
    •   
  •   
  • 问题:管理Keycloak和rest api的用户权限的最佳做法是什么?
  •   

上下文

我们正在实施一个带有spring的rest API,供移动应用程序和SPA使用。我们的用户帐户,权限,规则......和所有数据都存储在不同整体应用程序使用的自定义数据库中。为了保护我们的api,我们决定使用Keycloak。

keycloak服务器配置了用于用户联合的现有LDAP和用于移动客户端应用程序的“Direct grand flow”。对于第一个用例(身份验证),一切正常。

现在我们必须管理用户权限,如下所示:

  • 客户端应用程序应该知道显示/隐藏功能的用户权限

  • api应该能够验证用户使用不同端点的权限

  • 用户权限基于数据库中的某些规则并经常更改

在我的理解中,keycloak可以使用硬编码或基于用户的策略处理授权和细粒度权限,但不能本机插入其他授权源。因此,我考虑使用 Keycloak SPI 构建自定义角色映射器,从我将开发的自定义API中检索用户权限,然后将它们映射到访问令牌。

因此,我的访问令牌应如下所示:

"resource_access": {
    “My-client”: {
      “permissions”: [
        “Show-products”,
        “Buy-something”,
        “Display-prices”
      ]
    }
  },
  "username": “myUser”

然后移动应用程序应该能够基于令牌了解用户权限,并且我的无状态服务器端(API)应该能够在每次调用时访问用户权限以使用spring注释检查它们:

@PreAuthorize("hasRole('Show-products')")

问题

在第一次尝试我的解决方案之后似乎工作正常,但我仍然对这个选择有一些安全问题,因为它超出了keycloak标准,并且包括对keycloak映射器内的不同后端的休息调用。

所以我想知道:

  • 将用户权限置于访问令牌声明中是否安全?
  • 如何保护对外部系统的密钥泄露访问(休息呼叫) 检索权限?
  • 我是否应该依赖令牌声明来验证每个声明的用户权限 在我的资源服务器中请求?
  • 是否有其他干净的解决方案/最佳做法来处理用户 keycloak中来自外部来源的权限?

免费信息

我正在使用:

  • Springboot 1.5.13.RELEASE
  • Keycloak-adapter-bom 3.4.3.Final
  • 独立keycloak服务器3.4.3.Final

1 个答案:

答案 0 :(得分:0)

关于您的问题:

-将用户权限放在访问令牌声明上是否安全?

是的,功能可以(并且应该)位于访问令牌上,并因此可以在业务层中进行一些分配(基于角色/访问声明)。还请记住,访问令牌不与任何前端共享,因此这也是一个秘密。

如何保护对外部系统(其余呼叫)的密钥库访问以获取权限?

这取决于是否需要从网络外部访问它。如果没有,您可以使其不受保护(并且不受外界的干扰/或仅适用于某些特定IP)。如果要从外部使用它,或者无论如何要使用密钥克隆保护它,则可以使用“机密”或“仅承载”类型的客户端。我建议您研究CORS和令牌共享,以便可以将已创建的“访问令牌”重新用于其他端点,而无需再次进行身份验证。

我应该依靠令牌声明来验证资源服务器中每个请求的用户权限吗?

不确定您的意思。在keycloak中,资源服务器不会像在典型的oAuth2舞中那样做额外的资源授权(除非激活了策略执行器,但我相信您没有采用这种方法,而是使用映射器SPI @auth服务器来正确设置角色?)

在oAuth2中,“资源服务器”具有2个职责:1提供资源和2执行额外的授权步骤。在密钥斗篷世界中,这两个步骤是由不同的角色完成的。步骤1是由您的应用程序完成的,而步骤2仅在还通过keycloak激活了策略强制时才完成(从oAuth2的角度来看,Keycloak是身份验证服务器,并且也是“资源服务器”的一部分)

现在回到您的问题,如果是由资源服务器代表您的应用程序提供了内容,那么是的,您可以在其中使用声明,请记住声明(以及整个访问令牌)是由数字签名和生成的身份验证服务器,因此您可以毫无问题地在应用程序中使用这些声明(否则也不知道如何做)。

是否有其他干净的解决方案/最佳实践来处理来自密钥库中外部源的用户权限?

您可能已经注意到,很难说;特定用例的网络文档非常有限;因此,在那里没有大量的最佳实践工作,您唯一真正的选择就是使用带有自定义策略SPI的策略,这还会带来其他挑战。我想你的解决方案很好。

最诚挚的问候。