How to include aws cognito authentication in a google apps script? - google-apps-script

From Google Sheet's App Script, we are trying to access our database using authentication via aws-cognito-identity. I am having trouble even getting started because I am not sure how to import modules because this is not a node.js environment. Does anybody have experience doing this and would not mind sharing it?
Thanks

This is how I got this to work:
var authEndpoint = "https://[put your auth domain here].amazoncognito.com/oauth2/token";
var authClientId = "[put your Cognito client ID here]";
var authSecret = "[put your Cognito auth secret string here]";
var authExpirationTime = undefined;
var authLatestToken = undefined;
function getAuthToken() {
// If last known token is still valid, use it.
if (authLatestToken && authExpirationTime && authExpirationTime < new Date().getTime()) {
return authLatestToken;
}
// Otherwise, request new token from AWS Cognito
var params = {
method: "POST",
followRedirects: true,
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": "Basic " + Utilities.base64Encode(authClientId + ":" + authSecret)
},
payload: "grant_type=client_credentials"
};
var response = UrlFetchApp.fetch(authEndpoint, params);
// Verify response
if (response.getResponseCode() !== 200) {
throw new Error("Authentication failed: HTTP Response not OK.");
}
var data = JSON.parse(response.getContentText());
if (!data.access_token) {
throw new Error("Authentication failed: No token returned.");
}
// Set internal vars and return token
authLatestToken = data.access_token;
if (data.expires_in > 0) {
authExpirationTime = new Date().getTime() + data.expires_in * 1000;
}
return authLatestToken;
}
Then you can add an authorization header with this bearer to any requests that need to be authenticated, for example:
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer " + getAuthToken()
},

Related

Google Apps Script and Google Search Console API

I need to access datas from Search Console using Apps Script.
I tried a loads of things but nothing worked.
I'm using this doc : https://developers.google.com/webmaster-tools/v1/searchanalytics/query
Here are some things I tried :
function authenticate() {
return gapi.auth2.getAuthInstance()
.signIn({scope: "https://www.googleapis.com/auth/webmasters https://www.googleapis.com/auth/webmasters.readonly"})
.then(function() { console.log("Sign-in successful"); },
function(err) { console.error("Error signing in", err); })}
function loadClient() {
gapi.client.setApiKey("YOUR_API_KEY");
return gapi.client.load("https://content.googleapis.com/discovery/v1/apis/searchconsole/v1/rest")
.then(function() { console.log("GAPI client loaded for API"); },
function(err) { console.error("Error loading GAPI client for API", err); })}
function execute() {
return gapi.client.webmasters.searchanalytics.query({
"resource": {}
})
.then(function(response) {
// Handle the results here (response.result has the parsed body).
console.log("Response", response);
},
function(err) { console.error("Execute error", err); })}
Other try:
function searchConsoleQuery() {
var service = getService();
var apiURL =
'https://www.googleapis.com/webmasters/v3/sites/[SITE_URL]/searchAnalytics/query';
var headers = {
'Authorization': 'Bearer ' + service.getAccessToken(),
'contentType':'application/json',
'startDate':'20019-10-01',
'endDate':'2019-10-10'};
var options = {
'payload': JSON.stringify(headers),
'method' : 'POST',
'muteHttpExceptions': true};
var response = UrlFetchApp.fetch(apiURL, options);
var json = JSON.parse(response.getContentText());
Logger.log(json)}
Modification points:
In your script, headers is used to payload.
'startDate' is 20019-10-01.
When these points are reflected in your script, it becomes as follows.
Modified script:
function searchConsoleQuery() {
var siteUrl = "###"; // Please set your site URL.
var service = getService();
var apiURL = `https://www.googleapis.com/webmasters/v3/sites/${encodeURIComponent(siteUrl)}/searchAnalytics/query`;
var options = {
'method': 'POST',
'muteHttpExceptions': true,
'headers': { 'Authorization': 'Bearer ' + service.getAccessToken() },
'contentType': 'application/json',
'payload': JSON.stringify({
'startDate': '2019-10-01',
'endDate': '2019-10-10'
})
};
var response = UrlFetchApp.fetch(apiURL, options);
var json = JSON.parse(response.getContentText());
Logger.log(json)
}
Note:
In this modification, it supposes that Google Search Console API has already been enabled at API console and also siteUrl and your access token of service.getAccessToken() are the valid values for using the API. Please be careful about this. When I tested this modified script with my site URL, I confirmed that the values are returned without error. So, if an error occurs, please confirm the condition of API in your API console and your values again.
If no values are returned, please modify 'startDate': '2019-10-01' and 'endDate': '2019-10-10' and test it again.
References:
Search Analytics: query
fetch(url, params)

Submission part of code works, but notification not appearing on slack channel I want it to run to

