Проблемы Guzzle и Form + Basic Auth с Laravel

Я пытался получить некоторые данные с Livecoding.tv, и в настоящее время я повторно использую свой контроллер Oauth2, который я использовал для twitch API, что должно быть довольно просто.

Если кто-то не знает, поток, используемый Oauth, следующий:

  1. Перенаправьте пользователя на стороннюю ссылку Oauth с кодом вашего приложения.

  2. Пользователь авторизуется.

  3. Пользователь снова перенаправляется на ваш веб-сайт с авторизованным токеном, который вы затем можете отправить третьей стороне, чтобы получить свой токен обновления и т. д.

Теперь на шаге 3 я столкнулся с некоторыми проблемами. Вот описание и пример от разработчика:

Получение токена: https://www.livecoding.tv/o/token/

Заголовок

Аутентификация HTTP Basic с использованием application_code в качестве имени пользователя и application_secret в качестве пароля, как показано в примере ниже.

Тело POST

code=EXAMPLE Token gotten from redirect
grant_type=Your grant type (authorization_type)
redirect_uri=Your redirect URL

А вот пример cURL-запроса из документации рабочего curl-запроса.

curl -X POST -d "grant_type=authorization_code&code=Php4iJpXGpDT8lCqgBcbfQ2yzhB0Av&client_id=vCk6rNsC&redirect_uri=http://localhost/externalapp" -u"vCk6rNsC:sfMxcHUuNnZ" https://www.livecoding.tv/o/token/

Итак, я попытался сделать это в Postman (https://www.getpostman.com/), что сработало. из коробки я попросил Почтальона преобразовать это в PHP, чтобы посмотреть, не пропустил ли я что-то. Вот результат рабочего запроса Postman:

<?php

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => "https://www.livecoding.tv/o/token/",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => "code=SOMECODE&client_id=SOMECLIENTID&redirect_uri=SOMEURL&grant_type=authorization_code",
  CURLOPT_HTTPHEADER => array(
    "authorization: Basic U09NRVVTRVI6U09NRVBBU1NXT1JE",
    "cache-control: no-cache",
    "content-type: application/x-www-form-urlencoded",
    "postman-token: c8df4bbc-cbd0-73eb-df35-80210989db33"
  ),
));

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $response;
}

Я был очень рад, что это сработало сразу, поэтому мне просто нужно было заставить клиент Guzzle делать то же самое, что уже работает для Twitch Oauth, вот мой код для этого:

{
            $providers = ServiceProvider::findOrFail(2);
            $client = new Client([
                'base_uri' => $providers->oauth_url . '/token/',
                'form_params' => [
                    'code' => $token,
                    'grant_type' => 'authorization_code',
                    'client_id' => $providers->application_code,
                    'redirect_uri' => $providers->redirection_url
                ],
                'auth' => [
                    'somestring',
                    'someotherstring',
                ],
                'headers' => [
                    'Content type' => 'application/x-www-form-urlencoded',
                    'cache-control' => 'no-cache'
                ]
            ]);
            $response = $client->request('POST');
            return ($response);
        }

Это просто вернет мне 401, поэтому я решил немного отладить, и вот запрос, который приходит, если я остановлю его прямо перед отправкой:

