Проблема
Отправка почтового запроса на 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]
}
Буду признателен за любую информацию здесь!