Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Проблема с получением refresh_token #5

Open
hardworm opened this issue May 22, 2020 · 13 comments
Open

Проблема с получением refresh_token #5

hardworm opened this issue May 22, 2020 · 13 comments

Comments

@hardworm
Copy link

hardworm commented May 22, 2020

Столкнулся с проблемой что API запросы бибилиотеки не соотвествуют документации https://www.amocrm.ru/developers/content/oauth/step-by-step

Требуется такой запрос с посылкой JSON и он работает

### обновление токена
### https://www.amocrm.ru/developers/content/oauth/step-by-step
POST https://site123.amocrm.ru/oauth2/access_token
Content-Type: application/json

{
  "client_id": "ffecefef-743d-***",
  "client_secret": "kVxG*****",
  "grant_type": "refresh_token",
  "refresh_token": "def5020****",
  "redirect_uri": "https://site.ru"
}

Но библиотека формирует запрос и он не работает

### обновление токена POST
POST https://site123.amocrm.com/oauth2/access_token
Content-Type: application/x-www-form-urlencoded

client_id=ffecefef-743d-******&client_secret=kVxGs2FW******&redirect_uri=https%3A%2F%2Fsite.ru%2F&grant_type=refresh_token&refresh_token=def50200*******

И сервер отвечает ошибкой

{
  "title": "Wrong client",
  "type": "https://developers.amocrm.ru/v3/errors/OAuthProblemJson",
  "status": 401,
  "detail": "Client authentication failed"
}
@bessudnov
Copy link
Collaborator

Проблема, судя по описанию, в другом
В первом примере у вас запрос на site123.amocrm.ru
А во втором site123.amocrm.com

@hardworm
Copy link
Author

Проблема, судя по описанию, в другом
В первом примере у вас запрос на site123.amocrm.ru
А во втором site123.amocrm.com

