Почему сервер ресурсов должен знать client_id в Spring OAuth2?

#spring-security #oauth-2.0

#spring-безопасность #oauth-2.0

Вопрос:

Я внедряю авторизацию OAuth2 с помощью Spring Boot. У меня уже есть сервер авторизации и сервер ресурсов, теперь я хочу получить доступ к ресурсам с сервера ресурсов, используя client_credentials тип предоставления.

Я немного смущен этим, потому что на сервере ресурсов я должен добавить client_id и client_secret . Но зачем серверу ресурсов это действительно нужно?

Насколько я понимаю эту концепцию, клиент должен получить от сервера авторизации, используя учетные данные клиента, свой токен доступа. А затем отправьте этот токен доступа на сервер ресурсов без каких-либо учетных данных клиента.

Итак, почему серверу ресурсов также нужны некоторые учетные данные клиента? Сервер ресурсов и клиент — это две отдельные сущности, я не понимаю, почему сервер ресурсов должен знать о client_id и client_secret .

Почему токена доступа недостаточно для аутентификации? check_token конечная точка может возвращать список ресурсов, к которым можно получить доступ с помощью этого токена, и если у клиента есть этот токен, это означает, что он уже аутентифицирован с учетными данными клиента для получения этого токена.

Что, если я хочу получить доступ от нескольких разных клиентов к этому серверу ресурсов?

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

 @Configuration
@RestController
@EnableWebSecurity
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(final HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/api/**").authenticated()
                .and()
            .httpBasic().disable();
    }

    @Override
    public void configure(ResourceServerSecurityConfigurer resources)  {
        resources
            .resourceId("translate-service");
    }
}
  

Свойства сервера ресурсов:

 security.oauth2.resource.user-info-uri=http://localhost:8090/user
security.oauth2.resource.token-info-uri=http://localhost:8090/oauth/check_token
security.oauth2.client.client-id=XXXX
security.oauth2.client.client-secret=XXXX
  

Если я не буду устанавливать свойства клиента, Spring выдаст предупреждение:

Обнаружен нулевой идентификатор клиента или секрет клиента. Конечная точка, требующая аутентификации, отклонит запрос с ошибкой 401.

И аутентификация не будет работать.

Может быть, я делаю что-то не так, и есть какое-то решение не предоставлять client_id на сервере ресурсов?

Ответ №1:

Если вы используете, RemoteTokenServices ваш сервер ресурсов также является дополнительным клиентом сервера авторизации, см. Руководство для разработчиков OAuth 2:

Альтернативой является, RemoteTokenServices которая представляет собой функции Spring OAuth (не входящие в спецификацию), позволяющие серверам ресурсов декодировать токены через HTTP-ресурс на сервере авторизации ( /oauth/check_token ). RemoteTokenServices удобны, если на серверах ресурсов нет большого объема трафика (каждый запрос должен быть проверен сервером авторизации), или если вы можете позволить себе кэшировать результаты. Чтобы использовать /oauth/check_token конечную точку, вам нужно предоставить ее, изменив ее правило доступа (по умолчанию «denyAll()») в AuthorizationServerSecurityConfigurer , например

 @Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
    oauthServer.tokenKeyAccess("isAnonymous() || hasAuthority('ROLE_TRUSTED_CLIENT')").checkTokenAccess(
        "hasAuthority('ROLE_TRUSTED_CLIENT')");
}
  

В этом примере мы настраиваем как /oauth/check_token конечную точку, так и конечную точку /oauth/token_key (чтобы доверенные ресурсы могли получить открытый ключ для проверки JWT). Эти две конечные точки защищены базовой аутентификацией HTTP с использованием учетных данных клиента.

и загрузка OAuth2:

2.4 Как настроить конечную точку информации о токене

Конечная точка информации о токене, также иногда называемая конечной точкой самоанализа, вероятно, требует какой-либо аутентификации клиента, либо базовой, либо на предъявителя. Вообще говоря, токена-носителя в SecurityContext недостаточно, поскольку он привязан к пользователю. Вместо этого вам нужно будет указать учетные данные, которые представляют этого клиента, например:

 spring:
  security:
    oauth2:
      client:
        clientId: client-id
        clientSecret: client-secret
      resource:
        tokenInfoUri: https://issuer/oauth2/check_token
  

По умолчанию для аутентификации в конечной точке token info будет использоваться базовая аутентификация с использованием настроенных учетных данных.