User credentials required: Google Cloud Print Submit API - javascript

I am trying to access the Submit API that is apart of the Google Cloud Print however I am running into the error "User credentials required".
I am able to get all the way through authentication and am able to retrieve my access token. I was following this guide https://developers.google.com/cloud-print/docs/appDevGuide
I do not know where it is going wrong. Does anyone know where the credentials are supposed to be inputted?
Here is my code for this portion:
function submitPrintJob(token){
try{
var params = {'printerid':'PRINTER_ID','title':'Test Print Job','ticket':{"version": "1.0", "print": {}},'contentType':'application/pdf'};
var response = https.post({
url: 'https://www.google.com/cloudprint/submit',
body: params,
headers: {'Authorization':'Bearer ' + token}
});
log.debug('submitPrintJob','Response - ' + response.body);
}catch(e){
log.error('submitPrintJob','Error - ' + e.message);
}
}
This code is being in done in Netsuite which is where the https.post API is coming in. I also am aware that I am not sending a document through but I at least need to get past this step. I am getting this error using Postman as well.
Editing to add the portion where I get the token:
I send a request to: https://accounts.google.com/o/oauth2/v2/auth
Parameters:
response_type: code,
scope: https://www.googleapis.com/auth/cloud-platform.read-only,
state: state_parameter_passthrough_value,
redirect_uri: scriplet url
client_id: client id
Google oauth returns a authorization code. I exchange the code for a token this way:
function getToken(code){
try{
var params = {'code':code,'client_id':CLIENT_ID,'client_secret':CLIENT_SECRET,'redirect_uri':REDIRECT_URI,'grant_type':'authorization_code'}
var response = https.post({
url: 'https://www.googleapis.com/oauth2/v4/token',
body: params,
headers: {'Content-Type':'application/x-www-form-urlencoded'}
});
var token = response.body.access_token;
submitPrintJob(token);
}catch(e){
log.error('getAuthCode','Error - ' + e.message);
}
}

As I thought, the problem is how you are getting the access token. In order to get a valid access token to do your cloud print business, you need to include the proper scope. That means that your params object should like like this:
var params = {'code':code,'client_id':CLIENT_ID,'client_secret':CLIENT_SECRET,'redirect_uri':REDIRECT_URI, 'scope': 'https://www.googleapis.com/auth/cloudprint', 'grant_type':'authorization_code'}
This should give you a valid access token to interact with Google Cloud Print. I hope it helps!

Related

urlFetchApp.fetch() seems to be failing silently when attempting a JSON POST to Discord Webhook

I'm attempting to post a message from a Google Apps Script to a discord server.
Attempting to debug by using logs reveals that the script seems to fail at the key line
var response = UrlFetchApp.fetch(discordUrl, params);
The logs are empty from that point, ('hi' never appears in the logs) leaving me stumped with how to proceed with error identification.
How can I discover why the call to UrlDetchApp.fetch() is apparently failing?
I have redacted the actual webhook url in the example below.
function postMessageToDiscord() {
message = "Hello World!";
Logger.log("trying to post message: " + message);
var discordUrl = 'https://discordapp.com/api/webhooks/[id]/[token]';
var payload = JSON.stringify({content: message});
var params = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
method: "POST",
payload: payload,
muteHttpExceptions: false
};
Logger.log('params set');
var response = UrlFetchApp.fetch(discordUrl, params);
Logger.log('hi');
Logger.log(response.getContentText());
}
EDIT using console.log has allowed me to identify that I'm missing some scopes from my project, I have now added these and authorised the app by calling the function in an installed onEdit trigger direct from the script screen.

Access Token error - Graph API getting user profile

