Расхождение в пользовательских ролях (полномочиях) в токене доступа, полученном из grant_type = password и grant_type = refresh_token - PullRequest
0 голосов
/ 29 августа 2018

У меня есть ситуация:

Шаг 1: Получен токен доступа (grant_type = пароль) (A1), а также токен обновления. (RT1)

Шаг 2: Доступ к ресурсу (R) с использованием токена (A1) - успех

Шаг 3. Отмененная роль доступа пользователя для ресурса R.

Шаг 4: Получен токен доступа (grant_type = пароль) (A2), а также токен обновления. (RT2)

Шаг 5: Доступ к ресурсу (R) с использованием токена (A2) - Сбой

пока здесь все прекрасно. Теперь приходит неожиданная часть.

Шаг 6: Получен новый токен доступа (grant_type = refresh_token) с использованием RT2. Неожиданно используя этот токен доступа, я смог получить доступ к ресурсу R.

Во время всего этого потока ни один из токенов не истек.

Я вижу здесь две проблемы: - Роли пользователей не обновляются для токена обновления на grant_type = password и grant_type = refresh_token. Хотя токен доступа изменился (шаг 4), но токен обновления остался прежним RT1 == RT2. следовательно, любое дальнейшее использование RT дает токен доступа с предыдущими ролями.

Как сообщить Spring (oauth2) обновлять роли пользователей (для вновь созданных токенов) при получении токена доступа с использованием токена обновления, а также при обновлении RT новыми ролями (шаг 4), чтобы устранить это несоответствие.

Ниже приведена конфигурация сервера авторизации:

 <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
       xmlns:security="http://www.springframework.org/schema/security"
       xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2.xsd
                           http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
                           http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


  <bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
    <property name="userDetailsService">
      <bean class="com.dummy.mc.security.service.UserDetailsServiceImpl">
        <property name="userRepository" ref="userRepository" />
        <property name="grantedAuthorityRepository" ref="grantedAuthorityRepository" />
      </bean>
    </property>
    <property name="passwordEncoder">
      <bean class="com.dummy.mc.security.password.McpmPasswordEncoder">
        <property name="encodeHashAsBase64" value="true" />
      </bean>
    </property>
    <property name="saltSource">
      <bean class="org.springframework.security.authentication.dao.ReflectionSaltSource">
        <property name="userPropertyToUse" value="salt" />
      </bean>
    </property>
  </bean>


    <!--https://stackoverflow.com/questions/49761597/spring-oauth2-clientid-passed-in-as-username-for-password-grant-type-->

    <bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.JdbcTokenStore">
        <constructor-arg ref="dataSource" />
    </bean>

    <bean id="tokenServices"
          class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
        <property name="tokenStore" ref="tokenStore" />
        <property name="supportRefreshToken" value="true" />
        <property name="clientDetailsService" ref="clientDetailsService" />
        <property name="reuseRefreshToken" value="false"/>

    </bean>

    <bean id="oauthAccessDeniedHandler"
          class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />

    <bean id="clientCredentialsTokenEndpointFilter"
          class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
        <property name="authenticationManager" ref="clientDetailAuthenticationManager" />
    </bean>



    <!-- Authentication manager for client (not resource-owner) authentication required to
        protect the token endpoint URL -->

    <security:authentication-manager id="clientDetailAuthenticationManager">
        <security:authentication-provider user-service-ref="clientDetailsUserService"/>
    </security:authentication-manager>

    <bean id="clientDetailsUserService" class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
        <constructor-arg ref="clientDetailsService"/>
    </bean>

    <bean id="clientAuthenticationEntryPoint"
          class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
        <property name="realmName" value="test/client" />
        <property name="typeName" value="Basic" />
    </bean>

    <security:http pattern="/oauth/token" create-session="stateless" use-expressions="true" authentication-manager-ref="authenticationManager">
        <security:intercept-url pattern="/oauth/token" access="isAuthenticated()" />
        <security:anonymous enabled="false" />
        <security:http-basic entry-point-ref="clientAuthenticationEntryPoint" />
        <!-- include this only if you need to authenticate clients via request
            parameters -->
        <security:custom-filter ref="clientCredentialsTokenEndpointFilter"
                                after="BASIC_AUTH_FILTER" />
        <security:access-denied-handler ref="oauthAccessDeniedHandler" />
    </security:http>

    <authorization-server client-details-service-ref="clientDetailsService"
                          xmlns="http://www.springframework.org/schema/security/oauth2" token-services-ref="tokenServices" >
        <authorization-code />
        <implicit />
        <refresh-token />
        <client-credentials />
        <password authentication-manager-ref="authenticationManager" />
    </authorization-server>

    <!-- <oauth:resource-server id="resourceFilter" token-services-ref="tokenServices" authentication-manager-ref="authenticationManager" />
 -->
    <security:authentication-manager id="authenticationManager">
        <security:authentication-provider ref="daoAuthenticationProvider">
        </security:authentication-provider>
    </security:authentication-manager>

    <oauth:client-details-service id="clientDetailsService">

        <oauth:client client-id="core-api" secret="secret"
                      authorized-grant-types="password,client_credentials,refresh_token" scope="read"
                      resource-ids="api-core" access-token-validity="36000"
                      authorities="ROLE_CLIENT,ROLE_TRUSTED_CLIENT" />
    </oauth:client-details-service>
</beans>

Конфигурация сервера ресурсов:

 <mvc:default-servlet-handler />

    <mvc:annotation-driven/>
    <security:global-method-security pre-post-annotations="enabled"/>

    <!-- TODO: make an access denied view that tells me something useful -->
    <security:http  use-expressions="true"  entry-point-ref="oauthAuthenticationEntryPoint">
        <security:intercept-url pattern="/**" access="isFullyAuthenticated() and hasRole('api.core')" />
        <security:custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
        <security:access-denied-handler ref="oauthAccessDeniedHandler" />

        <security:anonymous />
    </security:http>


    <!-- It's just a "feature" of the Spring Security that an authentication manager is mandatory.
        so install an empty one because it isn't used at run time -->
    <security:authentication-manager/>



    <oauth:resource-server id="resourceServerFilter"  token-services-ref="tokenServices" resource-id="api-core"/>


    <bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices" >
        <property name="tokenStore" ref="tokenStore" />
    </bean>


    <bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.JdbcTokenStore">
        <constructor-arg ref="dataSource" />
    </bean>

    <bean id="oauthAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
        <property name="realmName" value="test/client" />
        <property name="typeName" value="Basic" />
    </bean>


    <bean id="oauthAccessDeniedHandler" class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />

1 Ответ

0 голосов
/ 18 января 2019

Полномочия загружаются, когда требуется токен доступа. Используя хранилище jdbc, полномочия сохраняются в таблицу OAUTH_ACCESS_TOKEN, столбец AUTHENTICATION.

Когда требуется обновить токен, права доступа загружаются из базы данных.

Если полномочия изменились после того, как токен доступа потребовался, вам придется реализовать собственное хранилище токенов.

Взгляните на org.springframework.security.oauth2.provider.token.store.JdbcTokenStore и пройдите от него.

...