Keycloak-gatekeeper: претензии 'aud' и 'client_id' не совпадают

Как правильно установить aud претензия, чтобы избежать ошибки ниже?

unable to verify the id token   {"error": "oidc: JWT claims invalid: invalid claims, 'aud' claim and 'client_id' do not match, aud=account, client_id=webapp"}

Я вроде работал над этим сообщением об ошибке жестким кодированием aud претендовать на то же самое, что и мой client_id, Есть ли лучший способ?

Вот мой docker-compose.yml:

version: '3'
services:
  keycloak-proxy:
    image: "keycloak/keycloak-gatekeeper"
    environment:
     - PROXY_LISTEN=0.0.0.0:3000
     - PROXY_DISCOVERY_URL=http://keycloak.example.com:8181/auth/realms/realmcom
     - PROXY_CLIENT_ID=webapp
     - PROXY_CLIENT_SECRET=0b57186c-e939-48ff-aa17-cfd3e361f65e
     - PROXY_UPSTREAM_URL=http://test-server:8000
    ports:
      - "8282:3000"
    command:
      - "--verbose"
      - "--enable-refresh-tokens=true"
      - "--enable-default-deny=true"
      - "--resources=uri=/*"
      - "--enable-session-cookies=true"
      - "--encryption-key=AgXa7xRcoClDEU0ZDSH4X0XhL5Qy2Z2j"
  test-server:
    image: "test-server"

4 ответа

В последней версии keycloak 4.6.0 идентификатор клиента, по-видимому, больше не добавляется автоматически в поле аудитории "aud" токена доступа. Поэтому, даже если вход в систему успешен, клиент отклоняет пользователя. Чтобы это исправить, вам нужно настроить аудиторию для ваших клиентов (сравните документ [2]).

Настроить аудиторию в Keycloak

  • Добавить область или настроить существующую
  • Добавить клиентское приложение или использовать существующее
  • Перейти к недавно добавленному меню "Области клиента" [1]
    • Добавить клиентскую область "хороший сервис"
    • В настройках "хорошего сервиса" перейдите на вкладку Mappers
      • Создание протокола Mapper 'my-app-аудитория'
        • Имя: my-app-аудитория
        • Выберите тип картографа: аудитория
        • Клиентская аудитория: my-app
        • Добавить к токену доступа: вкл
  • Настройте клиентское приложение my-app в меню "Клиенты"
    • Вкладка Области клиента в настройках моего приложения
    • Добавить доступные клиентские области "good-service" в назначенные клиентские области по умолчанию

Если у вас более одного клиента, повторите действия для других клиентов и добавьте область хорошего обслуживания. Целью этого является изоляция клиентского доступа. Выданный токен доступа будет действителен только для целевой аудитории. Это подробно описано в документации Keycloak [1,2].

Ссылки на последнюю версию документации кей-клока:

Ссылки с тегом git:

This is due to a bug: https://issues.jboss.org/browse/KEYCLOAK-8954

There are two workarounds described in the bug report, both of which appear to do basically the same thing as the accepted answer here but can be applied to the Client Scope role, so you don't have to apply them to every client individually.

Если, как и я, вы хотите автоматизировать конфигурацию keycloak, вы можете использовать kcadm

/opt/jboss/keycloak/bin/kcadm.sh \
        создать клиентов / d3170ee6-7778-413b-8f41-31479bdb2166 / protocol-mappers / models -r your-realm \
        -s имя = отображение аудитории \
        -s протокол = openid-connect \
        -s protocolMapper = oidc-аудитория-картограф \
        -s config. \ "included.client.audience \" = "ваша-аудитория" \
        -s config. \ "access.token.claim \" = "true" \
        -s config. \ "id.token.claim \" = "false"

Это работает для меня:

В моем классе SecurityConfiguration:

      @Bean
public CorsConfigurationSource corsConfigurationSource() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        
        config.setAllowCredentials(true);
        config.setAllowedOrigins(Arrays.asList("http://localhost:3000"));
        config.setAllowedMethods(Arrays.asList(CorsConfiguration.ALL));
        config.setAllowedHeaders(Arrays.asList(CorsConfiguration.ALL));
        config.setAllowCredentials(true);
        source.registerCorsConfiguration("/**", config);
        
        return source;
    }
Другие вопросы по тегам