Related
I am trying to get the youtube transcription with youtube API on the Express.js server. From what I understand, I need to use the client id for this, so I am trying to authenticate to google API. For this purpose I use quickstart.js from google docs and Express listener on redirect_uri to handle authentication:
interface GoogleOAuthTokenResponse {
access_token: string
token_type: string
expires_in: number
id_token: string
refresh_token?: string
}
// Handle authentication callback from Google
app.get('/auth/google/callback', async (req, res, next) => {
const code = req.query.code
const response = await axios.post<GoogleOAuthTokenResponse>('https://oauth2.googleapis.com/token', {
code,
client_id: process.env.YOUTUBE_CLIENT_ID,
client_secret: process.env.YOUTUBE_CLIENT_SECRET,
redirect_uri: process.env.YOUTUBE_REDIRECT_URI,
grant_type: 'authorization_code'
}, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
const accessToken = response.data.access_token
// Now that we have the access token and id token, we can use them to call Google API services
const googleResponse = await axios.get('https://www.googleapis.com/some_google_api', {
headers: {
Authorization: `Bearer ${accessToken}`
}
})
res.send(googleResponse.data)
})
But I get the following error:
/Users/demian/Desktop/work/youtube-navigator/server/node_modules/axios/lib/core/settle.js:19
reject(new AxiosError(
^
AxiosError: Request failed with status code 400
at settle (/Users/demian/Desktop/work/youtube-navigator/server/node_modules/axios/lib/core/settle.js:19:12)
at Unzip.handleStreamEnd (/Users/demian/Desktop/work/youtube-navigator/server/node_modules/axios/lib/adapters/http.js:548:11)
at Unzip.emit (node:events:525:35)
at Unzip.emit (node:domain:489:12)
at endReadableNT (node:internal/streams/readable:1359:12)
at processTicksAndRejections (node:internal/process/task_queues:82:21) {
code: 'ERR_BAD_REQUEST',
config: {
transitional: {
silentJSONParsing: true,
forcedJSONParsing: true,
clarifyTimeoutError: false
},
adapter: [ 'xhr', 'http' ],
transformRequest: [ [Function: transformRequest] ],
transformResponse: [ [Function: transformResponse] ],
timeout: 0,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
maxBodyLength: -1,
env: { FormData: [Function], Blob: [class Blob] },
validateStatus: [Function: validateStatus],
headers: AxiosHeaders {
Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/x-www-form-urlencoded',
'User-Agent': 'axios/1.3.2',
'Content-Length': '313',
'Accept-Encoding': 'gzip, compress, deflate, br'
},
method: 'post',
url: 'https://oauth2.googleapis.com/token',
data: 'code=4%2F0AWtgzh5yCRs6xsZCCAEUhJGVTNE22-xpI9u3KaaCrgGl_wI618yJSGHUta53Z-w5VB7_Lw&client_id=252564275188-g55c2qnu6ajii45m3d154uuj9fnhlbfb.apps.googleusercontent.com&client_secret=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&redirect_uri=http%3A%2F%2Flocalhost%3A8000%2Fauth%2Fgoogle%2Fcallback&grant_type=authorization_code'
},
request: <ref *1> ClientRequest {
_events: [Object: null prototype] {
abort: [Function (anonymous)],
aborted: [Function (anonymous)],
connect: [Function (anonymous)],
error: [Function (anonymous)],
socket: [Function (anonymous)],
timeout: [Function (anonymous)],
finish: [Function: requestOnFinish]
},
_eventsCount: 7,
_maxListeners: undefined,
outputData: [],
outputSize: 0,
writable: true,
destroyed: true,
_last: false,
chunkedEncoding: false,
shouldKeepAlive: true,
maxRequestsOnConnectionReached: false,
_defaultKeepAlive: true,
useChunkedEncodingByDefault: true,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
strictContentLength: false,
_contentLength: '313',
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
_closed: true,
socket: TLSSocket {
_tlsOptions: [Object],
_secureEstablished: true,
_securePending: false,
_newSessionPending: false,
_controlReleased: true,
secureConnecting: false,
_SNICallback: null,
servername: 'oauth2.googleapis.com',
alpnProtocol: false,
authorized: true,
authorizationError: null,
encrypted: true,
_events: [Object: null prototype],
_eventsCount: 9,
connecting: false,
_hadError: false,
_parent: null,
_host: 'oauth2.googleapis.com',
_closeAfterHandlingError: false,
_readableState: [ReadableState],
_maxListeners: undefined,
_writableState: [WritableState],
allowHalfOpen: false,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: undefined,
_server: null,
ssl: [TLSWrap],
_requestCert: true,
_rejectUnauthorized: true,
timeout: 5000,
parser: null,
_httpMessage: null,
[Symbol(res)]: [TLSWrap],
[Symbol(verified)]: true,
[Symbol(pendingSession)]: null,
[Symbol(async_id_symbol)]: -1,
[Symbol(kHandle)]: [TLSWrap],
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: [Timeout],
[Symbol(kBuffer)]: null,
[Symbol(kBufferCb)]: null,
[Symbol(kBufferGen)]: null,
[Symbol(kCapture)]: false,
[Symbol(kSetNoDelay)]: false,
[Symbol(kSetKeepAlive)]: true,
[Symbol(kSetKeepAliveInitialDelay)]: 1,
[Symbol(kBytesRead)]: 0,
[Symbol(kBytesWritten)]: 0,
[Symbol(connect-options)]: [Object]
},
_header: 'POST /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/1.3.2\r\n' +
'Content-Length: 313\r\n' +
'Accept-Encoding: gzip, compress, deflate, br\r\n' +
'Host: oauth2.googleapis.com\r\n' +
'Connection: keep-alive\r\n' +
'\r\n',
_keepAliveTimeout: 0,
_onPendingData: [Function: nop],
agent: Agent {
_events: [Object: null prototype],
_eventsCount: 2,
_maxListeners: undefined,
defaultPort: 443,
protocol: 'https:',
options: [Object: null prototype],
requests: [Object: null prototype] {},
sockets: [Object: null prototype] {},
freeSockets: [Object: null prototype],
keepAliveMsecs: 1000,
keepAlive: true,
maxSockets: Infinity,
maxFreeSockets: 256,
scheduling: 'lifo',
maxTotalSockets: Infinity,
totalSocketCount: 1,
maxCachedSessions: 100,
_sessionCache: [Object],
[Symbol(kCapture)]: false
},
socketPath: undefined,
method: 'POST',
maxHeaderSize: undefined,
insecureHTTPParser: undefined,
path: '/token',
_ended: true,
res: IncomingMessage {
_readableState: [ReadableState],
_events: [Object: null prototype],
_eventsCount: 4,
_maxListeners: undefined,
socket: null,
httpVersionMajor: 1,
httpVersionMinor: 1,
httpVersion: '1.1',
complete: true,
rawHeaders: [Array],
rawTrailers: [],
aborted: false,
upgrade: false,
url: '',
method: null,
statusCode: 400,
statusMessage: 'Bad Request',
client: [TLSSocket],
_consuming: true,
_dumped: false,
req: [Circular *1],
responseUrl: 'https://oauth2.googleapis.com/token',
redirects: [],
[Symbol(kCapture)]: false,
[Symbol(kHeaders)]: [Object],
[Symbol(kHeadersCount)]: 30,
[Symbol(kTrailers)]: null,
[Symbol(kTrailersCount)]: 0
},
aborted: false,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
reusedSocket: false,
host: 'oauth2.googleapis.com',
protocol: 'https:',
_redirectable: Writable {
_writableState: [WritableState],
_events: [Object: null prototype],
_eventsCount: 3,
_maxListeners: undefined,
_options: [Object],
_ended: true,
_ending: true,
_redirectCount: 0,
_redirects: [],
_requestBodyLength: 313,
_requestBodyBuffers: [],
_onNativeResponse: [Function (anonymous)],
_currentRequest: [Circular *1],
_currentUrl: 'https://oauth2.googleapis.com/token',
[Symbol(kCapture)]: false
},
[Symbol(kCapture)]: false,
[Symbol(kBytesWritten)]: 0,
[Symbol(kEndCalled)]: true,
[Symbol(kNeedDrain)]: false,
[Symbol(corked)]: 0,
[Symbol(kOutHeaders)]: [Object: null prototype] {
accept: [Array],
'content-type': [Array],
'user-agent': [Array],
'content-length': [Array],
'accept-encoding': [Array],
host: [Array]
},
[Symbol(errored)]: null,
[Symbol(kUniqueHeaders)]: null
},
response: {
status: 400,
statusText: 'Bad Request',
headers: AxiosHeaders {
date: 'Tue, 07 Feb 2023 12:04:34 GMT',
expires: 'Mon, 01 Jan 1990 00:00:00 GMT',
pragma: 'no-cache',
'cache-control': 'no-cache, no-store, max-age=0, must-revalidate',
'content-type': 'application/json; charset=utf-8',
vary: 'Origin, X-Origin, Referer',
server: 'scaffolding on HTTPServer2',
'x-xss-protection': '0',
'x-frame-options': 'SAMEORIGIN',
'x-content-type-options': 'nosniff',
'alt-svc': 'h3=":443"; ma=2592000,h3-29=":443"; ma=2592000',
'transfer-encoding': 'chunked'
},
config: {
transitional: [Object],
adapter: [Array],
transformRequest: [Array],
transformResponse: [Array],
timeout: 0,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
maxBodyLength: -1,
env: [Object],
validateStatus: [Function: validateStatus],
headers: [AxiosHeaders],
method: 'post',
url: 'https://oauth2.googleapis.com/token',
data: 'code=4%2F0AWtgzh5yCRs6xsZCCAEUhJGVTNE22-xpI9u3KaaCrgGl_wI618yJSGHUta53Z-w5VB7_Lw&client_id=252564275188-g55c2qnu6ajii45m3d154uuj9fnhlbfb.apps.googleusercontent.com&client_secret=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&redirect_uri=http%3A%2F%2Flocalhost%3A8000%2Fauth%2Fgoogle%2Fcallback&grant_type=authorization_code'
},
request: <ref *1> ClientRequest {
_events: [Object: null prototype],
_eventsCount: 7,
_maxListeners: undefined,
outputData: [],
outputSize: 0,
writable: true,
destroyed: true,
_last: false,
chunkedEncoding: false,
shouldKeepAlive: true,
maxRequestsOnConnectionReached: false,
_defaultKeepAlive: true,
useChunkedEncodingByDefault: true,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
strictContentLength: false,
_contentLength: '313',
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
_closed: true,
socket: [TLSSocket],
_header: 'POST /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/1.3.2\r\n' +
'Content-Length: 313\r\n' +
'Accept-Encoding: gzip, compress, deflate, br\r\n' +
'Host: oauth2.googleapis.com\r\n' +
'Connection: keep-alive\r\n' +
'\r\n',
_keepAliveTimeout: 0,
_onPendingData: [Function: nop],
agent: [Agent],
socketPath: undefined,
method: 'POST',
maxHeaderSize: undefined,
insecureHTTPParser: undefined,
path: '/token',
_ended: true,
res: [IncomingMessage],
aborted: false,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
reusedSocket: false,
host: 'oauth2.googleapis.com',
protocol: 'https:',
_redirectable: [Writable],
[Symbol(kCapture)]: false,
[Symbol(kBytesWritten)]: 0,
[Symbol(kEndCalled)]: true,
[Symbol(kNeedDrain)]: false,
[Symbol(corked)]: 0,
[Symbol(kOutHeaders)]: [Object: null prototype],
[Symbol(errored)]: null,
[Symbol(kUniqueHeaders)]: null
},
data: { error: 'invalid_grant', error_description: 'Bad Request' }
}
}
I checked few times that my env variables are correct. So I think this is problem with my code.
Maybe this is stupid question, but I really couldn't understand what I do incorrectly. What to do?
I'm working on a React Native app with Firebase Functions. I am unable to add new contacts to a SendGrid list consistently.
This is my function:
exports.addToSendGridMembersList = functions.https.onCall(async (data) => {
const {first, last, email} = data
p(first,last,email)
const axios = require('axios');
let e = JSON.stringify(email)
let f = JSON.stringify(first)
let l = JSON.stringify(last)
p("JSON.stringify: ", e, f, l)
axios({
method: "PUT",
url: "https://api.sendgrid.com/v3/marketing/contacts",
headers:
{ 'content-type': 'application/json',
authorization: 'Bearer ' + SEND_GRID_KEY },
body:
{ "list_ids": [
"eda0bc01-b098-4366-ad58-8bab03ec9b33"
],
"contacts": [
{
"email": "o#gmail.com",
"first_name": "o",
"last_name": "o"
}
]
}
})
.then(function (error, response, body) {
console.log(error)
console.log(response)
console.log(body);
})
});
I at first thought the axios body was unable to read constants that's why I stringified them and was going to insert them in the body (first, last and email) values. This is the response I get in Google Cloud logs
JSON.stringify: "gg#gmail.com" "gg" "gg"
> Unhandled error { Error: Request failed with status code 400 at createError (/workspace/node_modules/axios/lib/core/createError.js:16:15) at settle (/workspace/node_modules/axios/lib/core/settle.js:17:12) at IncomingMessage.handleStreamEnd (/workspace/node_modules/axios/lib/adapters/http.js:260:11) at IncomingMessage.emit (events.js:203:15) at IncomingMessage.EventEmitter.emit (domain.js:466:23) at endReadableNT (_stream_readable.js:1145:12) at process._tickCallback (internal/process/next_tick.js:63:19) config: { url: 'https://api.sendgrid.com/v3/marketing/contacts', method: 'put', headers: { Accept: 'application/json, text/plain, */*', 'Content-Type': 'application/json', authorization: 'Bearer HIDDEN', 'User-Agent': 'axios/0.21.1' }, transformRequest: [ [Function: transformRequest] ], transformResponse: [ [Function: transformResponse] ], timeout: 0, adapter: [Function: httpAdapter], xsrfCookieName: 'XSRF-TOKEN', xsrfHeaderName: 'X-XSRF-TOKEN', maxContentLength: -1, maxBodyLength: -1, validateStatus: [Function: validateStatus], body: { list_ids: [Array], contacts: [Array] }, data: undefined }, request: ClientRequest { domain: Domain { domain: null, _events: [Object], _eventsCount: 3, _maxListeners: undefined, members: [], [Symbol(kWeak)]: WeakReference {} }, _events: [Object: null prototype] { socket: [Function], abort: [Function], aborted: [Function], connect: [Function], error: [Function], timeout: [Function], prefinish: [Function: requestOnPrefinish] }, _eventsCount: 7, _maxListeners: undefined, output: [], outputEncodings: [], outputCallbacks: [], outputSize: 0, writable: true, _last: true, chunkedEncoding: false, shouldKeepAlive: false, useChunkedEncodingByDefault: true, sendDate: false, _removedConnection: false, _removedContLen: false, _removedTE: false, _contentLength: 0, _hasBody: true, _trailer: '', finished: true, _headerSent: true, socket: TLSSocket { _tlsOptions: [Object], _secureEstablished: true, _securePending: false, _newSessionPending: false, _controlReleased: true, _SNICallback: null, servername: 'api.sendgrid.com', alpnProtocol: false, authorized: true, authorizationError: null, encrypted: true, _events: [Object], _eventsCount: 9, connecting: false, _hadError: false, _handle: [TLSWrap], _parent: null, _host: 'api.sendgrid.com', _readableState: [ReadableState], readable: true, domain: [Domain], _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)]: 81, [Symbol(lastWriteQueueSize)]: 0, [Symbol(timeout)]: null, [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.sendgrid.com', alpnProtocol: false, authorized: true, authorizationError: null, encrypted: true, _events: [Object], _eventsCount: 9, connecting: false, _hadError: false, _handle: [TLSWrap], _parent: null, _host: 'api.sendgrid.com', _readableState: [ReadableState], readable: true, domain: [Domain], _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)]: 81, [Symbol(lastWriteQueueSize)]: 0, [Symbol(timeout)]: null, [Symbol(kBytesRead)]: 0, [Symbol(kBytesWritten)]: 0, [Symbol(connect-options)]: [Object] }, _header: 'PUT /v3/marketing/contacts HTTP/1.1\r\nAccept: application/json, text/plain, */*\r\nContent-Type: application/json\r\nauthorization: Bearer HIDDEN\r\nUser-Agent: axios/0.21.1\r\nHost: api.sendgrid.com\r\nConnection: close\r\nContent-Length: 0\r\n\r\n', _onPendingData: [Function: noopPendingOutput], agent: Agent { domain: null, _events: [Object], _eventsCount: 1, _maxListeners: undefined, defaultPort: 443, protocol: 'https:', options: [Object], requests: {}, sockets: [Object], freeSockets: {}, keepAliveMsecs: 1000, keepAlive: false, maxSockets: Infinity, maxFreeSockets: 256, maxCachedSessions: 100, _sessionCache: [Object] }, socketPath: undefined, timeout: undefined, method: 'PUT', insecureHTTPParser: undefined, path: '/v3/marketing/contacts', _ended: true, res: IncomingMessage { _readableState: [ReadableState], readable: false, domain: [Domain], _events: [Object], _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.sendgrid.com/v3/marketing/contacts', redirects: [] }, aborted: undefined, timeoutCb: null, upgradeOrConnect: false, parser: null, maxHeadersCount: null, _redirectable: Writable { _writableState: [WritableState], writable: true, domain: [Domain], _events: [Object], _eventsCount: 2, _maxListeners: undefined, _options: [Object], _ended: true, _ending: true, _redirectCount: 0, _redirects: [], _requestBodyLength: 0, _requestBodyBuffers: [], _onNativeResponse: [Function], _currentRequest: [Circular], _currentUrl: 'https://api.sendgrid.com/v3/marketing/contacts' }, [Symbol(isCorked)]: false, [Symbol(outHeadersKey)]: [Object: null prototype] { accept: [Array], 'content-type': [Array], authorization: [Array], 'user-agent': [Array], host: [Array] } }, response: { status: 400, statusText: 'Bad Request', headers: { server: 'nginx', date: 'Mon, 28 Dec 2020 01:39:11 GMT', 'content-type': 'application/json', 'content-length': '50', connection: 'close', 'x-amzn-requestid': '7cec2ea8-620a-4096-af97-c58c3f5f12d2', 'access-control-allow-origin': '*', 'access-control-allow-headers': 'AUTHORIZATION, Content-Type, On-behalf-of, x-sg-elas-acl, X-Recaptcha, X-Request-Source', 'x-amz-apigw-id': 'YPWR7E1GvHcFVXg=', 'access-control-allow-methods': 'PUT,DELETE,OPTIONS', 'access-control-expose-headers': 'Link, Location', 'x-amzn-trace-id': 'Root=1-5fe9373f-69accb7255a34e6321797cf3;Sampled=0', 'x-envoy-upstream-service-time': '93', 'referrer-policy': 'strict-origin-when-cross-origin', 'x-content-type-options': 'nosniff', 'x-ratelimit-limit': '200', 'x-ratelimit-remaining': '199', 'x-ratelimit-reset': '49' }, config: { url: 'https://api.sendgrid.com/v3/marketing/contacts', method: 'put', headers: [Object], transformRequest: [Array], transformResponse: [Array], timeout: 0, adapter: [Function: httpAdapter], xsrfCookieName: 'XSRF-TOKEN', xsrfHeaderName: 'X-XSRF-TOKEN', maxContentLength: -1, maxBodyLength: -1, validateStatus: [Function: validateStatus], body: [Object], data: undefined }, request: ClientRequest { domain: [Domain], _events: [Object], _eventsCount: 7, _maxListeners: undefined, output: [], outputEncodings: [], outputCallbacks: [], outputSize: 0, writable: true, _last: true, chunkedEncoding: false, shouldKeepAlive: false, useChunkedEncodingByDefault: true, sendDate: false, _removedConnection: false, _removedContLen: false, _removedTE: false, _contentLength: 0, _hasBody: true, _trailer: '', finished: true, _headerSent: true, socket: [TLSSocket], connection: [TLSSocket], _header: 'PUT /v3/marketing/contacts HTTP/1.1\r\nAccept: application/json, text/plain, */*\r\nContent-Type: application/json\r\nauthorization: Bearer HIDDEN\r\nUser-Agent: axios/0.21.1\r\nHost: api.sendgrid.com\r\nConnection: close\r\nContent-Length: 0\r\n\r\n', _onPendingData: [Function: noopPendingOutput], agent: [Agent], socketPath: undefined, timeout: undefined, method: 'PUT', insecureHTTPParser: undefined, path: '/v3/marketing/contacts', _ended: true, res: [IncomingMessage], aborted: undefined, timeoutCb: null, upgradeOrConnect: false, parser: null, maxHeadersCount: null, _redirectable: [Writable], [Symbol(isCorked)]: false, [Symbol(outHeadersKey)]: [Object] }, data: { errors: [Array] } }, isAxiosError: true, toJSON: [Function: toJSON] }
Turns out axios was failing. I switched to request and it worked like a charm. Here's my final code:
var request = require("request");
var options = { method: 'PUT',
url: 'https://api.sendgrid.com/v3/marketing/contacts',
headers:
{ 'content-type': 'application/json',
authorization: 'Bearer ' + SEND_GRID_KEY},
body:
{ list_ids: [ 'eda0bc01-b098-4366-ad58-8bab03ec9b33' ],
contacts: [
{
"email": e,
"first_name": f,
"last_name": l
}
]
},
json: true };
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
You can test out SendGrid's api and generate code here: https://sendgrid.api-docs.io/v3.0/contacts/add-or-update-a-contact
I am new to NodeJs and with some little NodeJs knowledge I wrote following code to basically get Access Token from Azure Tenant and later on use the same Access Token in the subsequent GET request thru AXIOS to query Azure Resource to which the Client ID Secret has been created (APP registration with Permission granted). I am able to get the Access Token but unfortunately the next GET request Fails with 403 and the same code works fine in Powershell, I am sure I am doing some small mistake in the Get Request header or some other config, Any help ? Following is the Node.Js code:-
const axios = require('axios');
const oauth = require('axios-oauth-client');
const qs = require('qs');
const APP_ID = 'XXXXXXXXXXXXXX';
const APP_SECERET = 'YYYYYYYYY';
const TOKEN_ENDPOINT ='https://login.microsoftonline.com/MyTenantIDGUID/oauth2/token?api-version=1.0';
const MS_GRAPH_SCOPE = 'Data.Read';
const resource ='https://api.loganalytics.io';
var responseval = "";
const postData = {
client_id: APP_ID,
scope: resource,
client_secret: APP_SECERET,
grant_type: 'client_credentials'
};
axios.defaults.headers.post['Content-Type'] =
'application/x-www-form-urlencoded';
axios
.post(TOKEN_ENDPOINT, qs.stringify(postData))
.then(function(response){
//console.log(response);
responseval= 'Bearer ' + response.data.access_token;
console.log ( responseval)
//Instance created below now for Log Analytics calls and passing the Access Token
var baseUrlLogAnl = 'https://api.loganalytics.io/v1/workspaces/MyLogAnalytisWorkspaceGUID/query?query=externalapistatus_CL';
var config ={headers: { 'Authorization': responseval, 'Content-Type': 'application/json' }};
axios.get(baseUrlLogAnl,config)
.then(function(response){
console.log (response)
})
.catch(function (err){
console.log(err.response);
});
})
.catch(function (err){
console.log(err.response);
});
After the execution of above code following is the RESULT and one THING STANDS OUT THAT THE AUTHORIZATION HEADER is MESSED UP with AXIO AGET and CONTENT-TYPE not sure how I can trim it:
Authorization:
'Bearer XXXXXXXXXXXXXXXXXXXXXXXXXXXXKKKKKKKKKKKKKKKKKKKKKKKKKKKSSSSSSSSSSSSSSSSSSSSSSSSZZZZZZZZZZZZZZZZZZZZwQSJ9.eyJhdWQiOiJzcG46MDAwMDAwMDItMDAwMC0wMDAwLWMwMDAtMDAwMDAwMDAwMDAwIiwiaXNzIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvZmEwNjE5ODItYTgxMC00YjQ4LTg5OGYtZGYzZTc2MWNlNzI3LyIsImlhdCI6MTU3ODc1NTg5MCwibmJmIjoxNTc4NzU1ODkwLCJleHAiOjE1Nzg3NTk3OTAsImFpbyI6IjQyTmdZQWdzMjMvdkc3dk5pNTZVVS8zMkVScFNBQT09IiwiYXBwaWQiOiIyNTMyNWY1ZC0yMWI1LTRkMmYtYWE4Ny1jMjYyNmZlZjU2OGQiLCJhcHBpZGFjciI6IjEiLCJpZHAiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC9mYTA2MTk4Mi1hODEwXXXXXXXXXXXXXXXXXXXXXXXXXXXXKKKKKKKKKKKKKKKKKKKKKKKKKKKSSSSSSSSSSSSSSSSSSSSSSSSZZZZZZZZZZZZZZZZZZZZwLThmOGUtM2QyZGFhYzgzZDIzIiwidGVuYW50X3JlZ2lvbl9zY29wZSI6Ik5BIiwidGlkIjoiZmEwNjE5ODItYTgxMC00YjQ4LTg5OGYtZGYzZTc2MWNlNzI3IiwidXRpIjoiaXRxTU5FN3dRMG11aUdySDVzTlBBQSIsInZlciI6IjEuMCJ9.UoOWozRlYhrkQMzFEUGWZJxEueN_2TRlR96SmhZt5M03BRxpqzlazRXaqWAz8qnHQvSCWVdZZtV96UWU_mbMxIzoSnIBGCUvDphUMh0OIJNFTy3-xD6NgAAhhm904-7yF2mnLQu0dFq06DmTNMk0XXXXXXXXXXXXXXXXXXXXXXXXXXXXKKKKKKKKKKKKKKKKKKKKKKKKKKKSSSSSSSSSSSSSSSSSSSSSSSSZZZZZZZZZZZZZZZZZZZZhMbhZeHs7D9U0Xi1Dcw6dHbwbfgn-zThudKTXVfxFxv0KakinWdzGXkLlH_BHvAKrYw',
**'Content-Type': 'application/json',
'User-Agent': 'axios/0.19.1'** },
Here is the FULL OUTPUT:-
Bearer XXXXXXXXXXXXXXXXXXXXXXXXXXXXKKKKKKKKKKKKKKKKKKKKKKKKKKKSSSSSSSSSSSSSSSSSSSSSSSSZZZZZZZZZZZZZZZZZZZZwQSJ9.eyJhdWQiOiJzcG46MDAwMDAwMDItMDAwMC0wMDAwLWMwMDAtMDAwMDAwMDAwMDAwIiwiaXNzIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvZmEwNjE5ODItYTgxMC00YjQ4LTg5OGYtZGYzZTc2MWNlNzI3LyIsImlhdCI6MTU3ODc1NTg5MCwibmJmIjoxNTc4NzU1ODkwLCJleHAiOjE1Nzg3NTk3OTAsImFpbyI6IjQyTmdZQWdzMjMvdkc3dk5pNTZVVS8zMkVScFNBQT09IiwiYXBwaWQiOiIyNTMyNWY1ZC0yMWI1LTRkMmYtYWE4Ny1jMjYyNmZlZjU2OGQiLCJhcHBpZGFjciI6IjEiLCJpZHAiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC9mYTA2MTk4Mi1hODEwXXXXXXXXXXXXXXXXXXXXXXXXXXXXKKKKKKKKKKKKKKKKKKKKKKKKKKKSSSSSSSSSSSSSSSSSSSSSSSSZZZZZZZZZZZZZZZZZZZZwLThmOGUtM2QyZGFhYzgzZDIzIiwidGVuYW50X3JlZ2lvbl9zY29wZSI6Ik5BIiwidGlkIjoiZmEwNjE5ODItYTgxMC00YjQ4LTg5OGYtZGYzZTc2MWNlNzI3IiwidXRpIjoiaXRxTU5FN3dRMG11aUdySDVzTlBBQSIsInZlciI6IjEuMCJ9.UoOWozRlYhrkQMzFEUGWZJxEueN_2TRlR96SmhZt5M03BRxpqzlazRXaqWAz8qnHQvSCWVdZZtV96UWU_mbMxIzoSnIBGCUvDphUMh0OIJNFTy3-xD6NgAAhhm904-7yF2mnLQu0dFq06DmTNMk0XXXXXXXXXXXXXXXXXXXXXXXXXXXXKKKKKKKKKKKKKKKKKKKKKKKKKKKSSSSSSSSSSSSSSSSSSSSSSSSZZZZZZZZZZZZZZZZZZZZhMbhZeHs7D9U0Xi1Dcw6dHbwbfgn-zThudKTXVfxFxv0KakinWdzGXkLlH_BHvAKrYw
{ status: 403,
statusText: 'Forbidden',
headers:
{ date: 'Sat, 11 Jan 2020 15:20:33 GMT',
'content-type': 'application/json; charset=utf-8',
'content-length': '241',
connection: 'close',
'strict-transport-security': 'max-age=15724800; includeSubDomains',
via: '1.1 draft-oms-6f46cfc587-khxdk',
'x-content-type-options': 'nosniff',
'access-control-allow-origin': '*',
'access-control-expose-headers':
'Retry-After,Age,WWW-Authenticate,x-resource-identities,x-ms-status-location',
vary: 'Accept-Encoding' },
config:
{ url:
'https://api.loganalytics.io/v1/workspaces/MYWORKSPACEGUID/query?query=externalapistatus_CL',
method: 'get',
headers:
{ Accept: 'application/json, text/plain, */*',
Authorization:
'Bearer XXXXXXXXXXXXXXXXXXXXXXXXXXXXKKKKKKKKKKKKKKKKKKKKKKKKKKKSSSSSSSSSSSSSSSSSSSSSSSSZZZZZZZZZZZZZZZZZZZZwQSJ9.eyJhdWQiOiJzcG46MDAwMDAwMDItMDAwMC0wMDAwLWMwMDAtMDAwMDAwMDAwMDAwIiwiaXNzIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvZmEwNjE5ODItYTgxMC00YjQ4LTg5OGYtZGYzZTc2MWNlNzI3LyIsImlhdCI6MTU3ODc1NTg5MCwibmJmIjoxNTc4NzU1ODkwLCJleHAiOjE1Nzg3NTk3OTAsImFpbyI6IjQyTmdZQWdzMjMvdkc3dk5pNTZVVS8zMkVScFNBQT09IiwiYXBwaWQiOiIyNTMyNWY1ZC0yMWI1LTRkMmYtYWE4Ny1jMjYyNmZlZjU2OGQiLCJhcHBpZGFjciI6IjEiLCJpZHAiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC9mYTA2MTk4Mi1hODEwXXXXXXXXXXXXXXXXXXXXXXXXXXXXKKKKKKKKKKKKKKKKKKKKKKKKKKKSSSSSSSSSSSSSSSSSSSSSSSSZZZZZZZZZZZZZZZZZZZZwLThmOGUtM2QyZGFhYzgzZDIzIiwidGVuYW50X3JlZ2lvbl9zY29wZSI6Ik5BIiwidGlkIjoiZmEwNjE5ODItYTgxMC00YjQ4LTg5OGYtZGYzZTc2MWNlNzI3IiwidXRpIjoiaXRxTU5FN3dRMG11aUdySDVzTlBBQSIsInZlciI6IjEuMCJ9.UoOWozRlYhrkQMzFEUGWZJxEueN_2TRlR96SmhZt5M03BRxpqzlazRXaqWAz8qnHQvSCWVdZZtV96UWU_mbMxIzoSnIBGCUvDphUMh0OIJNFTy3-xD6NgAAhhm904-7yF2mnLQu0dFq06DmTNMk0XXXXXXXXXXXXXXXXXXXXXXXXXXXXKKKKKKKKKKKKKKKKKKKKKKKKKKKSSSSSSSSSSSSSSSSSSSSSSSSZZZZZZZZZZZZZZZZZZZZhMbhZeHs7D9U0Xi1Dcw6dHbwbfgn-zThudKTXVfxFxv0KakinWdzGXkLlH_BHvAKrYw',
'Content-Type': 'application/json',
'User-Agent': 'axios/0.19.1' },
transformRequest: [ [Function: transformRequest] ],
transformResponse: [ [Function: transformResponse] ],
timeout: 0,
adapter: [Function: httpAdapter],
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
validateStatus: [Function: validateStatus],
data: undefined },
request:
ClientRequest {
_events:
[Object: null prototype] {
socket: [Function],
abort: [Function],
aborted: [Function],
error: [Function],
timeout: [Function],
prefinish: [Function: requestOnPrefinish] },
_eventsCount: 6,
_maxListeners: undefined,
output: [],
outputEncodings: [],
outputCallbacks: [],
outputSize: 0,
writable: true,
_last: true,
chunkedEncoding: false,
shouldKeepAlive: false,
useChunkedEncodingByDefault: false,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
_contentLength: 0,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
socket:
TLSSocket {
_tlsOptions: [Object],
_secureEstablished: true,
_securePending: false,
_newSessionPending: false,
_controlReleased: true,
_SNICallback: null,
servername: 'api.loganalytics.io',
alpnProtocol: false,
authorized: true,
authorizationError: null,
encrypted: true,
_events: [Object],
_eventsCount: 8,
connecting: false,
_hadError: false,
_handle: [TLSWrap],
_parent: null,
_host: 'api.loganalytics.io',
_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)]: 27,
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: null,
[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.loganalytics.io',
alpnProtocol: false,
authorized: true,
authorizationError: null,
encrypted: true,
_events: [Object],
_eventsCount: 8,
connecting: false,
_hadError: false,
_handle: [TLSWrap],
_parent: null,
_host: 'api.loganalytics.io',
_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)]: 27,
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: null,
[Symbol(kBytesRead)]: 0,
[Symbol(kBytesWritten)]: 0,
[Symbol(connect-options)]: [Object] },
_header:
'GET /v1/workspaces/427fa6ee-41cd-4570-b201-ef6cda4bd314/query?query=externalapistatus_CL HTTP/1.1\r\nAccept: application/json, text/plain, */*\r\nAuthorization: Bearer XXXXXXXXXXXXXXXXXXXXXXXXXXXXKKKKKKKKKKKKKKKKKKKKKKKKKKKSSSSSSSSSSSSSSSSSSSSSSSSZZZZZZZZZZZZZZZZZZZZwQSJ9.eyJhdWQiOiJzcG46MDAwMDAwMDItMDAwMC0wMDAwLWMwMDAtMDAwMDAwMDAwMDAwIiwiaXNzIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvZmEwNjE5ODItYTgxMC00YjQ4LTg5OGYtZGYzZTc2MWNlNzI3LyIsImlhdCI6MTU3ODc1NTg5MCwibmJmIjoxNTc4NzU1ODkwLCJleHAiOjE1Nzg3NTk3OTAsImFpbyI6IjQyTmdZQWdzMjMvdkc3dk5pNTZVVS8zMkVScFNBQT09IiwiYXBwaWQiOiIyNTMyNWY1ZC0yMWI1LTRkMmYtYWE4Ny1jMjYyNmZlZjU2OGQiLCJhcHBpZGFjciI6IjEiLCJpZHAiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC9mYTA2MTk4Mi1hODEwXXXXXXXXXXXXXXXXXXXXXXXXXXXXKKKKKKKKKKKKKKKKKKKKKKKKKKKSSSSSSSSSSSSSSSSSSSSSSSSZZZZZZZZZZZZZZZZZZZZwLThmOGUtM2QyZGFhYzgzZDIzIiwidGVuYW50X3JlZ2lvbl9zY29wZSI6Ik5BIiwidGlkIjoiZmEwNjE5ODItYTgxMC00YjQ4LTg5OGYtZGYzZTc2MWNlNzI3IiwidXRpIjoiaXRxTU5FN3dRMG11aUdySDVzTlBBQSIsInZlciI6IjEuMCJ9.UoOWozRlYhrkQMzFEUGWZJxEueN_2TRlR96SmhZt5M03BRxpqzlazRXaqWAz8qnHQvSCWVdZZtV96UWU_mbMxIzoSnIBGCUvDphUMh0OIJNFTy3-xD6NgAAhhm904-7yF2mnLQu0dFq06DmTNMk0XXXXXXXXXXXXXXXXXXXXXXXXXXXXKKKKKKKKKKKKKKKKKKKKKKKKKKKSSSSSSSSSSSSSSSSSSSSSSSSZZZZZZZZZZZZZZZZZZZZhMbhZeHs7D9U0Xi1Dcw6dHbwbfgn-zThudKTXVfxFxv0KakinWdzGXkLlH_BHvAKrYw\r\nContent-Type: application/json\r\nUser-Agent: axios/0.19.1\r\nHost: api.loganalytics.io\r\nConnection: close\r\n\r\n',
_onPendingData: [Function: noopPendingOutput],
agent:
Agent {
_events: [Object],
_eventsCount: 1,
_maxListeners: undefined,
defaultPort: 443,
protocol: 'https:',
options: [Object],
requests: {},
sockets: [Object],
freeSockets: {},
keepAliveMsecs: 1000,
keepAlive: false,
maxSockets: Infinity,
maxFreeSockets: 256,
maxCachedSessions: 100,
_sessionCache: [Object] },
socketPath: undefined,
timeout: undefined,
method: 'GET',
path:
'/v1/workspaces/MYWORKSPACEGUID/query?query=externalapistatus_CL',
_ended: true,
res:
IncomingMessage {
_readableState: [ReadableState],
readable: false,
_events: [Object],
_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: 403,
statusMessage: 'Forbidden',
client: [TLSSocket],
_consuming: false,
_dumped: false,
req: [Circular],
responseUrl:
'https://api.loganalytics.io/v1/workspaces/427fa6ee-41cd-4570-b201-ef6cda4bd314/query?query=externalapistatus_CL',
redirects: [] },
aborted: undefined,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
_redirectable:
Writable {
_writableState: [WritableState],
writable: true,
_events: [Object],
_eventsCount: 2,
_maxListeners: undefined,
_options: [Object],
_redirectCount: 0,
_redirects: [],
_requestBodyLength: 0,
_requestBodyBuffers: [],
_onNativeResponse: [Function],
_currentRequest: [Circular],
_currentUrl:
'https://api.loganalytics.io/v1/workspaces/MyWORKSPACEGUIDhMbhZeHs7D9U0Xi1Dcw6dHbwbfgn-zThudKTXVfxFxv0KakinWdzGXkLlH_BHvAKrYw/query?query=externalapistatus_CL' },
[Symbol(isCorked)]: false,
[Symbol(outHeadersKey)]:
[Object: null prototype] {
accept: [Array],
authorization: [Array],
'content-type': [Array],
'user-agent': [Array],
host: [Array] } },
data:
{ error:
{ message: 'The provided authentication is not valid for this resource',
code: 'InvalidTokenError',
innererror: [Object] } } }
Finally I was able to resolve the issue and was on my end as the RESOURCE and the SCOPE I used in the POSTDATA was incorrect and JESONWEBTOKEN.IO was the site which helped me look at the actual token and identify the issue. Following is tokens I received from powershell and nodejs app which pointed out that aud (scope) was incorrect for nodejs:-
{
"aud": "https://api.loganalytics.io",
"iss": "https://sts.windows.net/fa061982-a810-4b48-898f-df3e761ce727/",
"iat": 1578793728,
"nbf": 1578793728,
"exp": 1578797747,
"aio": "42NgYGDRa+oxtXx52Wj9EhNf792XAA==",
"appid": "AAPP ID",
"appidacr": "1",
"idp": "https://sts.windows.net/fa061982-a810-4b48-898f-df3e761ce727/",
"oid": "07e8e976-d8ca-4090-8f8e-3d2daac83d23",
"roles": [
"Data.Read"
],
"sub": "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZzzzzz",
"tid": "XXXXXXXXXXXXXXXXXXXX",
"uti": "o95V0Bai-kSKJ2OFgL1hAA",
"ver": "1.0",
"jti": "1f30af68-8308-4a1c-ba4e-0b0cbfbc8aa6"
}
{
"aud": "spn:00000002-0000-0000-c000-000000000000",
"iss": "https://sts.windows.net/765a879e-5d61-47f9-9de8-fdca959f52b0/",
"iat": 1578792024,
"nbf": 1578792024,
"exp": 1578797718,
"aio": "42NgYHA+Pz8hku24/PsXFep8f2foAAA=",
"appid": "AAP IDD",
"appidacr": "1",
"idp": "https://sts.windows.net/765a879e-5d61-47f9-9de8-fdca959f52b0/",
"oid": "6e180301-8371-47c8-9551-a1417e67943d",
"sub": "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZzzzzzzz",
"tenant_region_scope": "NA",
"tid": "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
"uti": "08AhiCc4SUuJMVlxefpoAA",
"ver": "1.0",
"jti": "f158f0f6-0399-4536-896d-7e732402654e"
}
Following is the working Code:-
const axios = require('axios');
const request = require('request');
const qs = require('qs');
const APP_ID = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
const APP_SECERET = 'YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY';
const TOKEN_ENDPOINT ='https://login.microsoftonline.com/ZZZZZZZZZZZZZZZZZZZZZZ/oauth2/token?api-version=1.0';
const SCOPE = 'Data.Read';
const resource ='https://api.loganalytics.io';
var responseval = "";
var baseUrlLogAnl2 = 'https://api.loganalytics.io/v1/workspaces/logAnalyticsworkspaceID/query';
const postQuery = {
"query": "AzureActivity | summarize count() by Category"
};
const postData = {
client_id: APP_ID,
scope: 'Data.Read',
client_secret: APP_SECERET,
grant_type: 'client_credentials',
resource: resource
};
axios.defaults.headers.post['Content-Type'] =
'application/x-www-form-urlencoded';
axios
.post(TOKEN_ENDPOINT, qs.stringify(postData))
.then(function(response){
console.log(response['data']);
responseval= 'Bearer ' + response.data.access_token;
axios.defaults.headers.post['Authorization']=responseval;
//axios.defaults.headers.post['Authorization']='Bearer XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXwQSJ9.eyJhdWQiOiJodHRwczovL2FwaS5sb2dhbmFseXRpY3MuaW8iLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC83NjVhODc5ZS01ZDYxLTQ3ZjktOWRlOC1mZGNhOTU5ZjUyYjAvIiwiaWF0IjoxNTc4Nzk5NDYwLCJuYmYiOjE1Nzg3OTk0NjAsImV4cCI6MTU3ODgwMzM2MCwiYWlvIjoiNDJOZ1lEaXk2VnBlNmRrRXRsOE10WEVSZTE3ZUJBQT0iLCJhcHBpZCI6IjI1NjJkYWZmLTcyNGYtNDkyYi1hNWVmLWUzOGFkYTVhNTBiYiIsImFwcGlkYWNyIjoiMSIsImlkcCI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0Lzc2NWE4NzllLTVkNjEtNDdmOS05ZGU4LWZkY2E5NTlmNTJiMC8iLCJvaWQiOiI2ZTE4MDMwMS04MzcxLTQ3YzgtOTU1MS1hMTQxN2U2Nzk0M2QiLCJyb2xlcyI6WyJEYXRhLlJlYWQiXSwic3ViIjoiNmUxODAzMDEtODM3MS00N2M4LTk1NTEtYTE0MTdlNjc5NDNkIiwidGlkIjoiNzY1YTg3OWUtNWQ2MS00N2Y5LTlkZTgtZmRjYTk1OWY1MmIwIiwidXRpIjoidjVYa09qZEV0a0dXWmM1TjR5dGlBQSIsInZlciI6IjEuMCJ9.y5m2qa2LEMm_jYYoXBECkY97bFRPpiI6SIFV1MVcjy4ue-1nVPmNf2DsKkrjFLtmD4EnjlZ7RcbBqFBglb3CssJY12TPEkUk8OMchz4JCUrqQKaamMx8pBZHDPDZEOmh3wZrhnzBloT8O20ICwE9yebEy3n9G4pnIBDobImjrMmNs-B0p0wseyItMFYuEnqvM91PpuPyQl032mmXP4SzX0A7XZCHh6ITiuwfb3-p4JGbUpxAmYkCoEOYkCRTaEPiRslqQSHa8PB6pAhuMLNBifoEFRqOgDlHHqde1sdO-8d7M5VxtNoYMCwtNl6yUB2WFBxRQOy46fZq38hMC-LabQ';
axios
.post(baseUrlLogAnl2, qs.stringify(postQuery))
.then(function(response2){
console.log(response2);
})
.catch(function (err){
console.log(err.response);
});
})
.catch(function (err){
console.log(err.response);
});
I am trying to implement nodejs express passport axios based server-client communication. My goal push files to the server using the terminal. But first I try to implement an authentication service. I have passport auth service which works well when I signing throw postman app.
Also, I have implemented nodejs based client, which try signup to the server but without success.
error:
{ Error: Request failed with status code 400
at createError (/home/gefalko/gepick-devenv/node_modules/axios/lib/core/createError.js:16:15)
at settle (/home/gefalko/gepick-devenv/node_modules/axios/lib/core/settle.js:18:12)
at IncomingMessage.handleStreamEnd (/home/gefalko/gepick-devenv/node_modules/axios/lib/adapters/http.js:201:11)
at emitNone (events.js:111:20)
at IncomingMessage.emit (events.js:208:7)
at endReadableNT (_stream_readable.js:1064:12)
at _combinedTickCallback (internal/process/next_tick.js:139:11)
at process._tickCallback (internal/process/next_tick.js:181:9)
config:
{ adapter: [Function: httpAdapter],
transformRequest: { '0': [Function: transformRequest] },
transformResponse: { '0': [Function: transformResponse] },
timeout: 0,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
validateStatus: [Function: validateStatus],
headers:
{ Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'User-Agent': 'axios/0.18.0',
'Content-Length': 45 },
method: 'post',
url: 'http://localhost:3005/login',
data: '{"username":"gefalko","password":"mypass"}' },
request:
ClientRequest {
domain: null,
_events:
{ socket: [Function],
abort: [Function],
aborted: [Function],
error: [Function],
timeout: [Function],
prefinish: [Function: requestOnPrefinish] },
_eventsCount: 6,
_maxListeners: undefined,
output: [],
outputEncodings: [],
outputCallbacks: [],
outputSize: 0,
writable: true,
_last: true,
upgrading: false,
chunkedEncoding: false,
shouldKeepAlive: false,
useChunkedEncodingByDefault: true,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
_contentLength: null,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
socket:
Socket {
connecting: false,
_hadError: false,
_handle: [Object],
_parent: null,
_host: 'localhost',
_readableState: [Object],
readable: true,
domain: null,
_events: [Object],
_eventsCount: 8,
_maxListeners: undefined,
_writableState: [Object],
writable: false,
allowHalfOpen: false,
_bytesDispatched: 263,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: null,
_server: null,
parser: null,
_httpMessage: [Circular],
[Symbol(asyncId)]: 45,
[Symbol(bytesRead)]: 0 },
connection:
Socket {
connecting: false,
_hadError: false,
_handle: [Object],
_parent: null,
_host: 'localhost',
_readableState: [Object],
readable: true,
domain: null,
_events: [Object],
_eventsCount: 8,
_maxListeners: undefined,
_writableState: [Object],
writable: false,
allowHalfOpen: false,
_bytesDispatched: 263,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: null,
_server: null,
parser: null,
_httpMessage: [Circular],
[Symbol(asyncId)]: 45,
[Symbol(bytesRead)]: 0 },
_header: 'POST /login HTTP/1.1\r\nAccept: application/json, text/plain, */*\r\nContent-Type: application/x-www-form-urlencoded; charset=UTF-8\r\nUser-Agent: axios/0.18.0\r\nContent-Length: 45\r\nHost: localhost:3005\r\nConnection: close\r\n\r\n',
_onPendingData: [Function: noopPendingOutput],
agent:
Agent {
domain: null,
_events: [Object],
_eventsCount: 1,
_maxListeners: undefined,
defaultPort: 80,
protocol: 'http:',
options: [Object],
requests: {},
sockets: [Object],
freeSockets: {},
keepAliveMsecs: 1000,
keepAlive: false,
maxSockets: Infinity,
maxFreeSockets: 256 },
socketPath: undefined,
timeout: undefined,
method: 'POST',
path: '/login',
_ended: true,
res:
IncomingMessage {
_readableState: [Object],
readable: false,
domain: null,
_events: [Object],
_eventsCount: 3,
_maxListeners: undefined,
socket: [Object],
connection: [Object],
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: [Object],
_consuming: true,
_dumped: false,
req: [Circular],
responseUrl: 'http://localhost:3005/login',
redirects: [],
read: [Function] },
aborted: undefined,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
_redirectable:
Writable {
_writableState: [Object],
writable: true,
domain: null,
_events: [Object],
_eventsCount: 2,
_maxListeners: undefined,
_options: [Object],
_ended: true,
_ending: true,
_redirectCount: 0,
_redirects: [],
_requestBodyLength: 45,
_requestBodyBuffers: [],
_onNativeResponse: [Function],
_currentRequest: [Circular],
_currentUrl: 'http://localhost:3005/login' },
[Symbol(outHeadersKey)]:
{ accept: [Array],
'content-type': [Array],
'user-agent': [Array],
'content-length': [Array],
host: [Array] } },
response:
{ status: 400,
statusText: 'Bad Request',
headers:
{ 'x-powered-by': 'Express',
date: 'Wed, 20 Mar 2019 11:52:49 GMT',
connection: 'close',
'content-length': '11' },
config:
{ adapter: [Function: httpAdapter],
transformRequest: [Object],
transformResponse: [Object],
timeout: 0,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
validateStatus: [Function: validateStatus],
headers: [Object],
method: 'post',
url: 'http://localhost:3005/login',
data: '{"username":"gefalko","password":"mypass"}' },
request:
ClientRequest {
domain: null,
_events: [Object],
_eventsCount: 6,
_maxListeners: undefined,
output: [],
outputEncodings: [],
outputCallbacks: [],
outputSize: 0,
writable: true,
_last: true,
upgrading: false,
chunkedEncoding: false,
shouldKeepAlive: false,
useChunkedEncodingByDefault: true,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
_contentLength: null,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
socket: [Object],
connection: [Object],
_header: 'POST /login HTTP/1.1\r\nAccept: application/json, text/plain, */*\r\nContent-Type: application/x-www-form-urlencoded; charset=UTF-8\r\nUser-Agent: axios/0.18.0\r\nContent-Length: 45\r\nHost: localhost:3005\r\nConnection: close\r\n\r\n',
_onPendingData: [Function: noopPendingOutput],
agent: [Object],
socketPath: undefined,
timeout: undefined,
method: 'POST',
path: '/login',
_ended: true,
res: [Object],
aborted: undefined,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
_redirectable: [Object],
[Symbol(outHeadersKey)]: [Object] },
data: 'Bad Request' } }
my client:
const axios = require('axios')
const prompt = require('prompt')
var prompt_attributes = [
{
name: 'username',
validator: /^[a-zA-Z\s\-]+$/,
warning: 'Username is not valid, it can only contains letters, spaces, or dashes'
},
{
name: 'password',
hidden: true
}
]
prompt.start();
prompt.get(prompt_attributes, function (err, result) {
if (err) {
console.log(err);
return 1;
}else {
console.log('Command-line received data:');
const username = result.username
const password = result.password
const config = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}
const reqBody = {
username: username,
password: password
}
axios.post('http://localhost:3005/login', reqBody, config).then(response => {
console.log(response.data);
}).catch(error => {
console.log(error);
})
}
});
also tried 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' but it not help.
server:
import * as express from 'express'
const app = express()
const passport = require('passport')
const LocalStrategy = require('passport-local').Strategy
const bcrypt = require('bcryptjs')
app.use(require('cookie-parser')())
app.use(require('body-parser').urlencoded({ extended: true }))
app.use(passport.initialize())
const port = 3005
/* DATABASE */
import { MongoClient, ObjectID } from 'mongodb'
const mongoUrl = "mongodb://localhost:27017/";
/* AUTHENTICATION */
MongoClient.connect(mongoUrl, async (err, db) => {
const myDB = db.db('mydb')
const Users = myDb.collection('users')
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(user, done) {
done(null, user);
});
passport.use(new LocalStrategy(
function(username, password, done) {
Users.findOne({ username: username }, async function(err, user) {
console.log('USER FROM DB:', user)
console.log('PASS from client', password)
if (err) { return done(err); }
if (!user){
return done(null, false, { message: 'Incorrect username.' });
}
const res = await bcrypt.compare(password, user.password)
return res ? done(null, user) : done(null, false, { message: 'Incorrect username.' })
})
}))
app.post('/login',passport.authenticate('local'), (req, res) =>
{
res.send('logined as ' + req.user.username)
}
)
app.listen(port, () => console.log('http server listening on port '+port+'!'))
})
Also, I found that my request body is parsed strange on the server when it`s come from node client and it is parsed correctly when it's coming from postman.
request body from nodejs axios client:
{ '{"username":"gefalko","password":"mypass"}': '' }
request body from postman client:
{"username":"gefalko","password":"mypass"}
Try this format :
var qs = require('qs');
axios.post('/foo', qs.stringify({ 'bar': 123 } , config);
I've been using the Google Sheets API successfully. I've managed to use the spreadsheets.values.update, and spreadsheets.values.get methods with no errors. Today I've been trying to use the method: spreadsheets.values.append. This method simply appends a row of data to the end of the table. In the developer portal, you can "try this api", and when I do I get a 200 response.
However, when I run exactly the same method (including parameters!) in my NodeJS/Express app I get the error:
"TypeError: Converting circular structure to JSON",
Yet, when I look at the Google Sheet, the data has successfully been appended. This is what my code looks like:
function postValid(req, res) {
const data = req.body;
console.log('received validate post');
sheets.spreadsheets.values.append( {
auth: jwtClient,
spreadsheetId: ssId,
range: 'Valid!A:C',
resource: {
values: [
[1, 2, 3]
]
},
valueInputOption: 'USER_ENTERED',
}, (err, response) => {
if (err) {
res.status(500);
res.send('The API returned an error: ' + err);
}
res.send(response)
})
}
I could ignore the error, as the data does get sent, but I'd really like to know what is causing this circular structure error. How can I go about debugging this?
Like I said the get and update methods with almost the same structure works fine so it isn't the {auth: jwtClient, spreadsheetId: ssId, } parts, and the rest is pretty standard JSON. I just don't get it.
Has anyone run into the same problem?
UPDATE:
I've narrowed down the issue. If I disable Express's JSON body parser, then I can view the full response. Here it is below, you'll see the circular reference is part of the Request, but this request is done via the googleapi methods, is this a possible bug with the googleapi library?
{ status: 200,
statusText: 'OK',
headers:
{ 'content-type': 'application/json; charset=UTF-8',
vary: 'X-Origin, Referer, Origin,Accept-Encoding',
date: 'Tue, 30 Oct 2018 12:22:09 GMT',
server: 'ESF',
'cache-control': 'private',
'x-xss-protection': '1; mode=block',
'x-frame-options': 'SAMEORIGIN',
'alt-svc': 'quic=":443"; ma=2592000; v="44,43,39,35"',
'accept-ranges': 'none',
connection: 'close' },
config:
{ adapter: [Function: httpAdapter],
transformRequest: { '0': [Function: transformRequest] },
transformResponse: { '0': [Function: transformResponse] },
timeout: 0,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: 2147483648,
validateStatus: [Function],
headers:
{ Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/json;charset=utf-8',
Authorization:
<REMOVED>,
'User-Agent': 'google-api-nodejs-client/1.6.1',
'Content-Length': 29 },
method: 'post',
url:
'https://sheets.googleapis.com/v4/spreadsheets/<REMOVED>/values/Valid!A:C:append',
paramsSerializer: [Function],
data: '{"values":[[null,null,null]]}',
params: { valueInputOption: 'USER_ENTERED' } },
request:
ClientRequest {
_events:
{ socket: [Function],
abort: [Function],
aborted: [Function],
error: [Function],
timeout: [Function],
prefinish: [Function: requestOnPrefinish] },
_eventsCount: 6,
_maxListeners: undefined,
output: [],
outputEncodings: [],
outputCallbacks: [],
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: 'sheets.googleapis.com',
alpnProtocol: false,
authorized: true,
authorizationError: null,
encrypted: true,
_events: [Object],
_eventsCount: 8,
connecting: false,
_hadError: false,
_handle: null,
_parent: null,
_host: 'sheets.googleapis.com',
_readableState: [ReadableState],
readable: false,
_maxListeners: undefined,
_writableState: [WritableState],
writable: false,
allowHalfOpen: false,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: undefined,
_server: null,
ssl: null,
_requestCert: true,
_rejectUnauthorized: true,
parser: null,
_httpMessage: [Circular], //<--HERE IS ONE ISSUE
write: [Function: writeAfterFIN],
[Symbol(res)]: [TLSWrap],
[Symbol(asyncId)]: 78,
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: null,
[Symbol(kBytesRead)]: 575,
[Symbol(kBytesWritten)]: 517,
[Symbol(connect-options)]: [Object] },
connection:
TLSSocket {
_tlsOptions: [Object],
_secureEstablished: true,
_securePending: false,
_newSessionPending: false,
_controlReleased: true,
_SNICallback: null,
servername: 'sheets.googleapis.com',
alpnProtocol: false,
authorized: true,
authorizationError: null,
encrypted: true,
_events: [Object],
_eventsCount: 8,
connecting: false,
_hadError: false,
_handle: null,
_parent: null,
_host: 'sheets.googleapis.com',
_readableState: [ReadableState],
readable: false,
_maxListeners: undefined,
_writableState: [WritableState],
writable: false,
allowHalfOpen: false,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: undefined,
_server: null,
ssl: null,
_requestCert: true,
_rejectUnauthorized: true,
parser: null,
_httpMessage: [Circular], //<--Again another problem
write: [Function: writeAfterFIN],
[Symbol(res)]: [TLSWrap],
[Symbol(asyncId)]: 78,
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: null,
[Symbol(kBytesRead)]: 575,
[Symbol(kBytesWritten)]: 517,
[Symbol(connect-options)]: [Object] },
_header:
'POST /v4/spreadsheets/<REMOVED>/values/Valid!A:C:append?valueInputOption=USER_ENTERED HTTP/1.1\r\nAccept: application/json, text/plain, */*\r\nContent-Type: application/json;charset=utf-8\r\nAuthorization: <REMOVED> User-Agent: google-api-nodejs-client/1.6.1\r\nContent-Length: 29\r\nHost: sheets.googleapis.com\r\nConnection: close\r\n\r\n',
_onPendingData: [Function: noopPendingOutput],
agent:
Agent {
_events: [Object],
_eventsCount: 1,
_maxListeners: undefined,
defaultPort: 443,
protocol: 'https:',
options: [Object],
requests: {},
sockets: [Object],
freeSockets: {},
keepAliveMsecs: 1000,
keepAlive: false,
maxSockets: Infinity,
maxFreeSockets: 256,
maxCachedSessions: 100,
_sessionCache: [Object] },
socketPath: undefined,
timeout: undefined,
method: 'POST',
path:
'/v4/spreadsheets/<REMOVED>/values/Valid!A:C:append?valueInputOption=USER_ENTERED',
_ended: true,
res:
IncomingMessage {
_readableState: [ReadableState],
readable: false,
_events: [Object],
_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: 200,
statusMessage: 'OK',
client: [TLSSocket],
_consuming: true,
_dumped: false,
req: [Circular], //<--Again another circular reference
responseUrl:
'https://sheets.googleapis.com/v4/spreadsheets/<REMOVED>/values/Valid!A:C:append?valueInputOption=USER_ENTERED',
redirects: [] },
aborted: undefined,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
_redirectable:
Writable {
_writableState: [WritableState],
writable: true,
_events: [Object],
_eventsCount: 2,
_maxListeners: undefined,
_options: [Object],
_redirectCount: 0,
_redirects: [],
_requestBodyLength: 29,
_requestBodyBuffers: [],
_onNativeResponse: [Function],
_currentRequest: [Circular], //<-- Again!!
_currentUrl:
'https://sheets.googleapis.com/v4/spreadsheets/<REMOVED>/values/Valid!A:C:append?valueInputOption=USER_ENTERED' },
[Symbol(isCorked)]: false,
[Symbol(outHeadersKey)]:
{ accept: [Array],
'content-type': [Array],
authorization: [Array],
'user-agent': [Array],
'content-length': [Array],
host: [Array] } },
data:
{ spreadsheetId: <REMOVED>,
tableRange: 'Valid!A1:C8',
updates:
{ spreadsheetId: <REMOVED>,
updatedRange: 'Valid!A9' } } }
This is indeed coming from Google api response. I also seen it when calling other api such as https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs/query
You have to make sure to call only the relevant part of the response and not attempt to convert it to JSON in order to avoid the circular error messags