I'm trying to access the authorization server that i have in okta, so i can see the users profile (in this case the user first name and favorite color )from the alexa skill but keep getting an error.
i just want to retrieve the user info (claims in okta name/color).i already set up the account linking in alexa, so there is probably an easier approach since the clientID and clientSecret is already configured.
Error message
{
"error": "access_denied",
"error_description": "The requested feature is not enabled in this environment."
}
is this something i have to enable in okta? can i do it in okta developers console with the free tier?
Code
function validateAccessToken(token, callback) {
console.log("token: ", token);
//start
var clientId = '**okta open id connect client id generated earlier**';
var clientSecret = '**okta open id connect client secret generated earlier**';
var auth = "Basic " + new Buffer.from(clientId + ":" + clientSecret).toString("base64");
var https = require('https');
var tokenParam = '?token=' + token;
var tokenHintParam = '&token_type_hint=access_token';
var tokenQuery = tokenParam + tokenHintParam;
var optionspost = {
host: '**your okta org**.oktapreview.com',
port: 443,
path: '/oauth2/**your authorization server id**/v1/introspect' + tokenQuery,
method: 'POST',
headers: {
'Authorization': auth,
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
}
};
console.log(optionspost);
var jsonResponseUser;
var firstName;
var favoriteColor;
console.log("pre Req Post");
var jsonObject;
var reqPost = https.request(optionspost, function(res) {
console.log("statusCode: ", res.statusCode);
// uncomment it for header details
console.log("headers: ", res.headers);
res.on('data', function(d) {
console.info('POST result:\n');
process.stdout.write(d);
console.info('\n\nPOST completed');
jsonResponseUser = JSON.parse(d);
firstName = jsonResponseUser['FirstNameClaim'];
favoriteColor = jsonResponseUser['FavoriteColorClaim'];
let responseVoice = firstName + '\'s Favorite Color is ' + favoriteColor;
console.log("responseVoice :" + responseVoice);
callback(responseVoice);
});
});
reqPost.end();
reqPost.on('error', function(e) {
console.error(e);
});
}
const FavoriteColorHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest' &&
request.intent.name === 'FavoriteColorIntent';
},
handle(handlerInput) {
let favoriteColor = '';
let request = handlerInput.requestEnvelope.request;
console.log(handlerInput.requestEnvelope.context.System.user.accessToken);
let token = handlerInput.requestEnvelope.context.System.user.accessToken;
return new Promise((resolve) => {
validateAccessToken(token, function(result) {
// setTimeout(1000000000000);
console.log("inside Opp Handler, responseVoice: " + result);
resolve(handlerInput.responseBuilder.speak(result).getResponse());
});
});
},
};
Related
I have an api post end point which would update a customer's information in dynamodb. It is set to authenticate using AWS_IAM. I am getting 403 from my lambda when calling this api. I have allowed execute-api:Invoke permission to the api for the role lambda uses. I see in this post that I need to create a canonical request. I was able to come up with the below code and I still get a 403. I can't figure out what is missing and wish if a different eye can spot the problem. Please help!
"use strict";
const https = require("https");
const crypto = require("crypto");
exports.handler = async (event, context, callback) => {
try {
var attributes = {
customerId: 1,
body: { firstName: "abc", lastName: "xyz" }
};
await updateUsingApi(attributes.customerId, attributes.body)
.then((result) => {
var jsonResult = JSON.parse(result);
if (jsonResult.statusCode === 200) {
callback(null, {
statusCode: jsonResult.statusCode,
statusMessage: "Attributes saved successfully!"
});
} else {
callback(null, jsonResult);
}
})
.catch((err) => {
console.log("error: ", err);
callback(null, err);
});
} catch (error) {
console.error("error: ", error);
callback(null, error);
}
};
function sign(key, message) {
return crypto.createHmac("sha256", key).update(message).digest();
}
function getSignatureKey(key, dateStamp, regionName, serviceName) {
var kDate = sign("AWS4" + key, dateStamp);
var kRegion = sign(kDate, regionName);
var kService = sign(kRegion, serviceName);
var kSigning = sign(kService, "aws4_request");
return kSigning;
}
function updateUsingApi(customerId, newAttributes) {
var request = {
partitionKey: `MY_CUSTOM_PREFIX_${customerId}`,
sortKey: customerId,
payLoad: newAttributes
};
var data = JSON.stringify(request);
var apiHost = new URL(process.env.REST_API_INVOKE_URL).hostname;
var apiMethod = "POST";
var path = `/stage/postEndPoint`;
var { amzdate, authorization, contentType } = getHeaders(host, method, path);
const options = {
host: host,
path: path,
method: method,
headers: {
"X-Amz-Date": amzdate,
Authorization: authorization,
"Content-Type": contentType,
"Content-Length": data.length
}
};
return new Promise((resolve, reject) => {
const req = https.request(options, (res) => {
if (res && res.statusCode !== 200) {
console.log("response from api", res);
}
var response = {
statusCode: res.statusCode,
statusMessage: res.statusMessage
};
resolve(JSON.stringify(response));
});
req.on("error", (e) => {
console.log("error", e);
reject(e.message);
});
req.write(data);
req.end();
});
}
function getHeaders(host, method, path) {
var algorithm = "AWS4-HMAC-SHA256";
var region = "us-east-1";
var serviceName = "execute-api";
var secretKey = process.env.AWS_SECRET_ACCESS_KEY;
var accessKey = process.env.AWS_ACCESS_KEY_ID;
var contentType = "application/x-amz-json-1.0";
var now = new Date();
var amzdate = now
.toJSON()
.replace(/[-:]/g, "")
.replace(/\.[0-9]*/, "");
var datestamp = now.toJSON().replace(/-/g, "").replace(/T.*/, "");
var canonicalHeaders = `content-type:${contentType}\nhost:${host}\nx-amz-date:${amzdate}\n`;
var signedHeaders = "content-type;host;x-amz-date";
var payloadHash = crypto.createHash("sha256").update("").digest("hex");
var canonicalRequest = [
method,
path,
canonicalHeaders,
signedHeaders,
payloadHash
].join("/n");
var credentialScope = [datestamp, region, serviceName, "aws4_request"].join(
"/"
);
const sha56 = crypto
.createHash("sha256")
.update(canonicalRequest)
.digest("hex");
var stringToSign = [algorithm, amzdate, credentialScope, sha56].join("\n");
var signingKey = getSignatureKey(secretKey, datestamp, region, serviceName);
var signature = crypto
.createHmac("sha256", signingKey)
.update(stringToSign)
.digest("hex");
var authorization = `${algorithm} Credential=${accessKey}/${credentialScope}, SignedHeaders=${signedHeaders}, Signature=${signature}`;
return { amzdate, authorization, contentType };
}
I'm new to NodeJs and I'm having the problem with response.on('end') I still can't find out the method to send the data I got from the response to the client side.
exports.getCheckoutSession = catchAsync(async (req, res, next) => {
const uuidv1 = require('uuid/v1');
const https = require('https');
const tour = await Tour.findById(req.params.tourId);
console.log(tour);
//parameters send to MoMo get get payUrl
var endpoint = 'https://test-payment.momo.vn/gw_payment/transactionProcessor';
var hostname = 'https://test-payment.momo.vn';
var path = '/gw_payment/transactionProcessor';
var partnerCode = 'MOMO';
var accessKey = 'accessKey';
var serectkey = 'secretKey';
var orderInfo = 'pay with MoMo';
var returnUrl = 'https://momo.vn/return';
var notifyurl = 'https://callback.url/notify';
var amount = (tour.price * 23000).toString();
console.log(amount);
var orderId = req.params.tourId;
var requestId = req.params.tourId;
var requestType = 'captureMoMoWallet';
var extraData = 'merchantName=;merchantId='; //pass empty value if your merchant does not have stores else merchantName=[storeName]; merchantId=[storeId] to identify a transaction map with a physical store
//before sign HMAC SHA256 with format
//partnerCode=$partnerCode&accessKey=$accessKey&requestId=$requestId&amount=$amount&orderId=$oderId&orderInfo=$orderInfo&returnUrl=$returnUrl¬ifyUrl=$notifyUrl&extraData=$extraData
var rawSignature =
'partnerCode=' +
partnerCode +
'&accessKey=' +
accessKey +
'&requestId=' +
requestId +
'&amount=' +
amount +
'&orderId=' +
orderId +
'&orderInfo=' +
orderInfo +
'&returnUrl=' +
returnUrl +
'¬ifyUrl=' +
notifyurl +
'&extraData=' +
extraData;
//puts raw signature
console.log('--------------------RAW SIGNATURE----------------');
console.log(rawSignature);
//signature
const crypto = require('crypto');
var signature = crypto
.createHmac('sha256', serectkey)
.update(rawSignature)
.digest('hex');
console.log('--------------------SIGNATURE----------------');
console.log(signature);
//json object send to MoMo endpoint
var body = JSON.stringify({
partnerCode: partnerCode,
accessKey: accessKey,
requestId: requestId,
amount: amount,
orderId: orderId,
orderInfo: orderInfo,
returnUrl: returnUrl,
notifyUrl: notifyurl,
extraData: extraData,
requestType: requestType,
signature: signature
});
//Create the HTTPS objects
var options = {
hostname: 'test-payment.momo.vn',
port: 443,
path: '/gw_payment/transactionProcessor',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(body)
}
};
//Send the request and get the response
console.log('Sending....');
var req = https.request(options, res => {
console.log(`Status: ${res.statusCode}`);
console.log(`Headers: ${JSON.stringify(res.headers)}`);
console.log('Type of body', JSON.stringify(res.body));
res.setEncoding('utf8');
let fullBody = '';
res.on('data', body => {
fullBody += body;
console.log(' Real Body');
console.log(fullBody);
//console.log('Type of body', body.payUrl);
// console.log(JSON.parse(body).payUrl);
// res.redirect(JSON.parse(body).payUrl);
});
res.on('end', () => {
const payURL = JSON.parse(fullBody).payUrl;
console.log('payUrl', payURL);
console.log('No more data in response.');
});
});
req.on('error', e => {
console.log(`problem with request: ${e.message}`);
});
// write data to request body
req.write(body);
req.end();
});
This is the url I got from response
payUrl https://test-payment.momo.vn/gw_payment/payment/qr?partnerCode=MOMO&accessKey=F8BBA842ECF85&requestId=5f38cc86954a6206211e2842&amount=23000&orderId=5f38cc86954a6206211e2842&signature=37ae247d56efd9ed6630b7d7d1435b88ffb8895956da5711a62ebbab8118aa7b&requestType=captureMoMoWallet
Can you please tell how could i send the data from res.on('end'), the "payURL" in the picture above, to client-side. I have tried some methods like res.writeHead, res.send, res.json( ) .... But they all returned error: res.send, res.writeHead, res.json... is not a function
This is my client-side, . If you guys don't mind , please also show me how to automatically redirect the payURL site above when the client click my button. Should I keep using window.location.replace like above ?
export const bookTour = async tourId => {
try {
const res = await fetch(
`http://localhost:3000/api/v1/bookings/checkout-session/${tourId}`,
{
method: 'POST',
body: 'a=1'
}
).then(res => window.location.replace(res.redirectURL));
console.log('The res', res);
} catch (err) {
showAlert('error', err);
}
};
This is my index.js
if (bookBtn) {
bookBtn.addEventListener('click', e => {
e.target.textContent = 'Processing...';
const tourId = e.target.dataset.tourId;
bookTour(tourId);
});
}
You're shadowing the req/res-variables from your getCheckoutSession-handler by using the same names for your http-request. If you change it to:
const request = https.request(options, response => {
// ...
let fullBody = '';
response.on('data', body => {
fullBody += body;
});
response.on('end', () => {
const payURL = JSON.parse(fullBody).payUrl;
// access the handler "res" object here
res.send(payURL);
// alternatively use res.json({payURL}) to send a json response
});
});
it should work fine.
Note: Nowadays you should definitely use const/let instead of var (see this for more information)
Simple,
res.on('end', () => {
const payURL = JSON.parse(fullBody).payUrl;
res.json({
payURL: payURL
})
});
or other way
res.on('end', () => {
const payURL = JSON.parse(fullBody).payUrl;
res.status(200).send({
payURL: payURL
});
});
I'm able to get access oauth2 token from google api by using below code:
<html><head></head><body>
<script>
var YOUR_CLIENT_ID =
'568020407566-s1tdctjbjeocf5nt20l64midfo1atu4h.apps.googleusercontent.com';
var YOUR_REDIRECT_URI =
'https://us-central1-hyperledger-poc.cloudfunctions.net/oauthjax';
var fragmentString = location.hash.substring(1);
// Parse query string to see if page request is coming from OAuth 2.0 server.
var params = {};
var regex = /([^&=]+)=([^&]*)/g, m;
while (m = regex.exec(fragmentString)) {
params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
}
if (Object.keys(params).length > 0) {
localStorage.setItem('oauth2-test-params', JSON.stringify(params) );
if (params['state'] && params['state'] == 'try_sample_request') {
trySampleRequest();
}
}
// If there's an access token, try an API request.
// Otherwise, start OAuth 2.0 flow.
function trySampleRequest() {
var params = JSON.parse(localStorage.getItem('oauth2-test-params'));
if (params && params['access_token']) {
var xhr = new XMLHttpRequest();
xhr.open('GET',
'https://www.googleapis.com' +
'access_token=' + params['access_token']);
xhr.onreadystatechange = function (e) {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.response);
} else if (xhr.readyState === 4 && xhr.status === 401) {
// Token invalid, so prompt for user permission.
oauth2SignIn();
}
};
xhr.send(null);
} else {
oauth2SignIn();
}
}
/*
* Create form to request access token from Google's OAuth 2.0 server.
*/
function oauth2SignIn() {
// Google's OAuth 2.0 endpoint for requesting an access token
var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth';
// Create element to open OAuth 2.0 endpoint in new window.
var form = document.createElement('form');
form.setAttribute('method', 'GET'); // Send as a GET request.
form.setAttribute('action', oauth2Endpoint);
// Parameters to pass to OAuth 2.0 endpoint.
var params = {'client_id': YOUR_CLIENT_ID,
'redirect_uri': YOUR_REDIRECT_URI,
'scope': 'https://www.googleapis.com/auth/userinfo.email',
'state': 'try_sample_request',
'include_granted_scopes': 'true',
'response_type': 'token'};
// Add form parameters as hidden input values.
for (var p in params) {
var input = document.createElement('input');
input.setAttribute('type', 'hidden');
input.setAttribute('name', p);
input.setAttribute('value', params[p]);
form.appendChild(input);
}
// Add form to page and submit it to open the OAuth 2.0 endpoint.
document.body.appendChild(form);
form.submit();
}
</script>
<button onclick="trySampleRequest();">Try sample request</button>
</body></html>
I'm trying to get the token information using https://oauth2.googleapis.com/tokeninfo?id_token=XYZ123 mentioned in below google document
https://developers.google.com/identity/protocols/oauth2/openid-connect#validatinganidtoken
I'm getting below error as response:
{
"error_description": "Invalid Value"
}
But if i use the same token to get user info, it was working fine by using below code and the response as well
code which i tried:
const token = req.body.access_token;
var options = {
host: 'www.googleapis.com',
port: 443,
//path: '/oauth2/v3/userinfo',
path: '/oauth2/v3/tokeninfo?id_token='+token,
method: 'GET',
headers: {'Authorization': 'Bearer '+ token}
}
// making the https get call
let data;
var getReq = await https.request(options, function(response) {
response.on('data', (chunk) => {
data += chunk;
});
response.on('end', function() {
// Data reception is done, do whatever with it!
console.log("line 52");
// var parsed = JSON.parse(data);
console.log("line 54"+data);
res.send(data);
// console.log('data', parsed);
// console.log('endSTATUS: ' + parsed);
});
});
// console.log("response",recievedJSON);
/*getReq.on('end',function(){
res.send(valid);
});*/
getReq.end();
getReq.on('error', function(err) {
console.log('Error: ', err);
});
Response:
{
"sub": "1070944556782450037456",
"picture": "https://lh6.googleusercontent.com/-b32hSj9vONg/AAAAAAAAAAI/AAAAAAAAAAA/tasdfsadfBfIQ/photo.jpg",
"email": "xxxxxxxxx#gmail.com",
"email_verified": true
}
Hi I'm trying to update a Google Doc with NodeJS using the Google Drive API and I'm getting this error:
{
"error": {
"code": 500,
"message": null
}
}
Here's the relevant code :
var j = new google.auth.JWT(
creds.client_email,
null,
creds.private_key,
[
"https://www.googleapis.com/auth/drive"
]
);
async function refreshTokens() {
startedWaiting = true;
return j.authorize((r,t) => {
startedWaiting = false;
timeTillNeedRefresh = t["expiry_date"] - Date.now();
setTimeout(function() {
refreshTokens();
// console.log("doing Q", Q);
}, timeTillNeedRefresh);
tokens = t;
console.log("GOT A TOKEN", tokens);
Q.forEach(x=>x());
Q = [];
});
}
async function start() {
await refreshTokens();
}
start();
function myFetch(opts) {
if(!opts) opts = {};
var cb = opts.cb || empty;
var headers = {
'Accept-Encoding': 'gzip',
'User-Agent': 'google-api-nodejs-client/0.7.2 (gzip)',
Authorization:tokens.token_type +" "+ tokens.access_token,
Accept:"application/json"
};
if(opts.headers) {
for(k in opts.headers) {
headers[k] = opts.headers[k];
}
}
fetch(
opts.url
|| "",
{
method:opts.method || "GET",
headers: headers
})
.then(res => res.text())
.then(body => {
cb(body);
});
}
updateFile({
id: "1vebqOamZ9QB4HqfUaQN-U9Zt4y33eij-I21glMvaPVQ",
content: "hi there"
});
async function allFuncs(tmp) {
if(tokens === null) {
console.log("DOING it later")
Q.push(tmp);
await refreshTokens();
} else if(startedWaiting || timeTillNeedRefresh <= 0) {
console.log("NOT for a while");
Q.push(tmp);
} else {
console.log("THIS is what should happen");
start = Date.now();
tmp();
}
}
async function updateFile(opts) {
var id = opts.id,
content = opts.content || "";
if(id) {
allFuncs(() => {
myFetch({
url:`https://www.googleapis.com/upload/drive/v3/files/${id}?uploadType=media`,
method:"PATCH",
headers: {
body: opts.content,
"Content-Type": "application/vnd.google-apps.document"
},
cb(b) {
console.log(b, "DID I DO IT?!");
}
});
});
}
}
I tried looking up what this error means but I couldn't find anything related to nodejs...
Does anyone know if its a header issue or is there any way to fix it?
I don't know if its possible to do wih a service key, or if you HAVE to verify the user in order to do so??
SEEMINGLY if the service key email has edit permissions for the file, it should just be able to edit it at will.
You want to overwrite the existing Google Document by a text of hi there with Drive API using Service Account.
The Google Document is shared with the Service Account.
You can use googleapis.
I could understand like above. If my understanding is correct, how about this sample script? In this sample script, I used the files.update method of Drive API.
Sample script:
Before you run the script, please set the json file path downloaded when the Service Account is created. And please confirm the file ID of Google Document, again.
const stream = require('stream');
const {google} = require('googleapis');
const creds = require('###'); // Please set the json file path downloaded when the Service Account is created.
const jwtClient = new google.auth.JWT(
creds.client_email,
null,
creds.private_key,
['https://www.googleapis.com/auth/drive'],
null
);
const id = "1vebqOamZ9QB4HqfUaQN-U9Zt4y33eij-I21glMvaPVQ"; // Please set the file ID of Google Document
const content = "hi there"; // Please set the text.
const drive = google.drive({version: 'v3', auth: jwtClient});
const buf = Buffer.from(content, 'binary');
const buffer = Uint8Array.from(buf);
var bufferStream = new stream.PassThrough();
bufferStream.end(buffer);
const media = {
mimeType: 'application/vnd.google-apps.document',
body: bufferStream,
};
drive.files.update({
fileId: id,
media: media,
}, (err, res) => {
if (err) {
console.log(err);
return;
}
console.log(res.data);
});
Note:
When you run the script, the existing Google Document is overwritten. So please be careful this. I recommend to use a sample Document for testing.
If this script didn't work, please confirm the following points.
Drive API is enabled at API console.
The Service Account can be used.
The Google Document is shared with the Service Account.
The version of googleapis is the latest one.
Reference:
Files: update
Edit:
You don't want to use googleapis.
You want to overwrite Google Document with a text value without using googleapis.
From your comments, I understood like above. If my understanding is correct, how about this sample script? When you run this script, please confirm the following points.
About the script,
Please set privateKey and clientEmail from JSON file of Service Account.
Please set the file ID of the existing Google Document you want to overwrite.
Drive API is enabled at API console.
The Service Account can be used.
The Google Document is shared with the Service Account.
The version of googleapis is the latest one.
Sample script:
const cryptor = require('crypto');
const request = require('request');
// Get access token using Service Account
function getAccessToken(serviceAccount) {
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: serviceAccount.clientEmail,
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(serviceAccount.privateKey, 'base64');
return new Promise(function(resolve, reject) {
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;
}
const obj = JSON.parse(body);
resolve(obj.access_token);
});
});
}
// Overwrite file in Google Drive
function overWriting(object) {
const metadata = {
mimeType: "application/vnd.google-apps.document",
};
const url = "https://www.googleapis.com/upload/drive/v3/files/" + object.googleDocumentFileId + "?uploadType=multipart";
const boundary = "xxxxxxxxxxx";
var data = "--" + boundary + "\r\n";
data += "Content-Disposition: form-data; name=\"metadata\"\r\n";
data += "Content-Type: application/json; charset=UTF-8\r\n\r\n";
data += JSON.stringify(metadata) + "\r\n";
data += "--" + boundary + "\r\n";
data += "Content-Disposition: form-data; name=\"file\"; filename=\"sample.txt\"\r\n";
data += "Content-Type: text/plain" + "\r\n\r\n";
const payload = Buffer.concat([
Buffer.from(data, "utf8"),
new Buffer(object.textData, 'binary'),
Buffer.from("\r\n--" + boundary + "--", "utf8"),
]);
const options = {
method: 'patch',
url: url,
headers: {
"Content-Type": "multipart/related; boundary=" + boundary,
'Authorization': 'Bearer ' + object.accessToken,
},
body: payload,
};
request(options, (error, response, body) => {
console.log(body);
});
}
async function main() {
const serviceAccount = {
privateKey: "###", // private_key of JSON file retrieved by creating Service Account
clientEmail: "###", // client_email of JSON file retrieved by creating Service Account
};
var object = {
googleDocumentFileId: "###", // Set the file ID of the existing Google Document
textData: "hi there",
};
const accessToken = await getAccessToken(serviceAccount);
if (accessToken) {
object.accessToken = accessToken;
overWriting(object);
}
}
main();
I'm currently looking to automate a few tasks by creating a custom application that allows me to easily post status updates on my Facebook page(not my personal timeline). My backend is running on NodeJS.
My client-side code has the following:
window.fbAsyncInit = function() {
FB.init({
appId : 'xxxxxxxxxxxxx', // App ID
channelUrl : '//xxxxxxxxxxx, // Channel File
status : true, // check login status
cookie : true, // enable cookies to allow the server to access the session
xfbml : true // parse XFBML
});
// Additional init code here
FB.getLoginStatus(function(response) {
if (response.status === 'connected') {
console.log("You are signed into FB");
var access_token = FB.getAuthResponse()['accessToken'];
console.log('Access Token = ' + access_token);
FB.api('/me/accounts', function(response) {
for(var i=0;i <response.data.length;i++){;
var page = response.data[i];
if(page.id==my_id){
var page_token = page.access_token;
console.log(page_token);
var param = 'callback=?&username=' + GetURLParameter('username')+'&session='+ GetURLParameter('session')+'&access_token='+ page_token;
$.post(saveTokenEndpoint, param, function(data) {
console.log(data);
});
}
}
});
FB.api('/me', function(response) {
username = response.name;
userid = response.id;
$('#username').text('~Hi '+username+'!');
$(document).trigger('fbInit');
});
// connected
} else if (response.status === 'not_authorized') {
// not_authorized
login();
} else {
login();
// not_logged_in
}
});
};
// Load the SDK Asynchronously
( function(d) {
var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
if (d.getElementById(id)) {
return;
}
js = d.createElement('script');
js.id = id;
js.async = true;
js.src = "//connect.facebook.net/en_US/all.js";
ref.parentNode.insertBefore(js, ref);
}(document));
function login() {
FB.login(function(response) {
if (response.authResponse) {
console.log("You are signed into FB");
var access_token = FB.getAuthResponse()['accessToken'];
FB.api('/me', function(response) {
username = response.name;
userid = response.id;
$('#username').text('~Hi '+username+'!');
$(document).trigger('fbInit');
});
FB.api('/me/accounts', function(response) {
// handle response
for(page in response.data){
if(page.id==my_id){
var page_token = page.access_token;
console.log(page_token);
var param = 'callback=?&username=' + GetURLParameter('username')+'&session='+ GetURLParameter('session')+'&access_token='+ page_token;
$.post(saveTokenEndpoint, param, function(data) {
console.log(data);
});
}
}
});
} else {
// cancelled
}
}, {scope: 'publish_stream, manage_pages, offline_access'});
}
My server-side code:
// saves the token received for future use in posting
app.post('/api/saveToken',function(req,res){
var username = req.body.username;
var access_token = req.body.access_token;
var session = req.body.session;
user.findOne({
username: username,
session: session
},function(err, userObj){
if(userObj!=null){
userObj.token = access_token;
console.log(access_token);
userObj.save();
res.jsonp({status:'true'});
}else{
res.jsonp({status:'false'});
}
});
});
I'm using this method to post my posts on my page:
var data = querystring.stringify({
access_token: token,
message: message
});
var options = {
host: 'graph.facebook.com',
port: 443,
path: '/app_name/feed',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': data.length
}
};
var req = https.request(options, function(res) {
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log("body: " + chunk);
});
res.on('end', function(){ // see http nodejs documentation to see end
console.log("\nfinished posting message");
conObj.approval = 'published';
conObj.save();
});
});
req.on('error', function(e) {
console.error(e);
});
req.write(data);
req.end();
Current situation:
My code is working and i can actually see the posts on the wall of my page.
BUT
It does not appear to anyone else except myself.
HOW I GOT IT TO APPEAR PROPERLY TEMPORARILY:
When i copy the token directly from the Graph API Explorer(/me/accounts), I got it to work.
https://developers.facebook.com/tools/explorer?method=GET&path=me%2Faccounts
Ultimately, all i want to do is find a way to post a post on my page
I monitored the differences that was made through both tokens and have found no differences. Their scope was to the 'public' and 'everyone'.
Experts do advice! I find this all very puzzling.
I'm intending to try NodeJS facebook such as facebook-node-sdk and nodejs-facebook-sdk libraries if all else fails.
Thanks for the replies in advance!
You should do OAUTH server side, not client side.
Here is a working example of posting a post through the Facebook Graph API using node.js here: http://code.runnable.com/facebook/UTlPM1-f2W1TAABY
The only dependency you're not already using is request, which you should be using.