Неверный JWToken: ребенок - обязательный заголовок JOSE - PullRequest
2 голосов
/ 13 апреля 2019

Я пытаюсь внедрить сервер авторизации Oauth2 с SpringBoot, используя это руководство в качестве ссылки.

В моем хранилище ключей есть один ключ.Мне удалось создать JWToken (я могу проверить его на jwt.io).

У меня также есть тестовый сервер ресурсов.Когда я пытаюсь получить доступ к любой конечной точке, я получаю следующее сообщение:

{
  "error": "invalid_token",
  "error_description": "Invalid JWT/JWS: kid is a required JOSE Header"
}

У токена действительно нет заголовка ребенка, но я не могу понять, как его добавить.Я могу только добавить данные в его полезную нагрузку, используя TokenEnchancer.Также кажется, что я не первый с этой проблемой .

Есть ли способ добавить этот заголовок или, по крайней мере, игнорировать его на сервере ресурсов?

Ответы [ 2 ]

1 голос
/ 07 июля 2019

Я работаю над статьей, которая может вам помочь: https://www.baeldung.com/spring-security-oauth2-jws-jwk

Итак, чтобы настроить сервер авторизации Spring Security OAuth для добавления заголовка JWT kid ,вы можете выполнить шаги раздела 4.9:

  1. создать новый класс, расширяющий JwtAccessTokenConverter
  2. В конструкторе:
    1. настроить родительский элементкласс, используя тот же подход, который вы использовали
    2. получить объект Signer , используя ключ подписи, который вы используете
  3. переопределить метод кодирования,Реализация будет такой же, как родительская, с той лишь разницей, что вы также будете передавать пользовательские заголовки при создании токена String
public class JwtCustomHeadersAccessTokenConverter extends JwtAccessTokenConverter {

    private JsonParser objectMapper = JsonParserFactory.create();
    final RsaSigner signer;

    public JwtCustomHeadersAccessTokenConverter(KeyPair keyPair) {
        super();
        super.setKeyPair(keyPair);
        this.signer = new RsaSigner((RSAPrivateKey) keyPair.getPrivate());
    }

    @Override
    protected String encode(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
        String content;
        try {
            content = this.objectMapper.formatMap(getAccessTokenConverter().convertAccessToken(accessToken, authentication));
        } catch (Exception ex) {
            throw new IllegalStateException("Cannot convert access token to JSON", ex);
        }
        Map<String, String> customHeaders = Collections.singletonMap("kid", "my_kid");
        String token = JwtHelper.encode(content, this.signer, this.customHeaders)
            .getEncoded();
        return token;
    }
}
  1. Затем, конечно, создайтеbean-компонент, использующий этот конвертер:
@Bean
public JwtAccessTokenConverter accessTokenConverter(KeyPair keyPair) {
    return new JwtCustomHeadersAccessTokenConverter(keyPair);
}

Здесь я использовал экземпляр KeyPair для получения ключа подписи и настройки конвертера (на основе примера из статьи), но вы можете адаптировать его к своемуконфигурации.

В этой статье я также объясняю соответствующие конечные точки, предоставляемые сервером аутентификации OAuth Spring Security.

Кроме того, что касается комментария @Ortomala Lokni, я не ожидаю, что Spring Security OAuth добавитлюбые новые функции на данный момент.В качестве альтернативы вы можете подождать, чтобы взглянуть на функции сервера авторизации Spring Security, которые планируется выпустить в 5.3.0

1 голос
/ 15 апреля 2019

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

В файле application.properties вместо:

security.oauth2.resource.jwk.key-set-uri=http://{auth_server}/.well-known/jwks.json

Я использовал:

security.oauth2.resource.jwt.key-uri=http://{auth_server}/oauth/token_key

Если я правильно понял, конфигурация key-set-uri указывает на конечную точку, которая представляет набор ключей, и в этом нуждается ребенок. С другой стороны key-uri config указывает на конечную точку одним ключом.

...