I'm using Microsoft graph API to get to login and get a users profile. I have the accessToken. Though I'm trying to get the profile of the user that I got the AccessToken with.
This is my code, am I missing anything here? Just need the users profile. Note: I'm using Cors anywhere through a proxy server, which has worked for getting the code and accessToken.
Thanks for your help!
I've tried adding the resource URL. I've tried changing the headers (you don't need body parameters for GET and DEL requests).
let auth =
"http://localhost:8080/https://graph.microsoft.com/v1.0/me?access_token=";
let client_id = "?client_id=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
let redirect_uri = "&redirect_uri=http://localhost:8100/";
let response = "&response_type=code";
let resource = "&resource=https://graph.microsoft.com";
let scope =
"&scope=openid+https://outlook.office.com/Contacts.read+offline_access";
let url =
auth + token + resource + client_id + redirect_uri;
//let url = 'http://localhost:8080/https://graph.microsoft.com/v1.0/me?access_token=' + token +"&resource=https://graph.microsoft.com";
this.http.get(url, {
headers: {
Authorization: "Bearer " + token,
"Content-Type": "application/x-www-form-urlencoded",
"Access-Control-Allow-Origin": "*",
resource: "https://graph.microsoft.com"
}
});
Expected: to take the AccessToken and get a user's profile like in Part 4 here.
You've got a number of things going on here.
You're specifying both scope and resource properties. These don't belong together. If you're using the v1 Endpoint then you should be using resource, if you're using the v2 Endpoint then you should be using scope. See Scopes, Not Resources in the documentation.
Your url is not correct. The actual URL should look like this for v1:
https://login.microsoftonline.com/common/oauth2/authorize?client_id={id}&scope=https%3A%2F%2Fgraph.microsoft.com&redirect_uri={uri}&response_type=code
or for v2, like this:
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id={id}&scope=openid+user.read+contacts.read+offline_access&redirect_uri={uri}&response_type=code
Can't use http.get() for this. OAuth's Authorization Code grant starts by redirecting the user to this URL. It will then return the code you then POST back to the /token endpoint to retrieve the access_token and refresh_token.
You need the User.Read scope to retrieve a user's profile (or User.ReadBasic.All to retrieve other user's profiles).
I would recommend using the v2 Endpoint and starting here:
Microsoft v2 Endpoint Primer
Get access tokens to call Microsoft Graph
AAD v2 Endpoint Overview

Invalid input response and secret when verifying google reCaptcha

