Instagram Basi c Display API отвечает 400 неверным запросом для AccessToken - PullRequest
1 голос
/ 19 июня 2020

Проблема

Отправка почтового запроса на https://api.instagram.com/oauth/access_token (шаг 2 здесь ) из нашего бэкэнда приводит к 400 неверному запросу без какой-либо другой информации.

Мы постоянно могут получить успешный ответ с помощью запроса cURL и попадания в API с помощью выборки на симуляторе iOS, но запрос узла не выполняется. Мы попробовали несколько библиотек запросов, включая request , node-fetch и ax ios, и все они показывают одинаковый статус ответа и сообщение об ошибке.

Успешный запрос cURL

Вот cURL, который работает успешно (без учета конфиденциальных данных):

curl -X POST \
  https://api.instagram.com/oauth/access_token \
  -H 'Accept: */*' \
  -H 'Cache-Control: no-cache' \
  -H 'Connection: keep-alive' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -H 'Host: api.instagram.com' \
  -H 'Postman-Token: ${myPostmanToken} ' \
  -H 'User-Agent: PostmanRuntime/7.11.0' \
  -H 'accept-encoding: gzip, deflate' \
  -H 'cache-control: no-cache' \
  -H 'content-length: 403' \
  -H 'cookie: ig_did=${my_ig_did}; rur=FTW; csrftoken=${mycsrftoken}; mid=${mymid}' \
  -b 'ig_did=${my_ig_did}; rur=FTW; csrftoken=${mycsrftoken}; mid=${mymid}' \
  -d 'client_id=${myClientId}&client_secret=${mysecret}&code=${myCode}&grant_type=authorization_code&redirect_uri=${myRedirectUri}'

Приведенное выше возвращает ожидаемый

{"error_type": "OAuthException", "code": 400, "error_message": "This authorization code has been used"}(base)

Неудачные запросы узла

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

Ниже приведен код узла, который мы пробовали:

  const url = 'https://api.instagram.com/oauth/access_token';

  const body = {
    client_id: myClientId,
    client_secret: myClientSecret,
    code: myCode,
    grant_type: 'authorization_code',
    redirect_uri: myRedirectUri,
  };

  const options = {
    headers: { 'Content-Type': 'application/json' },
  };

  return axios.post(url, body, options).then(resp => {
    console.log(resp);
  });

Мы также пробовали использовать x-www-form-url-encoded согласно этому сообщению SO :

  const url = 'https://api.instagram.com/oauth/access_token';

  const body = {
    client_id: myClientId,
    client_secret: myClientSecret,
    code: myCode,
    grant_type: 'authorization_code',
    redirect_uri: myRedirectUri,
  };

  const options = {
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  };

  return axios.post(url, body, options).then(resp => {
    console.log(resp);
  });

Мы также пробовали кодировать его в соответствии с этим сообщением SO :

  const url = 'https://api.instagram.com/oauth/access_token';

  const body = {
    client_id: myClientId,
    client_secret: myClientSecret,
    code: myCode,
    grant_type: 'authorization_code',
    redirect_uri: myRedirectUri,
  };

  var formBody = [];
  for (var property in body) {
    var encodedKey = encodeURIComponent(property);
    var encodedValue = encodeURIComponent(body[property]);
    formBody.push(encodedKey + '=' + encodedValue);
  }
  formBody = formBody.join('&');

  const options = {
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
    },
  };

  return axios.post(url, formBody, options).then(resp => {
    console.log(resp);
  });

Объект ответа

Вот весь объект ответа ax ios, который включает запрос данные и заголовок:

Error: Request failed with status code 400
    at createError (/Users/sgarza62/ditto-app/api/node_modules/axios/lib/core/createError.js:16:15)
    at settle (/Users/sgarza62/ditto-app/api/node_modules/axios/lib/core/settle.js:17:12)
    at IncomingMessage.handleStreamEnd (/Users/sgarza62/ditto-app/api/node_modules/axios/lib/adapters/http.js:236:11)
    at IncomingMessage.emit (events.js:322:22)
    at IncomingMessage.EventEmitter.emit (domain.js:482:12)
    at endReadableNT (_stream_readable.js:1187:12)
    at processTicksAndRejections (internal/process/task_queues.js:84:21) {
  config: {
    url: 'https://api.instagram.com/oauth/access_token',
    method: 'post',
    data: 'client_id=601492960801083&client_secret=56c3508989f3aa0eff2939201280c616&code=AQAr0t6KazHaErfxOychsqVqW9nOlczw8o_PrAKuktDaC6xH25gSiqPV4Wi-OSwHfqvyUhD8gbXDB31iZqDnLG0lRTvNGhRooUTfG41tlJgoxHFZ9JVJPkk9eoQfJTFKQfXKwsDST92pJx7bkcp_GugVtbhan1s-X9EJOgBoTo1LTVusWCnlXXt2QkgRU6Ji3fNkj3con_BElakFVmeKu4sXCuMb9CodXyeH_bEvbQosIw&grant_type=authorization_code&redirect_uri=https%3A%2F%2Fwww.ditto-app.com%2Finstagram',
    headers: {
      Accept: 'application/json, text/plain, */*',
      'Content-Type': 'application/x-www-form-urlencoded',
      'User-Agent': 'axios/0.19.2',
      'Content-Length': 403
    },
    transformRequest: [ [Function: transformRequest] ],
    transformResponse: [ [Function: transformResponse] ],
    timeout: 0,
    adapter: [Function: httpAdapter],
    xsrfCookieName: 'XSRF-TOKEN',
    xsrfHeaderName: 'X-XSRF-TOKEN',
    maxContentLength: -1,
    validateStatus: [Function: validateStatus]
  },
  request: ClientRequest {
    _events: [Object: null prototype] {
      socket: [Function],
      abort: [Function],
      aborted: [Function],
      error: [Function],
      timeout: [Function],
      prefinish: [Function: requestOnPrefinish]
    },
    _eventsCount: 6,
    _maxListeners: undefined,
    outputData: [],
    outputSize: 0,
    writable: true,
    _last: true,
    chunkedEncoding: false,
    shouldKeepAlive: false,
    useChunkedEncodingByDefault: true,
    sendDate: false,
    _removedConnection: false,
    _removedContLen: false,
    _removedTE: false,
    _contentLength: null,
    _hasBody: true,
    _trailer: '',
    finished: true,
    _headerSent: true,
    socket: TLSSocket {
      _tlsOptions: [Object],
      _secureEstablished: true,
      _securePending: false,
      _newSessionPending: false,
      _controlReleased: true,
      _SNICallback: null,
      servername: 'api.instagram.com',
      alpnProtocol: false,
      authorized: true,
      authorizationError: null,
      encrypted: true,
      _events: [Object: null prototype],
      _eventsCount: 9,
      connecting: false,
      _hadError: false,
      _parent: null,
      _host: 'api.instagram.com',
      _readableState: [ReadableState],
      readable: true,
      _maxListeners: undefined,
      _writableState: [WritableState],
      writable: false,
      allowHalfOpen: false,
      _sockname: null,
      _pendingData: null,
      _pendingEncoding: '',
      server: undefined,
      _server: null,
      ssl: [TLSWrap],
      _requestCert: true,
      _rejectUnauthorized: true,
      parser: null,
      _httpMessage: [Circular],
      [Symbol(res)]: [TLSWrap],
      [Symbol(asyncId)]: 390,
      [Symbol(kHandle)]: [TLSWrap],
      [Symbol(kSetNoDelay)]: false,
      [Symbol(lastWriteQueueSize)]: 0,
      [Symbol(timeout)]: null,
      [Symbol(kBuffer)]: null,
      [Symbol(kBufferCb)]: null,
      [Symbol(kBufferGen)]: null,
      [Symbol(kCapture)]: false,
      [Symbol(kBytesRead)]: 0,
      [Symbol(kBytesWritten)]: 0,
      [Symbol(connect-options)]: [Object]
    },
    connection: TLSSocket {
      _tlsOptions: [Object],
      _secureEstablished: true,
      _securePending: false,
      _newSessionPending: false,
      _controlReleased: true,
      _SNICallback: null,
      servername: 'api.instagram.com',
      alpnProtocol: false,
      authorized: true,
      authorizationError: null,
      encrypted: true,
      _events: [Object: null prototype],
      _eventsCount: 9,
      connecting: false,
      _hadError: false,
      _parent: null,
      _host: 'api.instagram.com',
      _readableState: [ReadableState],
      readable: true,
      _maxListeners: undefined,
      _writableState: [WritableState],
      writable: false,
      allowHalfOpen: false,
      _sockname: null,
      _pendingData: null,
      _pendingEncoding: '',
      server: undefined,
      _server: null,
      ssl: [TLSWrap],
      _requestCert: true,
      _rejectUnauthorized: true,
      parser: null,
      _httpMessage: [Circular],
      [Symbol(res)]: [TLSWrap],
      [Symbol(asyncId)]: 390,
      [Symbol(kHandle)]: [TLSWrap],
      [Symbol(kSetNoDelay)]: false,
      [Symbol(lastWriteQueueSize)]: 0,
      [Symbol(timeout)]: null,
      [Symbol(kBuffer)]: null,
      [Symbol(kBufferCb)]: null,
      [Symbol(kBufferGen)]: null,
      [Symbol(kCapture)]: false,
      [Symbol(kBytesRead)]: 0,
      [Symbol(kBytesWritten)]: 0,
      [Symbol(connect-options)]: [Object]
    },
    _header: 'POST /oauth/access_token HTTP/1.1\r\n' +
      'Accept: application/json, text/plain, */*\r\n' +
      'Content-Type: application/x-www-form-urlencoded\r\n' +
      'User-Agent: axios/0.19.2\r\n' +
      'Content-Length: 403\r\n' +
      'Host: api.instagram.com\r\n' +
      'Connection: close\r\n' +
      '\r\n',
    _onPendingData: [Function: noopPendingOutput],
    agent: Agent {
      _events: [Object: null prototype],
      _eventsCount: 2,
      _maxListeners: undefined,
      defaultPort: 443,
      protocol: 'https:',
      options: [Object],
      requests: {},
      sockets: [Object],
      freeSockets: {},
      keepAliveMsecs: 1000,
      keepAlive: false,
      maxSockets: Infinity,
      maxFreeSockets: 256,
      maxCachedSessions: 100,
      _sessionCache: [Object],
      [Symbol(kCapture)]: false
    },
    socketPath: undefined,
    method: 'POST',
    insecureHTTPParser: undefined,
    path: '/oauth/access_token',
    _ended: true,
    res: IncomingMessage {
      _readableState: [ReadableState],
      readable: false,
      _events: [Object: null prototype],
      _eventsCount: 3,
      _maxListeners: undefined,
      socket: [TLSSocket],
      connection: [TLSSocket],
      httpVersionMajor: 1,
      httpVersionMinor: 1,
      httpVersion: '1.1',
      complete: true,
      headers: [Object],
      rawHeaders: [Array],
      trailers: {},
      rawTrailers: [],
      aborted: false,
      upgrade: false,
      url: '',
      method: null,
      statusCode: 400,
      statusMessage: 'Bad Request',
      client: [TLSSocket],
      _consuming: false,
      _dumped: false,
      req: [Circular],
      responseUrl: 'https://api.instagram.com/oauth/access_token',
      redirects: [],
      [Symbol(kCapture)]: false
    },
    aborted: false,
    timeoutCb: null,
    upgradeOrConnect: false,
    parser: null,
    maxHeadersCount: null,
    reusedSocket: false,
    _redirectable: Writable {
      _writableState: [WritableState],
      writable: true,
      _events: [Object: null prototype],
      _eventsCount: 2,
      _maxListeners: undefined,
      _options: [Object],
      _redirectCount: 0,
      _redirects: [],
      _requestBodyLength: 403,
      _requestBodyBuffers: [],
      _onNativeResponse: [Function],
      _currentRequest: [Circular],
      _currentUrl: 'https://api.instagram.com/oauth/access_token',
      [Symbol(kCapture)]: false
    },
    [Symbol(kCapture)]: false,
    [Symbol(kNeedDrain)]: false,
    [Symbol(corked)]: 0,
    [Symbol(kOutHeaders)]: [Object: null prototype] {
      accept: [Array],
      'content-type': [Array],
      'user-agent': [Array],
      'content-length': [Array],
      host: [Array]
    }
  },
  response: {
    status: 400,
    statusText: 'Bad Request',
    headers: {
      'content-type': 'application/json; charset=utf-8',
      'ig-set-password-encryption-web-key-id': '87',
      'ig-set-password-encryption-web-pub-key': '8dd9aad29d9a614c338cff479f850d3ec57c525c33b3f702ab65e9e057fc087e',
      'ig-set-password-encryption-web-key-version': '9',
      vary: 'Accept-Language, Cookie',
      'content-language': 'en',
      date: 'Thu, 18 Jun 2020 22:22:38 GMT, Thu, 18 Jun 2020 22:22:38 GMT',
      'strict-transport-security': 'max-age=31536000',
      'cache-control': 'private, no-cache, no-store, must-revalidate',
      pragma: 'no-cache',
      expires: 'Sat, 01 Jan 2000 00:00:00 GMT',
      'x-frame-options': 'SAMEORIGIN',
      'content-security-policy': "report-uri https://www.instagram.com/security/csp_report/; default-src 'self' https://www.instagram.com; img-src https: data: blob:; font-src https: data:; media-src 'self' blob: https://www.instagram.com https://*.cdninstagram.com https://*.fbcdn.net; manifest-src 'self' https://www.instagram.com; script-src 'self' https://instagram.com https://www.instagram.com https://*.www.instagram.com https://*.cdninstagram.com wss://www.instagram.com https://*.facebook.com https://*.fbcdn.net https://*.facebook.net 'unsafe-inline' 'unsafe-eval' blob:; style-src 'self' https://*.www.instagram.com https://www.instagram.com 'unsafe-inline'; connect-src 'self' https://instagram.com https://www.instagram.com https://*.www.instagram.com https://graph.instagram.com https://*.graph.instagram.com https://*.cdninstagram.com https://api.instagram.com https://i.instagram.com wss://www.instagram.com wss://edge-chat.instagram.com https://*.facebook.com https://*.fbcdn.net https://*.facebook.net chrome-extension://boadgeojelhgndaghljhdicfkmllpafd blob:; worker-src 'self' blob: https://www.instagram.com; frame-src 'self' https://instagram.com https://www.instagram.com https://staticxx.facebook.com https://www.facebook.com https://web.facebook.com https://connect.facebook.net https://m.facebook.com; object-src 'none'; upgrade-insecure-requests",
      'x-content-type-options': 'nosniff',
      'x-xss-protection': '0',
      'x-aed': '15',
      'access-control-expose-headers': 'X-IG-Set-WWW-Claim',
      'set-cookie': [Array],
      'x-fb-trip-id': '1082456386',
      connection: 'close',
      'content-length': '101'
    },
    config: {
      url: 'https://api.instagram.com/oauth/access_token',
      method: 'post',
      data: 'client_id=601492960801083&client_secret=56c3508989f3aa0eff2939201280c616&code=AQAr0t6KazHaErfxOychsqVqW9nOlczw8o_PrAKuktDaC6xH25gSiqPV4Wi-OSwHfqvyUhD8gbXDB31iZqDnLG0lRTvNGhRooUTfG41tlJgoxHFZ9JVJPkk9eoQfJTFKQfXKwsDST92pJx7bkcp_GugVtbhan1s-X9EJOgBoTo1LTVusWCnlXXt2QkgRU6Ji3fNkj3con_BElakFVmeKu4sXCuMb9CodXyeH_bEvbQosIw&grant_type=authorization_code&redirect_uri=https%3A%2F%2Fwww.ditto-app.com%2Finstagram',
      headers: [Object],
      transformRequest: [Array],
      transformResponse: [Array],
      timeout: 0,
      adapter: [Function: httpAdapter],
      xsrfCookieName: 'XSRF-TOKEN',
      xsrfHeaderName: 'X-XSRF-TOKEN',
      maxContentLength: -1,
      validateStatus: [Function: validateStatus]
    },
    request: ClientRequest {
      _events: [Object: null prototype],
      _eventsCount: 6,
      _maxListeners: undefined,
      outputData: [],
      outputSize: 0,
      writable: true,
      _last: true,
      chunkedEncoding: false,
      shouldKeepAlive: false,
      useChunkedEncodingByDefault: true,
      sendDate: false,
      _removedConnection: false,
      _removedContLen: false,
      _removedTE: false,
      _contentLength: null,
      _hasBody: true,
      _trailer: '',
      finished: true,
      _headerSent: true,
      socket: [TLSSocket],
      connection: [TLSSocket],
      _header: 'POST /oauth/access_token HTTP/1.1\r\n' +
        'Accept: application/json, text/plain, */*\r\n' +
        'Content-Type: application/x-www-form-urlencoded\r\n' +
        'User-Agent: axios/0.19.2\r\n' +
        'Content-Length: 403\r\n' +
        'Host: api.instagram.com\r\n' +
        'Connection: close\r\n' +
        '\r\n',
      _onPendingData: [Function: noopPendingOutput],
      agent: [Agent],
      socketPath: undefined,
      method: 'POST',
      insecureHTTPParser: undefined,
      path: '/oauth/access_token',
      _ended: true,
      res: [IncomingMessage],
      aborted: false,
      timeoutCb: null,
      upgradeOrConnect: false,
      parser: null,
      maxHeadersCount: null,
      reusedSocket: false,
      _redirectable: [Writable],
      [Symbol(kCapture)]: false,
      [Symbol(kNeedDrain)]: false,
      [Symbol(corked)]: 0,
      [Symbol(kOutHeaders)]: [Object: null prototype]
    },
    data: {
      error_type: 'OAuthException',
      code: 400,
      error_message: 'This authorization code has expired'
    }
  },
  isAxiosError: true,
  toJSON: [Function]
}

Буду признателен за любую информацию здесь!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...