Google OAuth2 Service Account HTTP/REST Authentication - node.js

I am attempting to make a access token request using the documentation found below:
https://developers.google.com/identity/protocols/OAuth2ServiceAccount
I am leveraging the jsrsasign library to generate my JWT
For clarity I am deploying the code to Parse.com cloud code, everything executes fine with exception of the failed response from Google.
jsrsasign [http://kjur.github.io/jsrsasign/]
https://kjur.github.io/jsrsasign/api/symbols/KJUR.jws.JWS.html#.sign
Parse.Cloud.define("testBase", function(request, response) {
var createJWT = function(){
var creds = {
private_key_id: "532ca15e518a0<foobar>74dd81d48a9cb24",
private_key: "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcw<foobar>QCzxcu5ae3l7JXT\nZzI2kHA3lYay/2DIcC4KXqQWCMejQacRlFROftfnqRrf9qmEewH/0TMSMlOFt0G6\n9hjznhOHu3rxZcAxuK5bh7UnmoUWYksdtb+6VgCGF9Z5piTASrLxssILAUqY6EjT\nHKp3IQk6aqMqe6NhymCS/o0K9NvGA98znpv28ilD9dd5HXhfTdeGm7PDkZGIXIbR\nG+sQN8+tW46N1PaYnoz8iNGfvGk2Y04WDC2HJ590z4DAk41jbcWtnZnr/UyIJzTq\nTBjCWwAcF0qwSabf/mlWSf2S7DeCZKYNveMSN7F6meI8uYshuVoNqd95u/KGfQ4q\ns+wMdF3tAgMBAAECggEAcQ2MhnelUhisSBv3qfS/fVUdNmf/d02ExqSpz+mJkpNw\n+08qjYqbQGZKLloyVMv+f+ARm/nmKIsMXQTywBHC+nLeZ/yzFxGrJIh9VgCIfYEm\n9/IaNpZrEejfyfS/2+WeDv15pe4T+YDqe0jlsrEl2oTBQ7ApGRBqF0bZb/B4XVd3\ngZ6kya+UL5j+PSgNcaGABUfj7pDXZIRmVnWJxXSYhvvbD+SrXIhBMS3wXZ+vka1J\nkW/bwhzayu9/nI24WN7pALxf6/zB3Ewyoj5n1pnxbkvBMcK+PBiX9yAPvfH5cGQF\nQZx86L11maYpWHxufrbclow16qZHP41O+1eePGbIgQKBgQDmOY04z02RIMX32I7k\nbtokmG8qDnR8iu8dkLSRU4Ib7ZPzIBpjg9neaRib9A2fPVjyuxjvsUbob11BuklZ\nGCMu9SFV8w4LpUQ3clL+kBiGncuSmBfZWbj7uqLuzsNeeu3pihVTlkeWeagTAR36\nhi8K4IVQi5SmPF2dPiw9A8oXkQKBgQDH5j1smCFu9d+F2HIwDFXsW1wlyWhtcgfV\n70uCXdImnU25pJDARLX8vqaZp0KHIPmXLgUV/sU3oAX9NRdgV56bJTo7vwO3DATM\ntK14h7GZCKSYniOqX+3FdweNyn89qlHeAkZdvCZhGX5rOVXtlhpey7Eu8fQnPs1S\nbxd1EXRKnQKBgH+m1Yj0WLvpghskdkZuuIGmC600Cp6rol2wSI5z0SaPGoOp/zfC\neeD6QOzn602qBFHCL9dnYjuq0/iHw/ekjI2S2YMAm38Vibd8qkv/tbmecKu9rSuU\nth7No13qQyV138ioCZ8pKlRi7DBtZCPultLfHsxEOI3b1sRDHuBN45YhAoGAGbKe\niNxRx/rxvjoiC806KoVgJjdrJk63dSgrE9pNzssAF/Jw7Van8pLrxer7oXV6wJWY\n78ftwIXg3zk5BRieeiFiCBY5OwnfgBVmC42eJic3SatiuF9WqMDxhqfWja3ckmbG\ndvxeDrOBTfVz93QJddBHudo+4eCv8n33jQQuZ/0CgYEAsYXmQWOUndqBaZgho3ZV\njrRFmwiwiqJ1hqJdflBXbKlTQOpqea8QoQOQqyeMVQ1X7x3rDcHbhFSbd65GJT5j\n65B/OXrBpIBhb5u0/x6ytJhlM9sPRIL+G/m5QYnBY7dcQo6jlKxTUKHPEV/mwT2m\nt/ZxkAmz/9DKWFKtDc4ZshI\u003d\n-----END PRIVATE KEY-----\n",
client_email: "<foobar>-t18b3hrkab6urireblm8kb4kt45c92a2#developer.gserviceaccount.com",
client_id: "<foobar>-t18b3hrkab6urireblm8kb4kt45c92a2.apps.googleusercontent.com",
type: "service_account"
};
var header = {
alg:"RS256",
typ:"JWT"
};
var data = {
iss: creds.client_email,
scope:"https://www.googleapis.com/auth/analytics.readonly",
aud:"https://www.googleapis.com/oauth2/v3/token",
exp: KJUR.jws.IntDate.get('now + 1hour'),
iat: KJUR.jws.IntDate.get('now')
};
console.log("Preparing to generate RS256 JWT");
var sJWT = KJUR.jws.JWS.sign("RS256", JSON.stringify(header), JSON.stringify(data), creds.private_key);
console.log("RS256 JWT generation complete:");
console.log(sJWT)
return sJWT;
}
console.log("############################## ")
try{
console.log("Preparing assertion...")
var jwt = createJWT()
console.log("Assertion: "+jwt);
var options = {
method: 'POST',
headers: {
'Content-Type':'application/x-www-form-urlencoded'
},
url: "https://www.googleapis.com/oauth2/v3/token",
params: {
grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
assertion: jwt
}
};
console.log("------------------------");
console.log(options);
console.log("------------------------");
Parse.Cloud.httpRequest(options).done(function(rsp){
var r = (_.isString(rsp.text)) ? JSON.parse(rsp.text) : rsp.text;
console.log("Reponse from Google:");
console.log(rsp)
// console.log({ body: req.body, params: req.params, query: req.query, o: options, r: r });
// res.send(r);
response.success(r);
}).fail(function(err){
// console.error(err);
console.error("Failed response from Google:")
console.error(err.text)
response.error(err);
});
}catch(err){
console.error(err);
response.error(err);
}
});
The console output:
I2015-06-29T19:42:17.315Z]##############################
I2015-06-29T19:42:17.316Z]Preparing assertion...
I2015-06-29T19:42:17.317Z]Preparing to generate RS256 JWT
I2015-06-29T19:42:17.401Z]RS256 JWT generation complete:
I2015-06-29T19:42:17.402Z]eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI2MDQ4Mjk2NTQ1MzktdDE4YjNocmthYjZ1cmlyZWJsbThrYjRrdDQ1YzkyYTJAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvYW5hbHl0aWNzLnJlYWRvbmx5IiwiYXVkIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vb2F1dGgyL3YzL3Rva2VuIiwiZXhwIjoxNDM1NjEwNTM3LCJpYXQiOjE0MzU2MDY5Mzd9.nGbApndzwwtadeL2Jr2zU__JZrBZ6tYGJ17sTDksiSsFRXop_6CFAsV7fkXC6Xd-Nf3KfYzNuqGzLciQTzc9AhGNFTk_aUXU-ndMbYiVh3EpTkBI0olkS5rkgnmm3Q_yfaOswkyvMwE12RvgTTjymVzHGTZ8xC_x22Ep1n07Ap3TQn3WpeFeJlHciiwcxMTG7TsxAvHEgaqLzZ79feFmZanj6pqEH1kfZeJUQK1n3bwKtU92qpPn7b4dFtJs8I7El62HLExU1B2l7qdSyp4CRxmUPViUfWykElDZeqDzPoX38QEMDmmTgCYUXna7wJB6O0qC3aJpxkCAmzPCDkXkZQ
I2015-06-29T19:42:17.403Z]Assertion: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI2MDQ4Mjk2NTQ1MzktdDE4YjNocmthYjZ1cmlyZWJsbThrYjRrdDQ1YzkyYTJAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvYW5hbHl0aWNzLnJlYWRvbmx5IiwiYXVkIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vb2F1dGgyL3YzL3Rva2VuIiwiZXhwIjoxNDM1NjEwNTM3LCJpYXQiOjE0MzU2MDY5Mzd9.nGbApndzwwtadeL2Jr2zU__JZrBZ6tYGJ17sTDksiSsFRXop_6CFAsV7fkXC6Xd-Nf3KfYzNuqGzLciQTzc9AhGNFTk_aUXU-ndMbYiVh3EpTkBI0olkS5rkgnmm3Q_yfaOswkyvMwE12RvgTTjymVzHGTZ8xC_x22Ep1n07Ap3TQn3WpeFeJlHciiwcxMTG7TsxAvHEgaqLzZ79feFmZanj6pqEH1kfZeJUQK1n3bwKtU92qpPn7b4dFtJs8I7El62HLExU1B2l7qdSyp4CRxmUPViUfWykElDZeqDzPoX38QEMDmmTgCYUXna7wJB6O0qC3aJpxkCAmzPCDkXkZQ
I2015-06-29T19:42:17.404Z]------------------------
I2015-06-29T19:42:17.405Z]{"method":"POST","headers":{"Content-Type":"application/x-www-form-urlencoded"},"url":"https://www.googleapis.com/oauth2/v3/token","params":{"grant_type":"urn:ietf:params:oauth:grant-type:jwt-bearer","assertion":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI2MDQ4Mjk2NTQ1MzktdDE4YjNocmthYjZ1cmlyZWJsbThrYjRrdDQ1YzkyYTJAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvYW5hbHl0aWNzLnJlYWRvbmx5IiwiYXVkIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vb2F1dGgyL3YzL3Rva2VuIiwiZXhwIjoxNDM1NjEwNTM3LCJpYXQiOjE0MzU2MDY5Mzd9.nGbApndzwwtadeL2Jr2zU__JZrBZ6tYGJ17sTDksiSsFRXop_6CFAsV7fkXC6Xd-Nf3KfYzNuqGzLciQTzc9AhGNFTk_aUXU-ndMbYiVh3EpTkBI0olkS5rkgnmm3Q_yfaOswkyvMwE12RvgTTjymVzHGTZ8xC_x22Ep1n07Ap3TQn3WpeFeJlHciiwcxMTG7TsxAvHEgaqLzZ79feFmZanj6pqEH1kfZeJUQK1n3bwKtU92qpPn7b4dFtJs8I7El62HLExU1B2l7qdSyp4CRxmUPViUfWykElDZeqDzPoX38QEMDmmTgCYUXna7wJB6O0qC3aJpxkCAmzPCDkXkZQ"}}
I2015-06-29T19:42:17.406Z]------------------------
I2015-06-29T19:42:17.504Z]Failed response from Google:
I2015-06-29T19:42:17.506Z]{
"error": "invalid_grant",
"error_description": "Bad Request"
}
Final Solution:
Import the google service account credentials json file (renamed to google-service-account-credentials.js), generate jwt, apply jwt as body in the Parse.Request instead of params.
var fs = require('fs');
var moment = require('moment');
var _ = require('underscore');
var KJUR = require("cloud/lib/jsrsasign/npm/lib/jsrsasign.js");
var googleServiceAccountCredentials = JSON.parse(fs.readFileSync('cloud/google-service-account-credentials.js'));
var createJWT = function(args, credentials){
var header = {
alg:"RS256",
typ:"JWT"
};
var now = moment().unix();
var defaults = {
iss: credentials.client_email,
scope:"https://www.googleapis.com/auth/analytics.readonly",
aud:"https://www.googleapis.com/oauth2/v3/token",
exp: now + (15*60),
iat: now
};
var data = {};
_.extend(data, defaults, args);
var sJWT = KJUR.jws.JWS.sign("RS256", JSON.stringify(header), JSON.stringify(data), credentials.private_key );
return sJWT;
};
Parse.Cloud.define("testBase", function(request, response) {
try{
var now = moment().unix();
var options = {
method: 'POST',
headers: {
'Content-Type':'application/x-www-form-urlencoded'
},
url: "https://www.googleapis.com/oauth2/v3/token",
body: {
grant_type: encodeURI("urn:ietf:params:oauth:grant-type:jwt-bearer"),
assertion: createJWT({
exp: now + (60*60),
iat: now
}, googleServiceAccountCredentials)
}
};
Parse.Cloud.httpRequest(options).done(function(rsp){
var r = (_.isString(rsp.text)) ? JSON.parse(rsp.text) : rsp.text;
console.log("Reponse from Google:");
console.log(r.access_token);
console.log(r.expires_in);
console.log(r.token_type);
response.success(r);
}).fail(function(err){
console.error("Failed response from Google:")
console.error(err.text)
response.error(err);
});
}catch(err){
console.error(err);
response.error(err);
}
});

Use body instead of params in your request options

Related

Paytm Payment Gateway - Returning Invalid payment mode for UPI

I'm trying to integrate Paytm's Payment gateway [Custom Checkout]. However, while UPI Integration, after sending the request i'm getting Invalid payment mode response code on the callback url.
As suggested in documentation,
First i'm calling the Initiate Transaction API for token.
initialise(order, res, next) {
const paytmParams = {};
paytmParams.body = {
requestType: 'Payment',
mid: paytm.mid,
websiteName: paytm.website,
orderId: order.orderId,
callbackUrl: paytm.callbackUrl,
txnAmount: {
value: order.amount,
currency: 'INR',
},
userInfo: {
custId: order.custId,
},
};
const paytmChecksum = PaytmChecksum.generateSignature(paytmParams.body, paytm.merchantKey);
paytmChecksum.then(function (checksum) {
paytmParams.head = {
signature: checksum,
};
const post_data = JSON.stringify(paytmParams);
const options = {
hostname: paytm.host,
port: 443,
path: `/theia/api/v1/initiateTransaction?mid=${paytm.mid}&orderId=${order.orderId}`,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': post_data.length,
},
};
let response = '';
const post_req = https.request(options, function (post_res) {
post_res.on('data', function (chunk) {
response += chunk;
});
post_res.on('end', function () {
const result = JSON.parse(response);
if (result.body.resultInfo.resultStatus === 'S') {
res.status(200).json({ token: result.body.txnToken, orderId: order.orderId });
} else {
next(new ApiError(httpStatus.EXPECTATION_FAILED, result.body.resultInfo.resultMsg));
}
});
});
post_req.write(post_data);
post_req.end();
});
}
After this i'm taking the user's vpa and validating that via Validate VPA API.
validateUpi(data, res, next) {
const paytmParams = {};
paytmParams.body = {
vpa: data.upiId,
};
paytmParams.head = {
tokenType: 'TXN_TOKEN',
token: data.token,
};
const post_data = JSON.stringify(paytmParams);
const options = {
hostname: paytm.host,
port: 443,
path: `/theia/api/v1/vpa/validate?mid=${paytm.mid}&orderId=${data.orderId}`,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': post_data.length,
},
};
let response = '';
const post_req = https.request(options, function (post_res) {
post_res.on('data', function (chunk) {
response += chunk;
});
post_res.on('end', function () {
const result = JSON.parse(response);
if (result.body.resultInfo.resultStatus === 'S') {
res.status(200).json({
action: `https://${paytm.host}/theia/api/v1/processTransaction?mid=${paytm.mid}&orderId=${data.orderId}`,
params: {
mid: paytm.mid,
orderId: data.orderId,
txnToken: data.token,
paymentMode: 'UPI',
payerAccount: data.upiId,
},
});
} else {
next(new ApiError(httpStatus.EXPECTATION_FAILED, result.body.resultInfo.resultMsg));
}
});
});
post_req.write(post_data);
post_req.end();
}
After the successfull response, i'm returning the action URL and the params to the front end to create the form and post it in front end.
const res = await paymentAPI.validateUpiId(body);
paymentHelpers.createFormAndSubmit(res.action, res.params, 'redirect');
export const createFormAndSubmit = (url: string, data: any, type = "") => {
const form = document.createElement("form");
form.method = "POST";
form.action = url;
form.type = type;
Object.keys(data).forEach((key) => {
const input = document.createElement("input");
input.type = "text";
input.name = key;
input.value = data[key];
form.appendChild(input);
});
document.body.appendChild(form);
form.submit();
document.body.removeChild(form);
};
But after this form is being submitted, i'm getting redirected to callbackUrl with error message
http://localhost:3000/callback/paytm?retryAllowed=false&errorMessage=Invalid%20payment%20mode&errorCode=317

Axios and Oauth1.0 - 'status: 400, Bad Request'

I'm new on Nodejs and all the modules related with Node. I've been trying to use axios for send a Oauth1.0 Autorization signature, but i'm getting: response: { status: 400, statusText: 'Bad Request', ...}
import { BASE_URL } from '../../../config/config.js';
import axios from 'axios';
import status from 'http-status';
import OAuth from 'oauth-1.0a';
import { createHmac } from 'crypto';
import dotenv from 'dotenv';
dotenv.config();
const CONSUMERKEY = process.env.consumer_key;
const CONSUMERSECRET = process.env.consumer_secret;
const TOKENKEY = process.env.access_token;
const TOKENSECRET = process.env.token_secret;
export const oauth = OAuth({
consumer: {
key: CONSUMERKEY,
secret: CONSUMERSECRET,
},
signature_method: 'HMAC-SHA1',
hash_function(base_string, key) {
return createHmac('sha1', key)
.update(base_string)
.digest('base64')
},
})
export const token = {
key: TOKENKEY,
secret: TOKENSECRET,
}
const doRequest = async (query) => {
const request_data = {
url: `${BASE_URL}`,
method: 'GET',
params: { q: `${query}` },
};
const authHeader = oauth.toHeader(oauth.authorize(request_data, token));
return await axios.get(request_data.url, request_data.params, { headers: authHeader });
};
const searchU = async (term) => {
return await doRequest(`${term}`);
};
export const userS = async (req, res, next) => {
try {
const { query } = req;
const { data } = await searchU(query.q);
const string = JSON.stringify(data);
const Rs = JSON.parse(string);
const response = {
code: 1,
message: 'sucess',
response: Rs
};
res.status(status.OK).send(response);
} catch (error) {
next(error);
if (error.response){
console.log("Response: ");
console.log(error.response);
} else if(error.request){
console.log("Request: ");
console.log(error.request)
} else if(error.message){
console.log("Message: ");
console.log(error.message)
}
}
};
I've been also trying the solution given On this post: but there's no way I can make this work, no idea what i could be doing wron...
When i try the following code (see below), using Request module (which is deprecated) works well, but I really need to do it with Axios...
const request_data = {
url: `${BASE_URL}`,
method: 'GET',
params: { q: `${query}` },
};
const authHeader = oauth.toHeader(oauth.authorize(request_data, token));
request(
{
url: request_data.url,
method: request_data.method,
form: request_data.params,
headers: authHeader,
},
function(error, response, body) {
console.log(JSON.parse(body));
}
)
Any thoughts on what I'm doing wrong on this?? Thank you very much!!
Refer to the following link for the Request Config for Axios. I believe you need to have the query params after the header in the axios.get()
Axios Request Config
Try, the following and see how it goes:-
return await axios.get(request_data.url, { headers: authHeader }, request_data.params);

Google Api Service Account "error":"invalid_grant","error_description":"Invalid JWT Signature."

I am pretty new with google api, but I already spent 6 hours with this error. So I want to access my google drive files with a service account. But I always get this error:
{"error":"invalid_grant","error_description":"Invalid JWT Signature."}
This is the method I create and send the JWT in NodeJs:
const privateKeyFile = require("./user.json");
const base64url = require("base64url");
const jsonwebtoken = require("jsonwebtoken");
const querystring = require("querystring");
const request = require("request");
// HEADER
let header = { alg: "RS256", typ: "JWT" };
let encodedH = base64url(JSON.stringify(header));
// CLAIM SET
let exp = parseInt(Date.now() / 1000) + 60 * 20;
// issue time
let iat = parseInt(Date.now() / 1000);
let claimset = {
iss: "*********#*******.iam.gserviceaccount.com",
scope: "https://www.googleapis.com/auth/drive",
aud: "https://oauth2.googleapis.com/token",
exp: exp,
iat: iat,
};
let encodedCs = base64url(JSON.stringify(claimset));
// create signiture
let signitureBase = encodedH + "." + encodedCs;
jsonwebtoken.sign(
signitureBase,
privateKeyFile.private_key,
{
algorithm: "RS256",
header: header,
},
function (err, signature) {
request.post(
"https://oauth2.googleapis.com/token",
{
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: querystring.encode({
grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
assertion: signitureBase + "." + base64url(signature),
}),
},
function (error, response) {
console.log(error);
console.log(response);
}
);
}
);
Thanks in advance!
I believe your goal as follows.
You want to retrieve the access token from the Google service account using Node.js.
For this, how about this answer?
Pattern 1:
In this pattern, crypto and request are used.
Sample script:
const privateKeyFile = require("./user.json");
const cryptor = require("crypto");
const request = require("request");
const scopes = ["https://www.googleapis.com/auth/drive"];
const url = "https://www.googleapis.com/oauth2/v4/token";
const header = {
alg: "RS256",
typ: "JWT",
};
const now = Math.floor(Date.now() / 1000);
const claim = {
iss: privateKeyFile.client_email,
scope: scopes.join(" "),
aud: url,
exp: (now + 3600).toString(),
iat: now.toString(),
};
const signature =
Buffer.from(JSON.stringify(header)).toString("base64") +
"." +
Buffer.from(JSON.stringify(claim)).toString("base64");
var sign = cryptor.createSign("RSA-SHA256");
sign.update(signature);
const jwt = signature + "." + sign.sign(privateKeyFile.private_key, "base64");
request(
{
method: "post",
url: url,
body: JSON.stringify({
assertion: jwt,
grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
}),
},
(err, res, body) => {
if (err) {
console.log(err);
return;
}
console.log(body);
}
);
Result:
When you run the script, the following result is retrieved.
{
"access_token": "###",
"expires_in": ####,
"token_type": "Bearer"
}
Pattern 2:
In this pattern, googleapis is used.
Sample script:
const privateKeyFile = require("./user.json");
const { google } = require("googleapis");
let jwtClient = new google.auth.JWT(
privateKeyFile.client_email,
null,
privateKeyFile.private_key,
["https://www.googleapis.com/auth/drive"]
);
jwtClient.authorize((err) => {
if (err) console.log(err);
});
jwtClient.getRequestHeaders().then((auth) => {
console.log(auth);
});
Result:
When you run the script, the following result is retrieved.
{
"Authorization": "Bearer ###"
}
Reference:
googleapis for Node.js

Twitter search API getting errors

I am trying to collect twitter search results.
I am using twitter search API with Nodejs.
Started with "quick start" given in twitter api site https://developer.twitter.com/en/docs/labs/recent-search/quick-start, but I am keeping get errors from my request.
this is my code:
const https = require('https');
const request = require('request');
const util = require('util');
const get = util.promisify(request.get);
const post = util.promisify(request.post);
const consumer_key = 'xxxxxxx'; // Add your API key here
const consumer_secret = 'xxxxxx'; // Add your API secret key here
const bearerTokenURL = new URL('https://api.twitter.com/oauth2/token');
const searchURL = new URL('https://api.twitter.com/labs/2/tweets/search');
async function bearerToken (auth) {
const requestConfig = {
url: bearerTokenURL,
auth: {
user: consumer_key,
pass: consumer_secret,
},
form: {
grant_type: 'client_credentials',
},
};
const response = await post(requestConfig);
return JSON.parse(response.body).access_token;
}
(async () => {
let token;
const query = 'obama';
const maxResults = 10;
try {
// Exchange your credentials for a Bearer token
token = await bearerToken({consumer_key, consumer_secret});
} catch (e) {
console.error(`Could not generate a Bearer token. Please check that your credentials are correct and that the Filtered Stream preview is enabled in your Labs dashboard. (${e})`);
process.exit(-1);
}
const requestConfig = {
url: searchURL,
qs: {
query: query,
max_results: maxResults,
format: 'compact',
},
auth: {
bearer: token,
},
headers: {
'User-Agent': 'LabsRecentSearchQuickStartJS',
},
json: true,
};
try {
const res = await get(requestConfig);
console.log(res.statusCode);
console.log(res);
if (res.statusCode !== 200) {
throw new Error(res.json);
return;
}
console.log(res.json);
} catch (e) {
console.error(`Could not get search results. An error occurred: ${e}`);
process.exit(-1);
}
})();
my error:
body: {
errors: [ [Object] ],
title: 'Invalid Request',
detail: 'One or more parameters to your request was invalid.',
type: 'https://api.twitter.com/labs/2/problems/invalid-request' }, [Symbol(kCapture)]: false } Could not get search results. An
error occurred: Error
There's a bug in this script which we need to fix. If you remove the line format: 'compact', then this will work - that parameter is no longer valid in Labs v2.