I am really struggling to get a successful response when doing a post request to the google recaptcha api. I am receiving the following response:
{
"success": false,
"error-codes": [
"invalid-input-response",
"invalid-input-secret"
]
}
I had a look at reCAPTCHA - error-codes: 'missing-input-response', 'missing-input-secret' when verifying user's response (missing details on POST) and followed the answer as closely as possible but with no success.
Here is my file below:
var request = require('request');
module.exports = {
verifyCaptcha: function(req, res) {
var secret = 'SECRET_KEY';
var response = JSON.stringify(req.body.response);
request({
url: 'https://www.google.com/recaptcha/api/siteverify',
method: 'POST',
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: `secret=${secret}&response=${response}`,
}, function (err, response, body) {
if (err) {
res.status(500).send({
error: "Could not verify captcha"
});
} else {
res.status(200).send({
message: body
});
}
});
},
}
If anyone has a solution to this problem please let me know!
Due to the docs: https://developers.google.com/recaptcha/docs/verify
invalid-input-secret: The secret parameter is invalid or malformed.
Maybe you have mixed the site_key and the secret_key.
You need to add the user remote IP address.
var user_ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
request({
url: 'https://www.google.com/recaptcha/api/siteverify',
method: 'POST',
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: `secret=${secret}&response=${response}&remoteip=${user_ip}`}...
Another thing I see that you are not using template literal, you should change the quotes to ` instead of '.
OR, You should use a ready-made module for reCaptcha, like this one:
https://www.npmjs.com/package/recaptcha
For reCAPTCHA Enterprise, check the official docs: https://cloud.google.com/recaptcha-enterprise/docs/create-assessment.
In short, you need to use the library that Google provides:
const { RecaptchaEnterpriseServiceClient } =
require('#google-cloud/recaptcha-enterprise');
const client = new RecaptchaEnterpriseServiceClient();
const [ response ] = await client.createAssessment({...});
RecaptchaEnterpriseServiceClient requires a service account to be created beforehand as described here. The key for that account with the right roles set can then be read by the app. Check the arguments of the constructor to see the available options to pass the data if the file cannot be retrieved automatically.
var response = JSON.stringify(req.body.response);
The stringifying here is probably the cause of the invalid-input-response error.
If your body is something like {"g-recaptcha-response": "..."}, you need to pull out the response value and pass that directly in your post.
Regarding invalid-input-secret, if you have set up your key and secret through the classic interface at https://www.google.com/u/1/recaptcha/admin/create, then you shouldn't have a problem.However if you set up a key with recaptcha Enterprise on Google Cloud, then it requires that you do Oauth authentication to the Google Cloud API and then use the create.assessment endpoint to get back information on the validity of the user. As Yuuhn implied, the Google provided library makes interaction with recaptcha Enterprise easier, without a lot of documentation digging to find where your REST API calls need to go.

Google translation Oauth2.0 from browser

I am creating a simple web page, that make use of the Google Translation Service.
The page has a field, to receive the input from the user and a button to trigger the call to the Translation API. It returns the result translation to the user.
I've successfully done the flow above using Ajax requests, but the access token
is hard-coded into my method and I want to change that to a call that gets sent whenever the token expires (currently I have to request a new token using the Google CLI and replace it in my code).
I have a very basic knowledge of Oauth2.0 and I've read the Google Documentation but couldn't find a part of it that would tell me the endpoint to call to get an access token from the client-side.
Could someone point me in the right direction, please?
Here is my code:
HTML:
<form id="translate_form">
<input id="input" />
<button id="translate_button">Translate</button>
</form>
Javascript
$("#translate_form").submit(function () {
var text = $("#input").val()
sendTranslationRequest(text);
return false;
})
function sendTranslationRequest(inputText) {
var requestBody = {
q: inputText,
source: "en",
target: "fr",
format: 'text'
}
translationAjaxRequest(requestBody);
}
function translationAjaxRequest(requestBody) {
var access_token = [access_token]
$.ajax({
url: "https://translation.googleapis.com/language/translate/v2",
method: "POST",
contentType: "application/json",
beforeSend: function (request) {
request.setRequestHeader("Authorization", "Bearer " + access_token)
},
data: JSON.stringify(requestBody),
success: function (response) {
var translatedText = response.data.translations[0].translatedText
alert(translatedText)
},
error: function () {
console.log("An error occurred on the request:", response)
}
});
}
The relevant endpoints to get an access token and refresh it are:
https://accounts.google.com/o/oauth2/v2/auth
https://www.googleapis.com/oauth2/v4/token
However, you’ll need to perform several steps in order to get an access token and a refresh token. You may want to review this guide on Using OAuth2.0 for Web Server Applications. It will walk you through the prerequisites, obtaining an access token and refreshing your token.
Alternatively, you may use an API Key. Just be mindful of the recommendations on how to secure it, since a stolen API Key may be used to generate calls that would be charged directly to your billing account.

"Invalid left-hand side in assignment" when receiving response from Facebook API

I'm trying to get an extended access token for one of my apps using the Javascript API (I know I should do this server side, but I'm the only one using this app and I have some reasons for not doing it server side this time)
Anyway, when I receive a call back from Facebook, I get an Invalid left-hand side in assignment error.
I don't have any weird if's or anything like that and it only happens when I get the response back from Facebook - so it has nothing to do with the code I've written I don't think.
Anyway, here's the itty-bitty script I'm running.
var token = response.authResponse.accessToken;
FB.api(
'/oauth/access_token',
'GET',
{
'grant_type': 'fb_exchange_token',
'client_id': 'XXX',
'client_secret': 'XXX',
'fb_exchange_token': token
},
function(response) {
console.log(response);
}
);
My token variable is set correctly, so that's not the issue.
If I remove any of the data sent in the array, I get an expected error response, but with it set up this way I just get that error mentioned above and this response from Facebook.
Object {error: Object}
error: Objectmessage: "unknown error"
type: "http"
So I'm kind of stumped on this.
What could I be doing wrong?
Here's what I ended up with.
Not ideal as it doesn't use the Faceook SDK, but it works.
$.get('https://graph.facebook.com/oauth/access_token', {
'grant_type': 'fb_exchange_token',
'client_id': 'XXX',
'client_secret': 'XXX',
'fb_exchange_token': token
}).done(function(data) {
var response = data.split('&');
var result = {};
for (i=0;i<response.length;i++) {
var this_one = response[i].split("=");
result[this_one[0]] = this_one[1];
}
console.log(result);
});
This ends up with an object with the token and expiration time.

Categories

Resources