ekapusta / oauth2-esia

Authenticate in ESIA and get authenticated individual personal information
MIT License
67 stars 48 forks source link

Ошибка при попытке использования ключей ГОСТ 2012 #15

Closed plutonio00 closed 3 years ago

plutonio00 commented 3 years ago

Добрый день. После обновления этого пакета до последней версии (1.4.1) у меня ошибка с валидацией токена все так же появляется (скрин с ошибкой прикладываю)

Что я пытаюсь делать:

use Ekapusta\OAuth2Esia\Provider\EsiaProvider;
use Ekapusta\OAuth2Esia\Security\JWTSigner\OpenSslCliJwtSigner;
use Ekapusta\OAuth2Esia\Security\Signer\OpensslPkcs7;

...

//настройки для провайдера
 $providerSettings = [
            'clientId' => $esiaParams['client_id'],
            'redirectUri' => $esiaParams[YII_ENV]['redirect_uri'],
            'defaultScopes' => $esiaParams['scopes'],
            'remoteCertificatePath' => $esiaParams[YII_ENV]['check_token_key_path'],
];

 $this->provider = new EsiaProvider(
            $providerSettings,
            [
                'signer' => new OpensslPkcs7(
                    $esiaParams['open_key_path'], //путь до секретного ключа
                    $esiaParams['secret_key_path'], //путь до открытого ключа
                    $esiaParams['secret_key_password'], //пароль от секретного ключа
                ),
                'remoteSinger' => new OpenSslCliJwtSigner('openssl'),
            ]
        );

К ключам претензий нет, т.к. авторизация проходит без проблем. Проблемы только с валидацией токена. Соответственно, если отключить в классе vendor/ekapusta/oauth2-esia/src/Token/EsiaAccessToken.php вторую проверку, то все работает отлично. Вот проверка:

if ($publicKeyPath && !$this->parsedToken->verify($signer, new Key(file_get_contents($publicKeyPath)))) {
            throw new InvalidArgumentException('Access token can not be verified: '.var_export($options, true));
}

Что я делаю не так?

Screenshot (67)

plutonio00 commented 3 years ago

Сегодня стал смотреть более детально что нет так. Выяснилось что проблемы начинаются в классе vendor/lcobucci/jwt/src/Token.php

 public function verify(Signer $signer, $key)
    {
        if ($this->headers->get('alg') !== $signer->getAlgorithmId()) {
            return false;
        }

        return $this->signature->verify($signer, $this->getPayload(), $key);
    }

Оказывается, $signer->getAlgorithmId() отдает значение RS256, тогда как $this->headers->get('alg') - GOST3410_2012_256 В общем $singer как-то на ГОСТ не перешел. С чем это может быть связано?

garex commented 3 years ago

Внимательно разберитесь с настройками и какие классы вы используете.

У вас явно у системы проверка токена идёт через ГОСТ -- вот гостовый сигнер ей и дайте.

plutonio00 commented 3 years ago

Проблема в том, что по каким-то причинам в классе vendor/ekapusta/oauth2-esia/src/Provider/EsiaProvider.php в конструкторе не выполняется условие

if (isset($collaborators['remoteSigner']) && $collaborators['remoteSigner'] instanceof Signer) {
            $this->remoteSigner = $collaborators['remoteSigner'];
}

Хотя я передаю remoteSinger. Не понимаю пока в чем дело. Для эксперимента захардкодил remoteSinger в вышеуказанном конструкторе. $this->remoteSigner = new OpenSslCliJwtSigner('openssl'); Получаю дальше ошибку: Operation failed with code#1 as of: engine "gost" set.

in /var/www/esia-service/vendor/ekapusta/oauth2-esia/src/Transport/Process.php

if (0 != $code) {
            throw new RuntimeException("Operation failed with code#$code as of: $stderr");
}

А это с чем связано? Если закомментировать этот кусок кода - то все работает