Here is my code
function notifyTeamMembersOfNewRequest(event) {
const response = event.values
console.log(`response values: ${response}`)
let payload = {
text: response,
channel: 'C04AZ4GT2UU'
}
requestSlack('POST', `chat.postMessage`, payload)
}
function requestSlack(method, endpoint, params) {
const base_url = "https://slack.com/api/"
const headers = {
'Authorization': "Bearer " + 'YOUR_SLACK_API_KEY',
'Content-Type' : 'application/json'
}
const options = {
headers: headers,
method: method
}
let request_url
if (method == 'POST') {
request_url = base_url + endpoint
options.payload = JSON.stringify(params)
} else {
request_url = base_url + endpoint + params
}
const response = UrlFetchApp.fetch(request_url, options).getContentText();
const json = JSON.parse(response)
return {
response_code: json.ok,
response_data: json
}
}
Basically I want it to send a new response on a form to a slack channel with the mentioned ID - however while on the executions tab it gives me the desired response; it doesn't send it to the slack channel. Can someone please help?
I have used quite a few Google searches however, no luck.

Why is Forge returning code 403 for Data Connector API This clientId is not authorized to perform the operation

Why is Forge returning code 403 for Data Connector API This clientId is not authorized to perform the operation. The token call comes back correctly but I get 403 on the gethubs {"warnings":[{"Id":null,"HttpStatusCode":"403","ErrorCode":"BIM360DM_ERROR","Title":"Unable to get hubs from BIM360DM EMEA.","Detail":"You don't have permission to access this API","AboutLink":null,"Source":null,"meta":null}]}}
And getcon as well "{"detail":"This clientId is not authorized to perform the operation.","status":403,"type":"error","title":"Forbidden","id":69852363,"errors":[{"detail":"This clientId is not authorized to perform the operation.","title":"Forbidden","type":"error"}]}"
These are the calls from App script using, what I think is, 3-legged code grant.
function getToken() {
var formData = {
'client_id': 'ClientID',
'client_secret': 'ClientSecret',
'grant_type': 'client_credentials',
'scope': 'user-profile:read user:read user:write viewables:read
data:create data:read data:write data:search bucket:read bucket:create
bucket:update code:all account:read account:write',
'prompt':'login'
}; var response =
UrlFetchApp.fetch('https://developer.api.autodesk.com/authentication/v1/a uthenticate', {
method: 'POST',
payload: formData
});
var token = JSON.parse(response.getContentText());
console.log(token);
return token.access_token;
}
function getHubs() {
var token = getToken();
console.log(token);
var header = {"Authorization" : "Bearer " + token};
console.log(header);
var options = {
"method" : "get",
"headers" : header
};
var response = UrlFetchApp.fetch('https://developer.api.autodesk.com/project/v1/hubs', options);
var hubs = JSON.parse(response.getContentText());
console.log(JSON.stringify(hubs));
}
function getDConn() {
var token = getToken();
console.log(token);
var header = {"Authorization" : "Bearer " + token,"Content-Type": "application/json" };
console.log(header);
var options = {
"method" : "post",
"headers" : header,
"description": "AccountExtract",
"isActive": true,
"scheduleInterval": "ONE_TIME",
"reoccuringInterval": null,
"effectiveFrom": "2022-10-06T10:00:00.106Z",
"effectiveTo": "2022-10-06T10:00:00.106Z",
"serviceGroups": "locations",
"callbackUrl": null,
"sendEmail": true,
"projectId": null
};
//Google Account ID
var response = UrlFetchApp.fetch('https://developer.api.autodesk.com/data- connector/v1/accounts/ACCOUNTID/requests', options);
var hubs = JSON.parse(response.getContentText());
console.log(JSON.stringify(hubs));

Google Script urlFetchApp Post failing calling Jira Tempo worklogs

I trying to write a google script to query Jira Tempo worklogs.
This is what I have so far:
function postDataForAPI() {
var payloadData = {
"taskKey" : []
};
payloadData.taskKey.push("AA-123");
var payload = Utilities.jsonStringify(payloadData);
var url = "https://api.tempo.io/core/4/worklogs/search";
var digestfull = PropertiesService.getUserProperties().getProperty("digest"); //get username and password (base64 encrypted)
var options = { "Accept":"application/json",
"Content-Type":"application/json",
"method": "POST",
"headers": {"Authorization": digestfull},
"muteHttpExceptions": true,
"payload" : payload
};
var resp = UrlFetchApp.fetch(url,options);
if (resp.getResponseCode() != 200) {
Browser.msgBox("Error retrieving data for url " + url + ":" + resp.getContentText());
return "";
}
else {
return resp.getContentText();
}
}
When I execute the above it fails.
If I use curl then I can successfully make the request (I think this is essentially the same POST):
curl -u "username:password" -X POST https://api.tempo.io/rest/tempo-timesheets/4/worklogs/search -H 'Content-Type: application/json' -d '{"taskKey":["AA-123"]}'
Making GET requests against the same API works fine:
function getDataForAPI() {
var url = "https://api.tempo.io/core/4/worklogs/101112";
var digestfull = PropertiesService.getUserProperties().getProperty("digest"); //get username and password (base64 encrypted)
var options = { "Accept":"application/json",
"Content-Type":"application/json",
"method": "GET",
"headers": {"Authorization": digestfull},
"muteHttpExceptions": true
};
var resp = UrlFetchApp.fetch(url,options);
if (resp.getResponseCode() != 200) {
Browser.msgBox("Error retrieving data for url " + url + ":" + resp.getContentText());
return "";
}
else {
return resp.getContentText();
}
}
So I'm confident it is not Authorisation (GET request succeeds). The curl request succeeds and appears to be in the same form as the google script and yet the google script POST fails.
What do I have wrong?
I believe your goal is as follows.
You want to convert the following curl command to Google Apps Script.
curl -u "username:password" -X POST https://api.tempo.io/rest/tempo-timesheets/4/worklogs/search -H 'Content-Type: application/json' -d '{"taskKey":["AA-123"]}'
Modification points:
It seems that "Accept":"application/json" is not used in the sample curl command.
"Content-Type":"application/json" is required to be included in the request header. But, at UrlFetchApp, the property of contentType can be used.
Utilities.jsonStringify has been deprecated. Ref
When these points are reflected in your script, it becomes as follows.
Modified script:
function postDataForAPI() {
var payloadData = { "taskKey": [] };
payloadData.taskKey.push("AA-123");
var url = "https://api.tempo.io/core/4/worklogs/search";
var digestfull = PropertiesService.getUserProperties().getProperty("digest");
var options = {
"method": "POST",
"contentType": "application/json",
"headers": { "Authorization": digestfull },
"muteHttpExceptions": true,
"payload": JSON.stringify(payloadData)
};
var resp = UrlFetchApp.fetch(url, options);
if (resp.getResponseCode() != 200) {
Browser.msgBox("Error retrieving data for url " + url + ":" + resp.getContentText());
return "";
}
else {
return resp.getContentText();
}
}
Note:
When I saw your provided curl command, it seems that the URL is different. The sample curl command uses https://api.tempo.io/rest/tempo-timesheets/4/worklogs/search. But your script uses https://api.tempo.io/core/4/worklogs/search. I'm worried about this difference. So if the above-modified script didn't work, please check the URL again.
The request of this modified script is the same as the sample curl command. But if an error occurs, please check each value like digestfull and payloadData, again.
Reference:
fetch(url, params)

Discord API tells me: "401: Unauthorized" when i make a GET with Google-Scripts: "UrlFetchApp.fetch()"

I'm setting up a api connection. I want to get informations from discord api for my app.
So I implemented OAuth2 without any problems, I have my access token. Then I tried query some endpoints (/users/#me, /users/#me/guilds,...) but every time I get the same error.
I'm sending my authorization token in headers but it's still returning error 401.
I call the script with the generated url:
https://discordapp.com/api/oauth2/authorize?client_id=XYZ&redirect_uri=https%3A%2F%2Fscript.google.com%2Fmacros%2Fs%2FAKfycbyyt9-FiVv0zXOr8p8pMfojwEs2AXvBftVN1xdWeU3UQ1xgURD%2Fexec&response_type=code&scope=identify
Here is my "authentication code":
function doGet(e){
if(typeof e.parameter.code !== 'undefined') {
var code = e.parameter.code;
getAccessToken(code);
}
return ContentService.createTextOutput('someThink..');
}
function getAccessToken(code){
var API_TOKEN_URL = 'https://discordapp.com/api/oauth2/token'
var CLIENT_ID = 'XYZ'
var CLIENT_SECRET = 'XYZ'
var REDIRECT_URI = 'https://script.google.com/macros/s/AKfycbyyt9-FiVv0zXOr8p8pMfojwEs2AXvBftVN1xdWeU3UQ1xgURD/exec'
data = {
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
'grant_type': 'authorization_code',
'code': code,
'redirect_uri': REDIRECT_URI,
'scope': 'identify'
}
header = {
'method' : 'post',
'Content-Type': 'application/x-www-form-urlencoded',
'payload' : data
}
var result = UrlFetchApp.fetch(API_TOKEN_URL, header);
if (result.getResponseCode() == 200) {
var params = JSON.parse(result.getContentText());
Logger.log(params.access_token); // all is fine
getUser(params.access_token, params.token_type)
}
}
And this code is my API request:
function getUser(accessToken, token_type){
var API_USERS_URL = 'https://discordapp.com/api/users/#me';
header2 = {
'method' : 'GET',
'Authorization': token_type + ' ' + accessToken,
// I tested all of them
// 'followRedirects' : true,
// 'muteHttpExceptions': true,
// 'Content-Type': 'application/json',
// 'Content-Type': 'application/x-www-form-urlencoded',
}
var resultUsers = UrlFetchApp.fetch(API_USERS_URL, header2); // ERROR HERE !
if (resultUsers.getResponseCode() == 200) {
var paramsUser = JSON.parse(result.getContentText());
Logger.log(paramsUser);
}
}
I accept the connection with discord with the same SCOPES: identify.
I tried so hard but I don't succeed. Every time the same error:
{"code": 0, "message": "401: Unauthorized"}
You're sending the header as the params/options parameter to UrlFetchApp.fetch(). Send the header as the header parameter in options:
var resultUsers = UrlFetchApp.fetch(API_USERS_URL,{headers: header2});