Client {#637 ▼
  -config: array:10 [▼
    "base_uri" => Uri {#676 ▼
      -scheme: "https"
      -userInfo: ""
      -host: "www.livecoding.tv"
      -port: null
      -path: "/o/token/"
      -query: ""
      -fragment: ""
    }
    "form_params" => array:4 [▼
      "code" => "SOMECODE"
      "grant_type" => "authorization_code"
      "client_id" => "SOMECLIENTID"
      "redirect_uri" => "http://REDIRECTURI"
    ]
    "auth" => array:2 [▼
      0 => "SOMECLIENTID"
      1 => "SOMECLIENTSECRET"
    ]
    "headers" => array:3 [▼
      "Content type" => "application/x-www-form-urlencoded"
      "cache-control" => "no-cache"
      "User-Agent" => "GuzzleHttp/6.2.1 curl/7.26.0 PHP/5.6.27-1~dotdeb+7.1"
    ]
    "handler" => HandlerStack {#664 ▼
      -handler: Closure {#671 ▼
        class: "GuzzleHttp\Handler\Proxy"
        parameters: {▼
          $request: {▼
            typeHint: "Psr\Http\Message\RequestInterface"
          }
          $options: {▼
            typeHint: "array"
          }
        }
        use: {▼
          $default: Closure {#669 ▼
            class: "GuzzleHttp\Handler\Proxy"
            parameters: {▼
              $request: {▼
                typeHint: "Psr\Http\Message\RequestInterface"
              }
              $options: {▼
                typeHint: "array"
              }
            }
            use: {▼
              $default: CurlMultiHandler {#634 ▼
                -factory: CurlFactory {#667 ▼
                  -handles: []
                  -maxHandles: 50
                }
                -selectTimeout: 1
                -active: null
                -handles: []
                -delays: []
              }
              $sync: CurlHandler {#666 ▼
                -factory: CurlFactory {#665 ▼
                  -handles: []
                  -maxHandles: 3
                }
              }
            }
            file: "/LARAVELPATH/vendor/guzzlehttp/guzzle/src/Handler/Proxy.php"
            line: "25 to 29"
          }
          $streaming: StreamHandler {#670 ▼
            -lastHeaders: []
          }
        }
        file: "LARAVELPATH/vendor/guzzlehttp/guzzle/src/Handler/Proxy.php"
        line: "49 to 53"
      }
      -stack: array:4 [▼
        0 => array:2 [▼
          0 => Closure {#672 ▼
            class: "GuzzleHttp\Middleware"
            parameters: {▶}
            file: "LARAVELPATH/vendor/guzzlehttp/guzzle/src/Middleware.php"
            line: "54 to 69"
          }
          1 => "http_errors"
        ]
        1 => array:2 [▼
          0 => Closure {#673 ▼
            class: "GuzzleHttp\Middleware"
            parameters: {▶}
            file: "LARAVELPATH/vendor/guzzlehttp/guzzle/src/Middleware.php"
            line: "148 to 150"
          }
          1 => "allow_redirects"
        ]
        2 => array:2 [▼
          0 => Closure {#674 ▼
            class: "GuzzleHttp\Middleware"
            parameters: {▶}
            file: "LARAVELPATH/vendor/guzzlehttp/guzzle/src/Middleware.php"
            line: "27 to 43"
          }
          1 => "cookies"
        ]
        3 => array:2 [▼
          0 => Closure {#675 ▼
            class: "GuzzleHttp\Middleware"
            parameters: {▶}
            file: "LARAVELPATH/vendor/guzzlehttp/guzzle/src/Middleware.php"
            line: "216 to 218"
          }
          1 => "prepare_body"
        ]
      ]
      -cached: null
    }
    "allow_redirects" => array:5 [▼
      "max" => 5
      "protocols" => array:2 [▼
        0 => "http"
        1 => "https"
      ]
      "strict" => false
      "referer" => false
      "track_redirects" => false
    ]
    "http_errors" => true
    "decode_content" => true
    "verify" => true
    "cookies" => false
  ]
}

Как вы можете видеть здесь, здесь есть только параметр с именем «auth», а не базовая аутентификация, которая задокументирована в Guzzle здесь: http://docs.guzzlephp.org/en/latest/request-options.html#auth

Хотя я бы отметил, что введены правильные значения.

Для отладки я только что сделал dd($client), я не знаю, даст ли это мне все ответы?

Таким образом, другая возможность состоит в том, чтобы закодировать его в base64 (как это делается в базовой аутентификации в целом) и добавить заголовок «Авторизация» вручную, я пробовал это, но я не знаю, правильно ли я это делаю, когда делаю:

$credentials = base64_encode($clientvariable . ':' . $clientsecretvariable)

Будет ли это правильным путем? Хотя я бы предпочел использовать это как последнее средство, если я не заставлю параметр auth работать в Guzzle.

Я знаю о других вопросах Stackoverflow о Guzzle и базовой аутентификации, и да, я читал их, надеюсь, я предоставил достаточно информации, чтобы показать это.


person Marius    schedule 28.12.2016    source источник


Ответы (1)


Проблема здесь была связана с тем, как я возвращаю ответ от Guzzle.

Поскольку я только что вернул $response, который является просто потоком, браузер ничего не вернул, а поскольку автоматическое обновление хрома он выполняет запрос дважды, а во второй раз у меня был бы только мой код дважды, который вернул бы ошибка.

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

person Marius    schedule 30.12.2016