Это неудачно скрыл данные. Руками я могу получить токен, могу сделать refresh, если собрать запрос как в документации. А вот с библиотекой беда :-(
Включил отладочную информацию и увидел какой запрос она шлет. Руками его повторяю - не работает.

@bessudnov
Copy link
Collaborator

Думаю к концу недели посмотрю подробно Issue и PR

@max-kut
Copy link
Contributor

max-kut commented Jun 3, 2020

Мне кажется в запросе передается неверный идентификатор клиента. У меня проблем с получением нового access_token по authotization_code и по refresh_token не возникало

@max-kut
Copy link
Contributor

max-kut commented Jun 3, 2020

Кстати, вроде такой ответ может прийти, если повторно используешь refresh_token

@hardworm
Copy link
Author

hardworm commented Jun 3, 2020

Мне кажется в запросе передается неверный идентификатор клиента. У меня проблем с получением нового access_token по authotization_code и по refresh_token не возникало

"У меня такая же нога и не болит" (с).

Как минимум сейчас библиотека не соотвествует документации. И поддерка ничего не может сделать и подсказать что не так.

Есть догадки, что проблема в экранировании. Взяв запрос генерируемый бибилиотекой и засунув curl и поигравшись с экранированием, мне удалось пропихнуть запрос. Но это чертова магия и нет документации. Добавив простой провайдер для формирования запроса проблема уходит

@max-kut
Copy link
Contributor

max-kut commented Jun 3, 2020

Документация и правда местами расстраивает, но покажи код работы с библиотекой

@hardworm
Copy link
Author

hardworm commented Jun 4, 2020

Документация и правда местами расстраивает, но покажи код работы с библиотекой

Сомневаюсь в такой процедуре

<?php

namespace UnitPay\PartnerBundle\Manager\OAuth2\Provider;

use AmoCRM\OAuth2\Client\Provider\AmoCRM;
use Exception;
use League\OAuth2\Client\Grant\AuthorizationCode;
use League\OAuth2\Client\Grant\RefreshToken;
use Psr\Log\LoggerInterface;
use UnitPay\PartnerBundle\Exception\OAuth2Exception;

class OAuth2AmoCRM extends OAuth2Abstract
{
    public const SERVICE = 3;

    private const REQUEST_TIMEOUT = 15;

    private const BASE_DOMAIN = 'salesunitpayru.amocrm.ru';

    /**
     * @var AmoCRM
     */
    private $provider;
    /**
     * @var LoggerInterface
     */
    private $logger;

    private $params = [];

    public function __construct(array $params, LoggerInterface $logger)
    {
        $this->logger = $logger;
        $this->params = $params;

        $this->provider = new AmoCRM(
            [
                'clientId'     => $params['id'],
                'clientSecret' => $params['secret'],
                'redirectUri'  => 'https://unitpay.ru',
                'timeout'      => self::REQUEST_TIMEOUT,
            ]
        );
        $this->provider->setBaseDomain(self::BASE_DOMAIN);

        parent::__construct($params);
    }

    public function getAuthUrl(string $hash): string
    {
        return $this->provider->getAuthorizationUrl();
    }

    public function getAuthToken(string $code): array
    {
        try {
            $accessToken = $this->provider->getAccessToken(
                new AuthorizationCode(),
                ['code' => $this->params['code']]
            );

            return $accessToken->getValues();
        } catch (Exception $exception) {
            $this->logger->error(__METHOD__ . ' exception request token error:' . $exception->getMessage());
            throw new OAuth2Exception('exception request token', OAuth2Exception::CODE_MANAGER_INVALID_ARGUMENT);
        }
    }

    public function refreshToken(array $token): array
    {
        try {
            $accessToken = $this->provider->getAccessToken(
                new RefreshToken(),
                ['refresh_token' => $token['refresh_token']]
            );

            return [
                'access_token'  => $accessToken->getToken(),
                'refresh_token' => $accessToken->getRefreshToken(),
                'expires_in'    => $accessToken->getExpires(),
            ];
        } catch (Exception $exception) {
            $this->logger->error(
                __METHOD__ . ' exception request token error: ' . $exception->getCode() . $exception->getMessage()
            );
            throw new OAuth2Exception('exception request token', OAuth2Exception::CODE_MANAGER_INVALID_ARGUMENT);
        }
    }
}

@bessudnov
Copy link
Collaborator

Проверил следующим простым скриптом:

$provider = new \AmoCRM\OAuth2\Client\Provider\AmoCRM(
    [
        'clientId'     => '0ef011a7-xxx,
        'clientSecret' => 'xxxx',
        'redirectUri'  => 'https://xxxx.ru',
        'timeout'      => 5,
    ]
);

$provider->setBaseDomain('shard151.amocrm.ru');

$refreshToken = 'xxxx';

$accessToken = $provider->getAccessToken(
    new \League\OAuth2\Client\Grant\RefreshToken(),
    ['refresh_token' => $refreshToken]
);

var_dump([
    'access_token'  => $accessToken->getToken(),
    'refresh_token' => $accessToken->getRefreshToken(),
    'expires_in'    => $accessToken->getExpires(),
]);

Всё отработало корректно.

Данное API вообще принимает и application/x-www-form-urlencoded и application/json

Сделал запрос cURL, тоже всё корректно:

curl -X POST 'https://shard151.amocrm.ru/oauth2/access_token' -H 'Content-Type: application/x-www-form-urlencoded' -d 'client_id=0ef011a7-xxx&client_secret=xxx&redirect_uri=https%3A%2F%2F8e0axxx.ngrok.io%2Fexamples%2Fget_token.php&grant_type=refresh_token&refresh_token=def5020xxx' -vvv

> POST /oauth2/access_token HTTP/1.1
> Host: shard151.amocrm.ru
> User-Agent: curl/7.64.1
> Accept: */*
> Content-Type: application/x-www-form-urlencoded
> Content-Length: 1111
> Expect: 100-continue
> 
< HTTP/1.1 100 Continue
* We are completely uploaded and fine
< HTTP/1.1 200 OK
< Date: Sat, 06 Jun 2020 17:15:40 GMT
< Content-Type: application/json; charset=UTF-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< Set-Cookie: session_id=xxxxx; path=/; domain=.amocrm.ru; secure; HttpOnly
< Expires: Thu, 19 Nov 1981 08:52:00 GMT
< Pragma: no-cache
< Cache-Control: no-store
< Server: -
< Runtime-Generated: 0.4131
< Runtime-Timestamp: 1591463740
< Served-By: 636f72652d6261636b2d736861726431302d7372763031622e70726f642e636f72652e616d6f7372762e7275
< Powered-By: amoCore
< Strict-Transport-Security: max-age=31536000
< X-XSS-Protection: 1; mode=block
< X-Content-Type-Options: nosniff
< X-Frame-Options: sameorigin
< 
* Connection #0 to host shard151.amocrm.ru left intact
{"token_type":"Bearer","expires_in":85699,"access_token":"xxx.xxx.xxx-xxx-xxx-xxx","refresh_token":"xxx"}

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

Вообще ошибка Client authentication failed выбрасывается в следующих случаях:

  1. Передаваемый redirect_uri не равен тому, который указан в настройках. Он должен полностью соответствовать.
  2. Передаче access_token не в заголовке, а в cookie

@hardworm
Copy link
Author

hardworm commented Jun 6, 2020

Передаваемый redirect_uri не равен тому, который указан в настройках. Он должен полностью соответствовать.

Скорей всего в этом и проблема. Добавь к url вконце / и будет та же ошибка

$provider = new \AmoCRM\OAuth2\Client\Provider\AmoCRM(
    [
        'clientId'     => '0ef011a7-xxx,
        'clientSecret' => 'xxxx',
        'redirectUri'  => 'https://xxxx.ru/',
        'timeout'      => 5,
    ]
);

Осталось понять почему через json и application/x-www-form-urlencode разное поведение. Первый токен запрашивался с /, а теперь без / вконце работает.

p.s. Спасибо, так уже можно работать, url исправить не проблема.
p.s.2 А над патчем стоит подумать, ведь удобно когда билиотека соответствует документации. Еще бы аозмодность debug добавить и вообще красота.

@TrejGun
Copy link

TrejGun commented Jul 10, 2020

еще бы добавить библиотеки на других языках, кроме php - вот тогда будет красота!

@hardworm
Copy link
Author

еще бы добавить библиотеки на других языках, кроме php - вот тогда будет красота!

тут победить php и синхронизировать его с документацией не могут. Какие другие языки?

@paulbaldie
Copy link

Вообще ошибка Client authentication failed выбрасывается в следующих случаях:

  1. Передаваемый redirect_uri не равен тому, который указан в настройках. Он должен полностью соответствовать.
  2. Передаче access_token не в заголовке, а в cookie

Помог первый пункт, спасибо! Отличался URI при получении первичных токенов и при запросе рефреша.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants