This is my first post on SO so I hope I'm doing this correctly. I have a Google Apps Script that is being used with as a web hook to create an integration between two services: YouCanBook.Me and Taleo. The script was published as a web app with the "Anyone, even anonymous" access and was working for weeks. Recently (as of 2/3/14 I believe) it stopped working and now navigating to the public URL results in the following error message:
Google Drive encountered an error. If reloading the page doesn't help, please report the error.
To learn more about Google Drive, please visit our help center.
We're sorry for the inconvenience. Thanks for your help!
- The Google Drive Team
Here is the code for the entire script:
function doGet(request) {
try {
//Get token data from URL parameters
var candidateID = request.parameter.candID;
var requisitionID = request.parameter.reqID;
var interviewType = request.parameter.intType;
var requestType = request.parameter.request;
}
catch(e) {
Logger.log('Unable to capture required parameters. Error message: ' + e);
return;
}
//Get authToken by passing in credentials
var authToken = taleoLogin();
//Get candidate application ID
var candidateApplicationID = getCandidateApplicationID(authToken, candidateID, requisitionID);
//Make PUT request to change candidate's status
taleoSubmit(authToken, candidateID, requisitionID, candidateApplicationID, interviewType, requestType);
//Logout
taleoLogout(authToken);
}
function getCandidateApplicationID(authToken, candidateID, requisitionID) {
//Build API call
var loginURL = 'https://ch.tbe.taleo.net/CH06/ats/api/v1/object/candidateapplication?candidateId=' + candidateID + '&requisitionId=' + requisitionID;
var loginOptions = {
'method' : 'get',
'headers' : {
'cookie' : authToken
},
'contentType' : 'application/json; charset=utf-8'
};
//Make API call
try {
var loginResponse = UrlFetchApp.fetch(loginURL, loginOptions);
if (loginResponse.getResponseCode() == 200) {
Logger.log('Logged in!');
}
else {
Logger.log('Error logging in: ' + loginResponse.getContentText());
}
}
catch (e) {
Logger.log('Could not log in: ' + e);
}
//Return candidate application ID
return candidateApplicationID = JSON.parse(loginResponse).response.candtoreqs[0].candidateapplication.id.toFixed(0);
}
//-----------------------------------//
// Log into Taleo via the REST API //
//-----------------------------------//
function taleoLogin() {
//Build API call
var loginURL = 'https://ch.tbe.taleo.net/CH06/ats/api/v1/login?orgCode=[companyCode]&userName=[username]&password=[password]';
var loginOptions = {
'method' : 'post',
'contentType' : 'application/json'
};
//Make API call
try {
var loginResponse = UrlFetchApp.fetch(loginURL, loginOptions);
if (loginResponse.getResponseCode() == 200) {
Logger.log('Logged in!');
}
else {
Logger.log('Error logging in: ' + loginResponse.getContentText());
}
}
catch (e) {
Logger.log('Could not log in: ' + e);
}
//Return full authToken key
return authToken = 'authToken=' + JSON.parse(loginResponse).response.authToken;
}
//-------------------------------------//
// Log out of Taleo via the REST API //
//-------------------------------------//
function taleoLogout(authToken) {
//Build API call
var logoutURL = 'https://ch.tbe.taleo.net/CH06/ats/api/v1/logout';
var logoutOptions = {
'method' : 'post',
'headers' : {
'cookie' : authToken
},
'contentType' : 'application/json; charset=utf-8'
};
//Make API call
try {
var logoutResponse = UrlFetchApp.fetch(logoutURL, logoutOptions);
if (logoutResponse.getResponseCode() == 200) {
Logger.log('Logged out!');
}
else {
Logger.log('Error logging out: ' + logoutResponse.getContentText());
}
}
catch (e) {
Logger.log('Could not log out: ' + e);
}
}
//-----------------------------------------//
// Submit data to Taleo via the REST API //
//-----------------------------------------//
function taleoSubmit(authToken, candID, reqID, appID, intType, requestType) {
//If phone interview and initial booking
if(intType == 'phone' && requestType == 'booking') {
//Build API call
try {
var submitURL = 'https://ch.tbe.taleo.net/CH06/ats/api/v1/object/candidateapplication/' + appID;
var payload = JSON.stringify({ "candidateapplication" : { "candidateId" : candID, "requisitionId" : reqID, "status" : 5033 }});
var submitOptions = {
'method' : 'put',
'headers' : {
'cookie' : authToken
},
'contentType' : 'application/json; charset=utf-8',
'payload' : payload
};
}
catch (e) {
Logger.log('Error creating API call: ' + e);
}
}
else if(intType == 'final' && requestType == 'booking') {
//Build API call
try {
var submitURL = 'https://ch.tbe.taleo.net/CH06/ats/api/v1/object/candidateapplication/' + appID;
var payload = JSON.stringify({ "candidateapplication" : { "candidateId" : candID, "requisitionId" : reqID, "status" : 5048 }});
var submitOptions = {
'method' : 'put',
'headers' : {
'cookie' : authToken
},
'contentType' : 'application/json; charset=utf-8',
'payload' : payload
};
}
catch (e) {
Logger.log('Error creating API call: ' + e);
}
}
else if(intType == 'phone' && requestType == 'cancel') {
//Build API call
try {
var submitURL = 'https://ch.tbe.taleo.net/CH06/ats/api/v1/object/candidateapplication/' + appID;
var payload = JSON.stringify({ "candidateapplication" : { "candidateId" : candID, "requisitionId" : reqID, "status" : 5032 }});
var submitOptions = {
'method' : 'put',
'headers' : {
'cookie' : authToken
},
'contentType' : 'application/json; charset=utf-8',
'payload' : payload
};
}
catch (e) {
Logger.log('Error creating API call: ' + e);
}
}
else if(intType == 'final' && requestType == 'cancel') {
//Build API call
try {
var submitURL = 'https://ch.tbe.taleo.net/CH06/ats/api/v1/object/candidateapplication/' + appID;
var payload = JSON.stringify({ "candidateapplication" : { "candidateId" : candID, "requisitionId" : reqID, "status" : 5047 }});
var submitOptions = {
'method' : 'put',
'headers' : {
'cookie' : authToken
},
'contentType' : 'application/json; charset=utf-8',
'payload' : payload
};
}
catch (e) {
Logger.log('Error creating API call: ' + e);
}
}
//Make API call
try {
var submitResponse = UrlFetchApp.fetch(submitURL, submitOptions);
if (submitResponse.getResponseCode() == 200) {
Logger.log('Results submitted!');
}
else {
Logger.log('Error submitting results: ' + submitResponse.getContentText());
}
}
catch (e) {
Logger.log('Could not submit results: ' + e);
}
}
Related
When I try my code in postman it's work very well but in my code in visual studio I got a CORS error,
this is my API, using Google Apps Script:
function doPost(e) {
var params = JSON.parse(e.postData.contents);
var action = params.action;
if (action == 'login') {
return handleLogin(params);
} else if (action == 'signup') {
return handleSignup(params);
} else {
return ContentService.createTextOutput("Invalid action");
}
}
function handleLogin(params) {
var username = params.username;
var password = params.password;
var data = sheet.getDataRange().getValues();
for (var i = 0; i < data.length; i++) {
if (data[i][0] == username && data[i][1] == password) {
return ContentService.createTextOutput("Login successful!");
}
}
return ContentService.createTextOutput("Invalid username or password");
}
And here my javascript code, I use the same endpoint, and JSON.stringfy(data),
I do not konw where is the problem,
I install the CORS extension, but the same problem
const data = {action : 'login', username, password};
btn_login.addEventListener('click', getUser);
async function getUser(){
const res = await fetch(api, {
method : 'POST',
mode : 'cors',
cache : 'default',
credentials : 'same-origin',
redirect : 'follow',
referrerPolicy : 'no-referrer',
headers : {
'Content-Type' : 'text/plain'
},
body : JSON.stringify(data)
});
if(res.ok){
console.log(data);
window.location.replace('welcome.html');
}
Thanks for reading.
I'm making a Spoiler Blocker Chrome Extension, and as you can imagine that's been quite a journey...
Right now I have everything sorted out, except the last part. Because of CORS Policy, I have to use a middleman (Cloudflare worker) to access the Razor API from the extension (returns data about entities).
I found an open source code from managing requests with Cors activated for the Cloudflare worker, but it's been days, and I can't get it to send requests as I want it to. I tried predetermining the url to analyze and other stuff, but it just doesn't work.
´´´
The API: https://www.textrazor.com/docs/rest
fetch('https://secret.workers.dev/?https://api.textrazor.com', {
method: 'POST',
body: JSON.stringify({
'extractors': 'entities,sentences',
'text': txt
}),
headers: {
'x-cors-headers': JSON.stringify({
'Content-Type': 'application/x-www-form-urlencoded',
'X-TextRazor-Key': 'secret',
'Accept-Encoding': 'gzip'
})
}
Cloudflare worker code:
addEventListener("fetch", async event=>{
event.respondWith((async function() {
isOPTIONS = (event.request.method == "OPTIONS");
var origin_url = new URL(event.request.url); ```
function fix(myHeaders) {
// myHeaders.set("Access-Control-Allow-Origin", "*");
myHeaders.set("Access-Control-Allow-Origin", event.request.headers.get("Origin"));
if (isOPTIONS) {
myHeaders.set("Access-Control-Allow-Methods", event.request.headers.get("access-control-request-method"));
acrh = event.request.headers.get("access-control-request-headers");
//myHeaders.set("Access-Control-Allow-Credentials", "true");
if (acrh) {
myHeaders.set("Access-Control-Allow-Headers", acrh);
}
myHeaders.delete("X-Content-Type-Options");
}
return myHeaders;
}
var fetch_url = decodeURIComponent(decodeURIComponent(origin_url.search.substr(1)));
var orig = event.request.headers.get("Origin");
var body = event.request;
var remIp = event.request.headers.get("CF-Connecting-IP");
if ((!isListed(fetch_url, blacklist)) && (isListed(orig, whitelist))) {
xheaders = event.request.headers.get("x-cors-headers");
if (xheaders != null) {
try {
xheaders = JSON.parse(xheaders);
} catch (e) {}
}
if (origin_url.search.startsWith("?")) {
recv_headers = {};
for (var pair of event.request.headers.entries()) {
if ((pair[0].match("^origin") == null) && (pair[0].match("eferer") == null) && (pair[0].match("^cf-") == null) && (pair[0].match("^x-forw") == null) && (pair[0].match("^x-cors-headers") == null)) {
recv_headers[pair[0]] = pair[1];
}
}
if (xheaders != null) {
Object.entries(xheaders).forEach((c)=>recv_headers[c[0]] = c[1]);
}
var myHeaders = new Headers();
myHeaders.append('x-textrazor-key', 'secret');
myHeaders.append('Content-Type', 'application/x-www-form-urlencoded');
var myBody = {
extractors: 'entities,sentences',
url: 'https://en.wikipedia.org/wiki/Marty_McFly'
}
newreq = new Request("https://api.textrazor.com", {
method: 'POST',
headers: myHeaders,
body: myBody
})
var response = await fetch(fetch_url,newreq);
var myHeaders = new Headers(response.headers);
cors_headers = [];
allh = {};
for (var pair of response.headers.entries()) {
cors_headers.push(pair[0]);
allh[pair[0]] = pair[1];
}
cors_headers.push("cors-received-headers");
myHeaders = fix(myHeaders);
myHeaders.set("Access-Control-Expose-Headers", cors_headers.join(","));
myHeaders.set("cors-received-headers", JSON.stringify(allh));
if (isOPTIONS) {
var body = null;
} else {
var body = await response.arrayBuffer();
}
var init = {
headers: myHeaders,
status: (isOPTIONS ? 200 : response.status),
statusText: (isOPTIONS ? "OK" : response.statusText)
};
return new Response(body,init);
} else {
var myHeaders = new Headers();
myHeaders = fix(myHeaders);
if (typeof event.request.cf != "undefined") {
if (typeof event.request.cf.country != "undefined") {
country = event.request.cf.country;
} else
country = false;
if (typeof event.request.cf.colo != "undefined") {
colo = event.request.cf.colo;
} else
colo = false;
} else {
country = false;
colo = false;
}
return new Response(
"CLOUDFLARE-CORS-ANYWHERE\n\n" +
"Source:\nhttps://github.com/Zibri/cloudflare-cors-anywhere\n\n" +
"Usage:\n" + origin_url.origin + "/?uri\n\n" +
"Donate:\nhttps://paypal.me/Zibri/5\n\n" +
"Limits: 100,000 requests/day\n" +
" 1,000 requests/10 minutes\n\n" +
(orig != null ? "Origin: " + orig + "\n" : "") +
"Ip: " + remIp + "\n" +
(country ? "Country: " + country + "\n" : "") +
(colo ? "Datacenter: " + colo + "\n" : "") + "\n" +
((xheaders != null) ? "\nx-cors-headers: " + JSON.stringify(xheaders) : ""),
{status: 200, headers: myHeaders}
);
}
} else {
return new Response(
"Create your own cors proxy</br>\n" +
"<a href='https://github.com/Zibri/cloudflare-cors-anywhere'>https://github.com/Zibri/cloudflare-cors-anywhere</a></br>\n" +
"\nDonate</br>\n" +
"<a href='https://paypal.me/Zibri/5'>https://paypal.me/Zibri/5</a>\n",
{
status: 403,
statusText: 'Forbidden',
headers: {
"Content-Type": "text/html"
}
});
}
}
)());
});
Error: "Please specify a TextRazor request."
Thanks in advance!
EDIT:
So, I tried doing the background thingy. But... it doesn't work
background.js after receiving the message from content.js
chrome.runtime.onMessage.addListener(function (msg, sender, value, request, sendResponse) {
if (msg.from == "content") { //get content scripts tab id
contentTabId = sender.tab.id;
var myHeaders = new Headers();
myHeaders.append("x-textrazor-key", "secret");
myHeaders.append("Content-Type", "application/x-www-form-urlencoded");
var urlencoded = new URLSearchParams();
urlencoded.append("text", request.txt);
urlencoded.append("extractors", "entities,entailments");
fetch("https://api.textrazor.com/", {
method: 'POST',
headers: myHeaders,
body: urlencoded,
redirect: 'follow'
}).then((response) => sendResponse(response.json()));
return true; // Will respond asynchronously.
}
content.js after receiving the first message from background (that orders it to look up the text from the page the user is on)
chrome.runtime.sendMessage({
contentScriptQuery: "querySpoiler", txt: txt, messsage: { from: "content" }, responseCallback: function (response) {
request = response.json();
When looking onto it in DevTools, runtime.sendMessage arguments and caller return an error:
TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
at Function.r (:1:83)
at chrome-extension://gbbiidobmakfdibhklcfnadmobpekifb/content.js:61:15
Thanks again!
To make cross-domain requests in an extension, list all hosts you need to access in the extension manifest.
In manifest v3 the key is "host_permissions" (in manifest v2 it is "permissions")
The value will be an array of 1 or more match patterns
The example in original post shows the target host is https://api.textrazor.com. The extension manifest should include the following permission. After adding the permission, and within the extension context, it will be allowed to make requests to the specified host without needing a proxy server.
{
"host_permissions": [
"https://api.textrazor.com/*"
]
}
The * represents a wildcard and means: "match any path that starts with this pattern". You can change the match pattern based on your requirements to include different schemes, subdomains, paths, etc. and add more entries to the value to include more hosts in general. See: https://developer.chrome.com/docs/extensions/mv3/match_patterns for more details and examples of how to define match patterns.
After that, you can perform the API requests, example:
var myHeaders = new Headers();
myHeaders.append("x-textrazor-key", "API_KEY_HERE");
myHeaders.append("Content-Type", "application/x-www-form-urlencoded");
var urlencoded = new URLSearchParams();
urlencoded.append("text", "Spain's stricken Bankia expects to sell off its vast portfolio of industrial holdings that includes a stake in the parent company of British Airways and Iberia.");
urlencoded.append("extractors", "entities,entailments");
fetch("https://api.textrazor.com/", {
method: 'POST',
headers: myHeaders,
body: urlencoded,
redirect: 'follow'
})
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
I'm trying to make script to generate my authentication bearer token for collections. so I don't have to pass token each time and I will Inherit auth from parent. But I don't know where I'm wrong in script, I'm not able to generate token and it giving me error
There was an error in evaluating the Pre-request Script: Error: No data, empty input at 1:1 ^
Here is my script,
var expiresOn = pm.variables.get('ExpiresOn');
if (!expiresOn || new Date(expiresOn) <= new Date()) {
var clientId = '565v7677676vfdrd';
var apiToken = '6565fdvdrdfd';
var request = {
url: 'http://.../auth/token',
method: 'POST',
header: 'Content-Type:application/Json',
body: {
mode: 'application/json',
raw: clientId + apiToken
}
};
}
};
pm.sendRequest(request, function (err, res) {
if (res !== null) {
var json = res.json();
pm.environment.set('Access_Token', json.access_token)
var expiresOn = new Date(0);
expiresOn.setUTCSeconds(json.expires_on);
pm.environment.set('ExpiresOn', expiresOn);
}
});
}
const echoPostRequest = {
url: 'https://example.com/sign_in?client_id=dbdsA8b6V6Lw7wzu1x0T4CLxt58yd4Bf',
method: 'POST',
header: 'Accept: application/json\nUser-Agent: Example/2019.10.31-release (Android 6.0.1; LGE Nexus 5)\nUDID: 1d2c7e65f34b3882f8e42ab8d6a82b4b\nContent-Type: application/json; charset=utf-8\nHost: api-mobile.example.com',
body: {
mode: 'application/json',
raw: JSON.stringify(
{
client_id:'dbdsA8b6V6Lw7wzu1x0T4CLxt58yd4Bf',
client_secret:'aBK1xbehZvrBw0dtVYNY3BuJJOuDFrYs',
auth_method:'password',
create_if_not_found:false,
credentials:{identifier:'username',password:'pass'},
signature:'2:a899cdc0'
})
}
};
var getToken = true;
if (!pm.environment.get('accessTokenExpiry') ||
!pm.environment.get('currentAccessToken')) {
console.log('Token or expiry date are missing')
} else if (pm.environment.get('accessTokenExpiry') <= (new Date()).getTime()) {
console.log('Token is expired')
} else {
getToken = false;
console.log('Token and expiry date are all good');
}
if (getToken === true) {
pm.sendRequest(echoPostRequest, function (err, res) {
console.log(err ? err : res.json());
if (err === null) {
console.log('Saving the token and expiry date')
var responseJson = res.json();
pm.environment.set('currentAccessToken', responseJson.access_token)
var expiryDate = new Date();
expiryDate.setSeconds(expiryDate.getSeconds() + responseJson.expires_in);
pm.environment.set('accessTokenExpiry', expiryDate.getTime());
}
});
}
The above example is a Postman Pre-request script to fetch access_token, and the expire time of the token. I think this example will help you to solve the issue.
Please check the console of the postman
Open Postman Console by pressing Ctrl+Alt+C on Windows (Cmd + Alt+ C on mac)
Syntax error
When running your script I got the following error:
There was an error in evaluating the Pre-request Script: SyntaxError: Unexpected token ';'
It should be something like this in order to run correctly:
var expiresOn = pm.variables.get('ExpiresOn');
if (!expiresOn || new Date(expiresOn) <= new Date()) {
var clientId = '565v7677676vfdrd';
var apiToken = '6565fdvdrdfd';
var request = {
url: 'https://api.domain.io/api/user/session',
method: 'POST',
header: 'Content-Type:application/Json',
body: {
mode: 'application/json',
raw: clientId + apiToken
}
};
}
pm.sendRequest(request, function (err, res) {
if (res !== null) {
var json = res.json();
pm.environment.set('Access_Token', json.access_token)
var expiresOn = new Date(0);
expiresOn.setUTCSeconds(json.expires_on);
pm.environment.set('ExpiresOn', expiresOn);
}
});
Additional options
I used one of these two options to get the bearer token for my collection:
https://gist.github.com/bcnzer/073f0fc0b959928b0ca2b173230c0669#file-postman-pre-request-js
https://community.postman.com/t/how-to-automatically-set-a-bearer-token-for-your-postman-requests/10126/2
A bit modified Sebin Sunny's answer tested with JWT against Azure + resource (/audience).
In headers of request use Authorization {{$randomLoremSentence}}
const echoPostRequest = {
url: 'https://login.microsoftonline.com/{tenant}/oauth2/token',
method: 'POST',
body: {
mode: 'formdata',
formdata: [
{ key: 'grant_type', value: 'client_credentials' },
{ key: 'client_Id', value: '*******************************' },
{ key: 'client_secret', value: '*******************************' },
{ key: 'resource', value: '*******************************' }
]
}
};
var getToken = true;
var token = pm.globals.get('$randomLoremSentence') || '';
var exp = pm.globals.get('accessTokenExpiry');
var exps = new Date(exp);
if (token.indexOf('Bearer ') < 0) {
console.log('Token or expiry date are missing')
} else if (exp <= (new Date()).getTime()) {
console.log('Token is expired - ${exps}')
} else {
getToken = false;
console.log(`Token ${token.substr(0,10)}...${token.substr(-5)} and expiry ${exps} date are all good`);
}
if (getToken === true) {
pm.sendRequest(echoPostRequest, function (err, res) {
console.log(err ? err : res.json());
if (err === null) {
var responseJson = res.json();
var token = responseJson.access_token;
console.log(`Saving the token ${token.substr(0,5)}...${token.substr(-5)} and expiry ${exps} date`)
pm.globals.set('$randomLoremSentence', "Bearer " + token);
var expiryDate = new Date(responseJson.expires_on * 1000);
pm.globals.set('accessTokenExpiry', expiryDate.getTime());
}
});
}
//pm.globals.set('$randomLoremSentence', 0); // reset token 2 test
I’m trying to create a JS service on WebOS 3.0 followed the official documentation.
I can send data between JS service and my application, but sometimes the JS service does not respond to the request if it’s idled for like 20 seconds. I’ve also tried to increase the timeout per this. Unfortunately, it does not seemed to be working.
Here’s my code
Application Side
const request = webOS.service.request('luna://com.myapp.service', {
method : 'fetch',
parameters : { url, method, headers, body },
onFailure : (err) => {
reject(err)
},
onSuccess : (s) => {
console.log('request success', s)
},
onComplete : (resp) => {
const isSuccess = resp.data.status >= 200 && resp.data.status < 400
var payload = {
json : () => Promise.resolve(JSON.parse(resp.data.body)),
ok : isSuccess,
headers : resp.data.headers,
status : resp.data.status,
error : isSuccess
? null
: resp.data.body
}
resolve(payload)
}
})
})
Service Side
var Service = require('webos-service')
var service = new Service('com.myapp.service')
service.register('fetch', function(message) {
var payload = message.payload
if(!payload) {
message.respond({
returnValue : true,
error : 'Message does not have a `payload`'
})
return
}
var url = payload.url,
headers = payload.headers,
method = payload.method,
body = payload.body
var request = http.request({
method : method,
hostname : URL.parse(url).hostname,
path : URL.parse(url).path,
headers : headers,
}, function(res) {
var data = ''
res.on('data', function(chunk) { data+=chunk })
res.on('end', function() {
message.respond({
returnValue : true,
data : {
status : res.statusCode,
statusText : res.statusMessage,
headers : res.headers,
body : data,
}
})
})
})
request.on('error', function(err) {
console.log(err)
message.respond({
returnValue : true,
error : err
})
})
request.end()
})
I recently wrote a JavaScript application for LG Smart-TVs and would highly recommend using socket.io for all communication between client and server.
It's a bit tricky getting it to work initially, but works flawlessly.
Here's how the connection looks ...
var socket = io("http://10.27.101.95");
idUser = getCookie("idUser"); // Retrieved from device and set to cookie.
// ┌────────────────────────────────────────────────────────────────┐
// │ Socket.io: Connect/Emit │
socket.on('connect', function() {
socket.emit("addUser", {
"idUser": idUser
});
reconnectHideData = false;
});
// Hide data if server cannot be reached.
var reconnectCount = 0;
var reconnectHideData = false;
socket.on('reconnect_error', function() {
if (reconnectCount < 10 && reconnectHideData == false) {
// console.log( '---=== Reconnect attempt: ' + reconnectCount + ' ===---' );
setTimeout(function(){
reconnectCount++;
}, 3000);
}
if (reconnectCount == 10 && reconnectHideData == false) {
// console.log( '-----===== Cleared Data =====-----' );
$('.section ').addClass(' u-hide ');
$('.greeting').addClass(' u-hide ');
reconnectHideData = true;
reconnectCount = 0;
}
else {
return;
}
});
// Necessary to trigger event to be emitted server side.
setInterval(function(){
socket.emit("reqData");
}, 5000);
// └────────────────────────────────────────────────────────────────┘
After that, it's all a matter of processing and formatting the returned data.
I'm following these tutorial:
https://developer.wordpress.com/docs/oauth2/
https://developer.wordpress.com/docs/wpcc/
https://github.com/Automattic/wpcom-connect-examples/blob/master/express.js/app.js
So I setup Meteor.loginWithWordpresscom with the following code:
Accounts.oauth.registerService('wordpresscom');
if (Meteor.isClient) {
Meteor.loginWithWordpresscom = function(options, callback) {
// support a callback without options
if (! callback && typeof options === "function") {
callback = options;
options = null;
}
var credentialRequestCompleteCallback = Accounts.oauth.credentialRequestCompleteHandler(callback);
Wordpresscom.requestCredential(options, credentialRequestCompleteCallback);
};
} else {
Accounts.addAutopublishFields({
forLoggedInUser: ['services.wordpresscom'],
forOtherUsers: ['services.wordpresscom.username']
});
}
And then I request credential with the following code:
Wordpresscom = {};
Wordpresscom.requestCredential = function (options, credentialRequestCompleteCallback) {
if (!credentialRequestCompleteCallback && typeof options === 'function') {
credentialRequestCompleteCallback = options;
options = {};
}
var config = ServiceConfiguration.configurations.findOne({service: 'wordpresscom'});
if (!config) {
credentialRequestCompleteCallback && credentialRequestCompleteCallback(
new ServiceConfiguration.ConfigError());
return;
}
var credentialToken = Random.secret();
var loginStyle = OAuth._loginStyle('wordpresscom', config, options);
var loginUrl =
'https://public-api.wordpress.com/oauth2/authorize' +
'?client_id=' + config.clientId +
'&redirect_uri=http://localhost:3000/connected' +
'&response_type=token' +
'&grant_type=authorization_code' +
'&scope=global'
OAuth.launchLogin({
loginService: "wordpresscom",
loginStyle: loginStyle,
loginUrl: loginUrl,
credentialRequestCompleteCallback: credentialRequestCompleteCallback,
credentialToken: credentialToken,
popupOptions: {width: 900, height: 450}
});
};
At the server, I request accessToken and identity with following code:
Wordpresscom = {};
OAuth.registerService('wordpresscom', 2, null, function(query) {
var accessToken = getAccessToken(query);
var identity = getIdentity(accessToken);
return {
serviceData: {
id: identity.ID,
accessToken: OAuth.sealSecret(accessToken),
email: identity.email,
username: identity.username,
displayName: identity.display_name,
avatar: identity.avatar_URL
},
options: {profile: {
name: identity.display_name,
displayName: identity.display_name,
avatar: identity.avatar_URL
}}
};
});
var getAccessToken = function (query) {
var config = ServiceConfiguration.configurations.findOne({service: 'wordpresscom'});
if (!config)
throw new ServiceConfiguration.ConfigError();
var response;
try {
response = HTTP.post(
"https://public-api.wordpress.com/oauth2/token", {
params: {
code: query.code,
client_id: config.clientId,
client_secret: OAuth.openSecret(config.secret),
redirect_uri: 'http://localhost:3000/connected',
grant_type: 'authorization_code'
}
});
} catch (err) {
throw _.extend(new Error("Failed to complete OAuth handshake with WordPress.com. " + err.message),
{response: err.response});
}
if (response.data.error) { // if the http response was a json object with an error attribute
throw new Error("Failed to complete OAuth handshake with WordPress.com. " + response.data.error);
} else {
console.log('getAccessToken');
return response.data.access_token;
}
};
var getIdentity = function (accessToken) {
console.log('getIdentity');
try {
return HTTP.get(
"https://public-api.wordpress.com/rest/v1/me", {
headers: {
/*"User-Agent": userAgent,*/
"Authorization": 'Bearer ' + accessToken
},
params: {access_token: accessToken}
}).data;
} catch (err) {
throw _.extend(new Error("Failed to fetch identity from WordPress.com. " + err.message),
{response: err.response});
}
};
Wordpresscom.retrieveCredential = function(credentialToken, credentialSecret) {
return OAuth.retrieveCredential(credentialToken, credentialSecret);
};
When I fire Meteor.loginWithWordpresscom popup window show up to ask user whether to approve or deny my app with this link http://localhost:3000/connected?code=a8kiRGwRPC
I get code a8kiRGwRPC to request access_token
After I approve, it redirect to http://localhost:3000/connected#access_token=w%5EQ7CFcvZQx3t%28OjspIs84v13BsbyUGROzrYh3%23aiLJQ%25NB%2AZ7jMjNX2%29m7%23t5J4&expires_in=1209600&token_type=bearer&site_id=0
Just like that. No new user stored in Meteor.users database
Any help would be appreciated
Thanks