Got error when trying to get access token in nodejs using azure, AADSTS50058: A silent sign-in request was sent but no user is signed in

I am trying to implement azure login in nodejs scheduler app, and then want to upload file to share point.
First i need to login, then get access token,refresh token, admin access token etc.
When i try to get access token , i got error like this.
Here no use of any front end.
URL= 'https://login.microsoftonline.com/' + TENANT_ID + '/oauth2/token',
Status Code Error: 400 -
"{"error":"invalid_grant","error_description":"AADSTS50058: A silent sign-in request was sent but no user is signed in.\r\nTrace ID: 05db5c6a-155c-4870-9bca-a518b5931900\r\nCorrelation ID: 1e8372d0-c1ba-4070-88d7-597e9cb5cb2c\r\nTimestamp: 2019-08-14 12:04:42Z","error_codes":[50058],"timestamp":"2019-08-14 12:04:42Z","trace_id":"05db5c6a-155c-4870-9bca-a518b5931900","correlation_id":"1e8372d0-c1ba-4070-88d7-597e9cb5cb2c","error_uri":"https://login.microsoftonline.com/error?code=50058\"}"
Here the code
async function init(parsedBody) {
var jwtToken = await sharepointAuth.getJWTToken(parsedBody);
console.log("jwtToken:",jwtToken)
const config = {
JWK_URI: appConstants.JWK_URI,
ISS: appConstants.ISS,
AUD: appConstants.conf.AUD,
};
console.log(config)
await azureJWT.verify(jwtToken, config).then(async () => {
console.log("----------------------------------")
var fileName = 'analytics.min.js';
var filePath = './public/analytics.min.js';
var userAccessToken = await getAccessToken(jwtToken);
console.log("userAccessToken:", userAccessToken);
var accessTokenObj = await sharepointAuth.getAdminAccessToken();
accessToken = accessTokenObj.access_token;
console.log("accessToken:", accessToken)
fs.readFile(filePath, { encoding: null }, function (err, data) {
const relativeUrl = web/GetFolderByServerRelativeUrl('${selectedFolderName}');
const SHAREPOINT_HEADER = {
'Authorization': Bearer ${accessToken},
"Content-Type": application/json;odata=verbose,
'Accept': 'application/json;odata=verbose',
}
const options = {
method: "POST",
uri: ${SHAREPOINT_URI}${relativeUrl}/Files/add(url='${fileName}',overwrite=true),
headers: SHAREPOINT_HEADER,
body: data
};
console.log(options)
rp(options)
.then(() => {
// POST succeeded...
console.log('File uploaded!');
})
.catch((error) => {
// POST failed...
console.log("File Upload Error: ", error.toString());
});
});
});
}
const request = require("request");
const endpoint = "https://login.microsoftonline.com/tenentId/oauth2/token";
const requestParams = {
grant_type: "client_credentials",
client_id: "ClientId",
client_secret: "Secret",
resource: "ClientId"
};
request.post({ url: endpoint, form: requestParams }, function (err, response, body) {
if (err) {
console.log("error");
}
else {
console.log("Body=" + body);
let parsedBody = JSON.parse(body);
if (parsedBody.error_description) {
console.log("Error=" + parsedBody.error_description);
}
else {
console.log("parsedBody : " + parsedBody);
console.log("Access Token=" + parsedBody.access_token);
init(parsedBody);
}
}
});
function getAccessToken(jwtToken) {
return new Promise(async (resolve) => {
try {
const options = {
method: 'POST',
uri: URL,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
formData: {
grant_type: appConstants.OTB_GRANT_TYPE,
client_id: appConstants.conf.AUD,
client_secret: appConstants.conf.CLIENT_SECRET,
resource: appConstants.OTB_RESOURCE_URI2,
client_assertion_type: appConstants.OTB_CLIENT_ASSERTION_TYPE,
requested_token_use: appConstants.OTB_REQ_TOKEN_USE,
scope: appConstants.OTB_SCOPE,
assertion: jwtToken,
},
};
console.log("options:", options)
await rp(options)
.then(async (parsedBody) => {
// POST succeeded...
const result = JSON.parse(parsedBody);
console.log("****************************************** result", result)
refreshToken = result.refresh_token;
resolve(result.access_token);
})
.catch((error) => {
// POST failed...
console.log('getAccessTokenRequestError: ', error.toString());
resolve(appConstants.ACCESS_TOKEN_ERROR);
});
} catch (error) {
console.log('getAccessTokenRequestPromiseError: ', error.toString());
resolve(appConstants.MIDDLEWARE_ERROR);
}
});
}
I have no idea about azure login without front end. I want to login in azure and upload file to share point in scheduler app in node.
First i need to login by using client id and secret. then i got bearer token. then i want to get access token by using bearer token. At that time i get error like this.
AADSTS50058: A silent sign-in request was sent but no user is signed in
Why don't you get the access token this way(client credentials flow)?
const request = require("request");
const endpoint =
"https://login.microsoftonline.com/{tenant}/oauth2/token";
const requestParams = {
grant_type: "client_credentials",
client_id: "",
client_secret: "",
resource: "https://mydomain.sharepoint.com"
};
request.post({ url: endpoint, form: requestParams }, function(
err,
response,
body
) {
if (err) {
console.log("error");
} else {
console.log("Body=" + body);
let parsedBody = JSON.parse(body);
if (parsedBody.error_description) {
console.log("Error=" + parsedBody.error_description);
} else {
console.log("Access Token=" + parsedBody.access_token);
}
}
});
If you need the access token which contains login user message, you can use ROPC flow.
const request = require("request");
const endpoint =
"https://login.microsoftonline.com/{tenant}/oauth2/token";
const requestParams = {
grant_type: "password",
username: "",
password: "",
client_id: "",
resource: "https://mydomain.sharepoint.com"
};
request.post({ url: endpoint, form: requestParams }, function(
err,
response,
body
) {
if (err) {
console.log("error");
} else {
console.log("Body=" + body);
let parsedBody = JSON.parse(body);
if (parsedBody.error_description) {
console.log("Error=" + parsedBody.error_description);
} else {
console.log("Access Token=" + parsedBody.access_token);
}
}
});

Resources