Below is the code to make post request:
export class AuthenticationService {
private authUrl = 'http://localhost:5555/api/auth';
constructor(private http: HttpClient) {}
login(username: string, password: string) {
console.log(username);
let data = {'username': username, 'password': password};
const headers = new HttpHeaders ({'Content-Type': 'application/json'});
//let options = new RequestOptions({headers: headers});
return this.http.post<any>(this.authUrl, JSON.stringify({data: data}), {headers: headers});
}
}
Below is the node code where I am trying to access the request body, Request body is null in the helow case:
router.use(express.static(path.join('webpage')));
var bodyParser = require('body-parser');
router.use(bodyParser.urlencoded({ extended: true }));
router.post('/api/auth', function(req, res){
console.log(req.body);
console.log(req.body.username + ":" + req.body.password);
});
Request was sent successfully using below method:
Angular:
login(username: string, password: string) {
const data = {'username': username, 'password': password};
const config = { headers: new HttpHeaders().set('Content-Type', 'application/json') };
return this.http.post<any>(this.authUrl, data, config)
.map(res => {
console.log(res);
if (res.user === true) {
localStorage.setItem('currentUser', res.user);
localStorage.setItem('role', res.role);
}
return res;
},
err => {
return err;
}
);
}
Node
var bodyParser = require('body-parser');
router.use(bodyParser.json());
router.post('/api/auth', function(req, res){
console.log("request received " + req.body);
});
if the body payload contains application/x-www-form-urlencoded values then post methods expects string value like below const body = 'client_id=ApiClient&grant_type=password&scope=UiApi&username=' + username +'&password=' +password;
getLoginCredentialsAccessToken(username: string, password: string)
: Observable<AccessToken>{
const headersList = new HttpHeaders({ 'Content-Type': 'application/x-www-form-urlencoded' });
const body = 'client_id=ApiClient&grant_type=password&scope=UiApi&username=' + username +'&password=' +password;
return this.http.post<AccessToken>(this.tokenEndpoint, body, { headers: headersList});
}
Related
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
in Node.js, I am trying to send a POST request with Axios to Twilio and send an SMS message to my phone. But I am getting an 'error: Authentication Error - No credentials provided ? Here is the code:
const body = {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
Body: 'hi from vsc',
To: toNumber,
From: fromNumber,
};
const headers = {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
Authorization: `Basic ${accountSID}:${authToken}`,
};
exports.axios = () => axios.post(`https://api.twilio.com/2010-04-01/Accounts/${accountSID}/Messages.json`, body, headers).then((res) => {
console.log(res, 'res');
}).catch((err) => {
console.log(err);
});
I also tried to use the same parameters with POSTMAN and the POST request is successful. I also tried to encode my authorization username and password to Base 64, but with no success.
I wrote to Twilio customer help but haven`t received any replies yet.
Axios makes an auth option available that takes an object with username and password options. You can use this with the username set to your account SID and password set to your auth token.
The headers object should be sent as the headers parameter of a config object in the third parameter to axios.post. Like so:
const params = new URLSearchParams();
params.append('Body','Hello from vcs');
params.append('To',toNumber);
params.append('From',fromNumber);
const headers = {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
};
exports.axios = () => axios.post(
`https://api.twilio.com/2010-04-01/Accounts/${accountSID}/Messages.json`,
params,
{
headers,
auth: {
username: accountSID,
password: authToken
}
}
}).then((res) => {
console.log(res, 'res');
}).catch((err) => {
console.log(err);
});
Headers is actually a field of config, try something like this:
const config = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
Authorization: `Basic ${accountSID}:${authToken}`,
}
}
axios.post(URL, data, config).then(...)
Or this (general example calling a Twilio endpoint)
const axios = require('axios');
const roomSID = 'RM1...';
const participantSID = 'PA8...';
const ACCOUNT_SID = process.env.ACCOUNT_SID;
const AUTH_TOKEN = process.env.AUTH_TOKEN;
const URL = "https://insights.twilio.com/v1/Video/Rooms/"+roomSID+"/Participants/"+participantSID;
axios({
method: 'get',
url: URL,
auth: {
username: ACCOUNT_SID,
password: AUTH_TOKEN
}
})
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.log(error);
});
Working code:
const params = new URLSearchParams();
params.append('Body','Hello from vcs');
params.append('To',toNumber);
params.append('From',fromNumber);
exports.axios = () => axios.post(
`https://api.twilio.com/2010-04-01/Accounts/${accountSID}/Messages.json`,
params,
{
auth: {
username: accountSID,
password: authToken,
},
},
).then((res) => {
console.log(res, 'res');
}).catch((err) => {
console.log(err);
});
The previous solutions did not work for me. I encountered either the Can't find variable: btoa error or A 'To' phone number is required..
Using qs worked for me:
import qs from 'qs';
import axios from 'axios';
const TWILIO_ACCOUNT_SID = ""
const TWILIO_AUTH_TOKEN = ""
const FROM = ""
const TO = ""
const sendText = async (message: string) => {
try {
const result = await axios.post(
`https://api.twilio.com/2010-04-01/Accounts/${TWILIO_ACCOUNT_SID}/Messages.json`,
qs.stringify({
Body: message,
To: TO,
From: FROM,
}),
{
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
auth: {
username: TWILIO_ACCOUNT_SID,
password: TWILIO_AUTH_TOKEN,
},
},
);
console.log({result});
} catch (e) {
console.log({e});
console.log({e: e.response?.data});
}
};
I'm trying to use 2checkout REST API
https://knowledgecenter.2checkout.com/API-Integration/REST_5.0_Reference#/introduction/authentication/json-encoded-requests
Here's a snippet of how i try to request
const axios = require('axios')
const moment = require('moment')
const saltedMd5 = require('salted-md5');
let now = moment().format('YYYY-MM-DD HH:MM:SS')
let vendorCode = '250207358831'
let toHash = vendorCode.length + vendorCode + now.length + now
let salt = '~0CSl)!M#4rZ|zX5QR&s'
const hash = saltedMd5(toHash, salt)
axios.get('https://api.2checkout.com/rest/5.0/subscriptions/?Email=customer%40email.com&AvangateCustomerReference=1234567&ExternalCustomerReference=abcdefg&Page=1&Limit=10&PurchasedBefore=2015-12-29&PurchasedAfter=2015-01-15&ExpireBefore=2016-05-22&ExpireAfter=2015-07-23&Type=regular&Aggregate=false', {
headers: {
'X-Avangate-Authentication': `code="${vendorCode}" date="${now}" hash="${hash}"`,
'Content-Type': 'application/json',
'Accept': 'application/json'
}
}).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
It returns status code 500. Does someone know how to retrieve subscriptions using the 2checkout API?
class TwoCheckoutService {
tco: {
domain:string;
apiUrl: string,
apiUser:string,
apiPass:string,
sellerId:string,
privateKey:string,
secretKey:string,
demo:boolean,
};
constructor(private userService: UserService) {
this.tco = {=
apiUrl: 'https://api.2checkout.com/rest/6.0',
apiUser: "=",
apiPass: "=",
sellerId: "=",
privateKey: "=",
secretKey: "=",
demo: true,
// sandbox: false
};
}
private async _getAuthHeaders(): Promise<{[key:string]: string}> {
var code = this.tco.sellerId;
var date = moment().utc().format('YYYY-MM-DD hh:mm:ss');
var stringToHash = code.toString().length + code + date.toString().length + date;
var hmac = crypto.createHmac('md5', this.tco.secretKey);
hmac.update(stringToHash, 'utf8');
var hash = hmac.digest('hex')
var authHeader = `code="${code}" date="${date}" hash="${hash}"`
return {
'X-Avangate-Authentication': authHeader,
'Content-Type': 'application/json',
'Accept': 'application/json'
};
}
async getProducts() {
var url = this.tco.apiUrl + '/products/';
var headers = await this._getAuthHeaders();
console.log(headers);
var res = await Axios.get(url, {
headers: headers,
params: {
'Limit': 10,
'Page': 1,
},
validateStatus: (status)=>true
});
if(res.status === 200) return res.data;
return {
error: true,
data: res.data,
url: url,
headers: headers
}
}
}
#This is an example in typescript nodejs
##requirements
crypto
axios
2checkout api credentials
I need to call an API from my Angular Node application.For that i have to pass username and password along with header request.How to pass parameters?
I tried below code
From Angular service,
checkUserApi(url: string): Observable<any> {
const headers = new HttpHeaders()
.set('Authorization', 'my-auth-token')
.set('Content-Type', 'application/json')
.set('userName','prismtest')
.set('password','12345678');
return this.http.post('/upload/checkUserApi/', { headers })
.map((response: Response) => {
console.log(response);
return response;
})
}
In Node,
router.post('/checkUserApi',function(req,res,next){
var proxyUrl = 'http://cors-anywhere.herokuapp.com/';
Request.post({
"headers": { "userName": "prismtest","password":"12345678" },
"url": proxyUrl+"https://example.com",
"body": {}
}, (error, response, body) => {
if(error) {
return console.log(error);
}
res.send(response);
});
});
You can pass the form parameters as the second attribute to post request:
checkUserApi(url: string): Observable<any> {
const headers = new HttpHeaders()
.set('Authorization', 'my-auth-token')
.set('Content-Type', 'application/json');
return this.http.post('/upload/checkUserApi/', {username: 'prismtest', password: '123'}, { headers })
.map((response: Response) => {
console.log(response);
return response;
})
}
You can do it by using interceptors which is Angular Service.
this should be helpfull :How to pass a param to HttpInterceptor?
Can you try below code following
/* SERVICE ANGULAR*/
import {Injectable} from '#angular/core';
import {HttpClient, HttpHeaders} from '#angular/common/http';
import {Observable,of} from 'rxjs';
import { map,catchError } from 'rxjs/operators';
import {User} from '../_models';
const httpOptions = {
headers:new HttpHeaders({'Content-Type':'application/json'})
};
const API_URL = "http://localhost/app/api";
#Injectable({
providedIn:'root',
})
export class UserService{
constructor(private http:HttpClient){}
/**
* POST LOGIN USER
*/
login(user: any) {
return this.http.post<any>(API_URL+"/login", user,httpOptions)
.pipe(map(user => {
return user;
}));
}
}
/*NODEJS*/
/* 1) install $ npm install body-parser --save*/
var bodyParser = require('body-parser');
app.use(bodyParser.json()); // support json encoded bodies
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies */
/ POST http://localhost:8080/api/users
// parameters sent with
app.post('/api/login', function(req, res) {
var user_id = req.body.id;
var token = req.body.token;
var geo = req.body.geo;
res.send(user_id + ' ' + token + ' ' + geo);
});
Can you seen : Use ExpressJS to Get URL and POST Parameters
Login State Angular + Laravel
const headerOptions = {
headers : new HttpHeaders({
'Constent-Type' : 'application/json',
'Authorization : 'you token here'
})
}
http.post('you action', {body Params}, headerOptions, function(res){
console.log('your respose is ', res);
})
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