在 Spring 资源服务器中采用来自 JWT 的权限
Adopt authorities from JWT in Spring Resource Server
我的 Spring OAuth2 客户端仅向经过身份验证的用户授予 ROLE_USER 权限,而忽略提供的 JWT 中来自 resource_access
的权限。
{
"wdb": {
"roles": [
"TestRole",
"TestRoleFoo",
"TestRoleBar"
]
}
我如何设置我的 OAuth2 客户端以同时授予来自 resource_access
的权限(TestRole、TestRoleFoo、测试角色栏)?我在这里缺少一些关键配置吗?
我的详细配置
在我的资源服务器上,我使用 Spring 的默认 OAuth2 客户端,配置如下:
security:
oauth2:
client:
client-id: wdb
client-secret: some-secret
access-token-uri: http://localhost:8080/auth/realms/master/protocol/openid-connect/token
user-authorization-uri: http://localhost:8080/auth/realms/master/protocol/openid-connect/auth
scope: openid profile email
authorized-grant-types: code
resource:
user-info-uri: http://localhost:8080/auth/realms/master/protocol/openid-connect/userinfo
我的 Keycloak 授权服务器为我提供了以下 JWT 负载:
{
"jti": "6a666808-2b69-4de0-ab94-9ceebdac13de",
"exp": 1569674641,
"nbf": 0,
"iat": 1569674341,
"iss": "http://localhost:8080/auth/realms/master",
"aud": "account",
"sub": "f19b0443-4cce-495a-8479-ff36f82628fc",
"typ": "Bearer",
"azp": "wdb",
"auth_time": 1569674341,
"session_state": "0a411eda-0efb-4f29-99c4-b54da6298d6c",
"acr": "1",
"allowed-origins": [
"/*"
],
"realm_access": {
"roles": [
"offline_access",
"uma_authorization"
]
},
"resource_access": {
"wdb": {
"roles": [
"TestRole",
"TestRoleFoo",
"TestRoleBar"
]
},
"account": {
"roles": [
"manage-account",
"manage-account-links",
"view-profile"
]
}
},
"scope": "openid profile email",
"email_verified": true,
"user_name": "sullrich",
"name": "Sebastian Ullrich",
"preferred_username": "sullrich",
"given_name": "Sebastian",
"locale": "de",
"family_name": "Ullrich",
"email": "sebastian@wdb.local"
}
在我的资源服务器中,此 JWT 将派生到以下 OAuth2Authentication
:
{
"authorities":[
{
"authority":"ROLE_USER"
}
],
"details":{
"remoteAddress":"0:0:0:0:0:0:0:1",
"sessionId":"... session id ...",
"tokenValue":"... encoded payload ...",
"tokenType":"bearer"
},
"authenticated":true,
"userAuthentication":{
"authorities":[
{
"authority":"ROLE_USER"
}
],
"details":{
"sub":"f19b0443-4cce-495a-8479-ff36f82628fc",
"email_verified":true,
"user_name":"sullrich",
"name":"Sebastian Ullrich",
"preferred_username":"sullrich",
"given_name":"Sebastian",
"locale":"de",
"family_name":"Ullrich",
"email":"sebastian@wdb.local"
},
"authenticated":true,
"principal":"Sebastian Ullrich",
"credentials":"N/A",
"name":"Sebastian Ullrich"
},
"principal":"Sebastian Ullrich",
"credentials":"",
"clientOnly":false,
"oauth2Request":{
"clientId":"wdb",
"scope":[
],
"requestParameters":{
},
"resourceIds":[
],
"authorities":[
],
"approved":true,
"refresh":false,
"responseTypes":[
],
"extensions":{
}
},
"name":"Sebastian Ullrich"
}
听起来你需要一个自定义的 JwtAuthenticationConverter
Spring 默认情况下只会将范围映射到授予的权限。
您可以创建一个 class 来扩展默认实现并覆盖 extractAuthorities 方法。
然后您就可以访问声明,并且可以将它们映射到您想要的角色。
public class JwtGrantedAuthoritiesConverter extends JwtAuthenticationConverter {
@Override
protected Collection<GrantedAuthority> extractAuthorities(Jwt jwt) {
Collection<GrantedAuthority> authorities = super.extractAuthorities(jwt);
if(jwt.containsClaim("roles") && jwt.getClaimAsStringList("roles").contains("TestRole")) {
authorities.add(new SimpleGrantedAuthority("ROLE_TestRole"));
} else {
.........
}
return authorities;
}
然后将您的版本插入 WebSecurityConfigurationAdapter 中的资源服务器:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.
......
.oauth2ResourceServer()
.jwt()
.jwtAuthenticationConverter(new JwtGrantedAuthoritiesConverter());
你的角色有点嵌套,即在 resource_access 之下。世界数据库
您始终可以创建一个 keycloak 映射器以将它们添加到父节点中的角色下以简化操作。
这是一个资源服务器的例子,它做类似的事情
https://github.com/wlesniak/effective-oauth2-with-spring-security-and-spring-boot/tree/master/module_8/mod8_support-service
我的 Spring OAuth2 客户端仅向经过身份验证的用户授予 ROLE_USER 权限,而忽略提供的 JWT 中来自 resource_access
的权限。
{
"wdb": {
"roles": [
"TestRole",
"TestRoleFoo",
"TestRoleBar"
]
}
我如何设置我的 OAuth2 客户端以同时授予来自 resource_access
的权限(TestRole、TestRoleFoo、测试角色栏)?我在这里缺少一些关键配置吗?
我的详细配置
在我的资源服务器上,我使用 Spring 的默认 OAuth2 客户端,配置如下:
security:
oauth2:
client:
client-id: wdb
client-secret: some-secret
access-token-uri: http://localhost:8080/auth/realms/master/protocol/openid-connect/token
user-authorization-uri: http://localhost:8080/auth/realms/master/protocol/openid-connect/auth
scope: openid profile email
authorized-grant-types: code
resource:
user-info-uri: http://localhost:8080/auth/realms/master/protocol/openid-connect/userinfo
我的 Keycloak 授权服务器为我提供了以下 JWT 负载:
{
"jti": "6a666808-2b69-4de0-ab94-9ceebdac13de",
"exp": 1569674641,
"nbf": 0,
"iat": 1569674341,
"iss": "http://localhost:8080/auth/realms/master",
"aud": "account",
"sub": "f19b0443-4cce-495a-8479-ff36f82628fc",
"typ": "Bearer",
"azp": "wdb",
"auth_time": 1569674341,
"session_state": "0a411eda-0efb-4f29-99c4-b54da6298d6c",
"acr": "1",
"allowed-origins": [
"/*"
],
"realm_access": {
"roles": [
"offline_access",
"uma_authorization"
]
},
"resource_access": {
"wdb": {
"roles": [
"TestRole",
"TestRoleFoo",
"TestRoleBar"
]
},
"account": {
"roles": [
"manage-account",
"manage-account-links",
"view-profile"
]
}
},
"scope": "openid profile email",
"email_verified": true,
"user_name": "sullrich",
"name": "Sebastian Ullrich",
"preferred_username": "sullrich",
"given_name": "Sebastian",
"locale": "de",
"family_name": "Ullrich",
"email": "sebastian@wdb.local"
}
在我的资源服务器中,此 JWT 将派生到以下 OAuth2Authentication
:
{
"authorities":[
{
"authority":"ROLE_USER"
}
],
"details":{
"remoteAddress":"0:0:0:0:0:0:0:1",
"sessionId":"... session id ...",
"tokenValue":"... encoded payload ...",
"tokenType":"bearer"
},
"authenticated":true,
"userAuthentication":{
"authorities":[
{
"authority":"ROLE_USER"
}
],
"details":{
"sub":"f19b0443-4cce-495a-8479-ff36f82628fc",
"email_verified":true,
"user_name":"sullrich",
"name":"Sebastian Ullrich",
"preferred_username":"sullrich",
"given_name":"Sebastian",
"locale":"de",
"family_name":"Ullrich",
"email":"sebastian@wdb.local"
},
"authenticated":true,
"principal":"Sebastian Ullrich",
"credentials":"N/A",
"name":"Sebastian Ullrich"
},
"principal":"Sebastian Ullrich",
"credentials":"",
"clientOnly":false,
"oauth2Request":{
"clientId":"wdb",
"scope":[
],
"requestParameters":{
},
"resourceIds":[
],
"authorities":[
],
"approved":true,
"refresh":false,
"responseTypes":[
],
"extensions":{
}
},
"name":"Sebastian Ullrich"
}
听起来你需要一个自定义的 JwtAuthenticationConverter Spring 默认情况下只会将范围映射到授予的权限。
您可以创建一个 class 来扩展默认实现并覆盖 extractAuthorities 方法。 然后您就可以访问声明,并且可以将它们映射到您想要的角色。
public class JwtGrantedAuthoritiesConverter extends JwtAuthenticationConverter {
@Override
protected Collection<GrantedAuthority> extractAuthorities(Jwt jwt) {
Collection<GrantedAuthority> authorities = super.extractAuthorities(jwt);
if(jwt.containsClaim("roles") && jwt.getClaimAsStringList("roles").contains("TestRole")) {
authorities.add(new SimpleGrantedAuthority("ROLE_TestRole"));
} else {
.........
}
return authorities;
}
然后将您的版本插入 WebSecurityConfigurationAdapter 中的资源服务器:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.
......
.oauth2ResourceServer()
.jwt()
.jwtAuthenticationConverter(new JwtGrantedAuthoritiesConverter());
你的角色有点嵌套,即在 resource_access 之下。世界数据库 您始终可以创建一个 keycloak 映射器以将它们添加到父节点中的角色下以简化操作。
这是一个资源服务器的例子,它做类似的事情 https://github.com/wlesniak/effective-oauth2-with-spring-security-and-spring-boot/tree/master/module_8/mod8_support-service