Принять полномочия из JWT в Spring Resource Server - PullRequest
0 голосов
/ 28 сентября 2019

Клиент My Spring OAuth2 предоставляет полномочия ROLE_USER только аутентифицированным пользователям, игнорируя полномочия resource_access в предоставленном JWT.

{
"wdb": {
  "roles": [
    "TestRole",
    "TestRoleFoo",
    "TestRoleBar"
  ]
}

Как настроить мой клиент OAuth2, чтобы он также предоставил полномочия от resource_access ( TestRole , TestRoleFoo , TestRoleBar )?Мне не хватает какой-то важной конфигурации здесь?

Подробно о моей конфигурации

На моем сервере ресурсов я использую OAuth2-клиент Springs по умолчанию со следующей конфигурацией:

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"
}

1 Ответ

0 голосов
/ 30 сентября 2019

Похоже, вам нужен пользовательский JwtAuthenticationConverter Spring по умолчанию будет сопоставлять только области с предоставленными полномочиями.

Вы можете создать класс, который расширяет реализацию по умолчанию и переопределяет метод 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; 
    } 

Затем вы подключаете свою версию к серверу ресурсов в вашем адаптере WebSecurityConfiguration:

@Override 
    protected void configure(HttpSecurity http) throws Exception { 
        http.
......
            .oauth2ResourceServer() 
                .jwt() 
                    .jwtAuthenticationConverter(new JwtGrantedAuthoritiesConverter());


Ваши роли немного больше вложены, то есть под resource_access.wdb Вы всегда можете создать маппер Keycloak, чтобы добавить их в роли в родительском узле, чтобы упростить вещи.

Вот пример сервера ресурсов, который делает нечто подобное https://github.com/wlesniak/effective-oauth2-with-spring-security-and-spring-boot/tree/master/module_8/mod8_support-service

...