英文:
Keycloak: how to set and restrict scopes of resource server per user
问题
我正在开发一个Spring Boot 3和Spring Security 6的应用程序。该应用程序是一个REST API。我将使用Spring Security和Spring Security资源服务器进行授权。端点将使用@PreAuthorize("hasAuthority('SCOPE_scope-name')")
进行注释以限制访问。我想要使用OIDC和JWT。
我将使用Keycloak作为授权服务器。现在,我想要限制特定用户组对资源/ API的访问。假设我有用户a、b、c和x、y。用户a、b、c将具有对read:test
和write:test
范围的访问权限。但是用户x、y只能访问read:test
范围。即使用户x、y请求write:test
范围,Keycloak也不会授予这些用户该范围。
最好的情况是,我想使用用户组来轻松管理用户。最好创建一些角色并分配给用户组。每个角色将具有一组允许访问的范围。我尝试阅读文档,但对我来说很困惑。范围和角色位于不同的位置。我不明白如何实现我想要做的事情。
根据Spring Security文档,在application.properties
文件中,我只需要设置spring.security.oauth2.resourceserver.jwt.issuer-uri
。我不明白Keycloak/Spring应用程序如何仅通过issuer-uri设置知道这是哪个客户端/资源服务器。
在Keycloak中,我如何设置和管理资源服务器的API端点的范围,并限制每个用户的范围?
英文:
I am developing a spring boot 3 and spring security 6 application. The application is rest api. I will use spring security, spring security resource sever for authorization. Endpoint will be annotated with @PreAuthorize("hasAuthority('SCOPE_scope-name')")
to restrict access to it. I want to use OIDC, JWT.
I will use keycloak as the authorization server. Now, I want to restrict access to resources/api for specific user groups. Suppose I have user a,b,c and x,y. User a,b,c will have access to scopes read:test
and write:test
. But users x,y will only have access to scope read:test. Even if user x,y asks for the write:test
scope, keycloak will not give the scope to these users.
Preferably I want to use user groups to easily manage the users. Preferably some roles will be created and assigned to user groups. Each role will have some set of scopes that the role will allow access to. I tried reading the documentation. It was confusing to me. There are scopes and roles in different places. I did not understand how can I achieve what I want to do.
According to spring security documentation, In the application.properties
file I just have to set spring.security.oauth2.resourceserver.jwt.issuer-uri
. I do not understand how keycloak/spring application will know which client/resource server is this application from just the issuer-uri settings.
In keycloak, how do I set, manage scopes for API endpoint for a resource server, and restrict those scopes per user?
答案1
得分: 2
以下是翻译好的内容:
范围不是角色
您可能会看到:
- 角色是用户被允许执行的操作
- 范围是客户端代表用户被允许执行的操作
OAuth2规范定义了范围,但与角色、组、权限、授权或用户访问表示无关。授权服务器供应商使用私有声明来处理这些。
默认情况下,Keycloak使用 realm_access.roles
和 resource_access.{client-ID}.roles
,但您可以定义自己的映射器来使用任何您喜欢的声明。
将Keycloak角色转换为Spring权限
由于OAuth2中没有角色的标准,Spring默认权限转换器使用范围声明作为源,并在每个条目前加上 SCOPE_
前缀。
这很少令人满意,您经常需要提供自己的权限转换器。
完整的工作示例
请参考我的教程。除了工作示例外,您还会找到一些您似乎缺少的OAuth2/OpenID背景信息。
英文:
Scopes Are Not Roles
You may see:
- roles as what a user is allowed to do
- scope as what a client is allowed to do on behalf of a user
Scope is defined the OAuth2 spec, but there is nothing about roles, groups, permissions, grants or whatever user access representation. Authorization servers vendors use private claims for that.
By default, Keycloak uses realm_access.roles
and resource_access.{client-ID}.roles
, but you may define your own mappers to use any claim you like.
Converting Keycloak Roles to Spring Authorities
As there is no standard for roles in OAuth2, Spring default authorities converter uses scope claim as source and prefixes each entry with SCOPE_
.
This is rarely satisfying and you frequently need to provide with your own authorities converter.
Complete Working Samples
Refer to my tutorials. In addition to working samples, you'll find some of the OAuth2 / OpenID background you seem to be missing.
答案2
得分: 1
Scopes are fixed at design time and do not provide a full authorization solution. When you want dynamic authorization per user, you must use claims instead. Arrange users into roles however you would like. In Keycloak, at the time of token issuance, include values such as these in tokens:
{
scope: orders,
role: customer,
access_level: read
}
More generally think of a scope representing a business area and being composed of claims. Look into Keycloak claims mappers for the vendor specific way to manage this.
USING CLAIMS
Your Spring resource server will then just receive such values in the authenticated principal, after validating the JWT access token. You can then use these values in the API's business authorization code.
Here is some example code of mine, to give you an idea of how claims can be injected then used for business authorization. Annotations may work to deny access in some cases. In others you will need to do things like filter collections to contain only authorized items.
英文:
Scopes are fixed at design time and do not provide a full authorization solution. When you want dynamic authorization per user, you must use claims instead. Arrange users into roles however you would like. In Keycloak, at the time of token issuance, include values such as these in tokens:
{
scope: orders,
role: customer,
access_level: read
}
More generally think of a scope representing a business area and being composed of claims. Look into Keycloak claims mappers for the vendor specific way to manage this.
USING CLAIMS
Your Spring resource server will then just receive such values in the authenticated principal, after validating the JWT access token. You can then use these values in the API's business authorization code.
Here is some example code of mine, to give you an idea of how claims can be injected then used for business authorization. Annotations may work to deny access in some cases. In others you will need to do things like filter collections to contain only authorized items.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论