I am tying to obtain Access Token using Google Apps Script.
Ref: https://developers.docusign.com/platform/auth/jwt/jwt-get-token/
Using Postman, I can get the ACCESS TOKEN by posting a request using this URL: https://account-d.docusign.com/oauth/token
and this two fields in the body:
grant_type : urn:ietf:params:oauth:grant-type:jwt-bearer
assertion : MY_JSON_WEB_TOKEN
How do I replicate tis in Apps script?
After endless hours of trial and error I still get this error: {"error":"invalid_grant","error_description":"unsupported_grant_type"}
The script:
function obtainAccessToken(){
const JWT = MY_JSON_WEB_TOKEN;
const URL = 'https://account-d.docusign.com/oauth/token';
const PARAMS = {
"muteHttpExceptions": true,
"method": "POST",
"contentType": "application/json",
"payload": {
"body":{
"grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
"assertion": JWT
}
}
};
return UrlFetchApp.fetch(URL, PARAMS);
}
This is the correct function:
function obtainAccessToken(){
const JWT = MY_JSON_WEB_TOKEN;
const URL = 'https://account-d.docusign.com/oauth/token';
const PARAMS = {
"method": "POST",
"headers":{
"Accept": "application/json",
"contentType": "application/x-www-form-urlencoded"
},
"payload": {
"grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
"assertion": JWT
}
};
return UrlFetchApp.fetch(URL, PARAMS);
}
Related
Simple code and straightforward. It works with postman but fails with Apps Script.
function validateAddress () {
const url = 'https://addressvalidation.googleapis.com/v1:validateAddress?key=';
const apikey = '...';
let payload, options, temp;
payload = JSON.stringify({
"address": {
"addressLines": "1600 Amphitheatre Pkwy"
}
});
options = {
'muteHttpExceptions': true,
'method': 'POST',
'Content-Type': 'application/json',
'body': payload
}
temp = UrlFetchApp.fetch(url + apikey, options);
Logger.log(temp)
}
Error:
{
"error": {
"code": 400,
"message": "Address is missing from request.",
"status": "INVALID_ARGUMENT"
}
}
EDIT:
Change options to
options = {
'muteHttpExceptions': true,
'method': 'POST',
'Content-Type': 'application/json',
'payload': payload
}
Gives error:
{
"error": {
"code": 400,
"message": "Invalid JSON payload received. Unknown name \"{\"address\":{\"addressLines\":\"1600 Amphitheatre Pkwy\"}}\": Cannot bind query parameter. Field '{\"address\":{\"addressLines\":\"1600 Amphitheatre Pkwy\"}}' could not be found in request message.",
"status": "INVALID_ARGUMENT",
"details": [
{
"#type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"description": "Invalid JSON payload received. Unknown name \"{\"address\":{\"addressLines\":\"1600 Amphitheatre Pkwy\"}}\": Cannot bind query parameter. Field '{\"address\":{\"addressLines\":\"1600 Amphitheatre Pkwy\"}}' could not be found in request message."
}
]
}
]
}
}
Documentation:
https://developers.google.com/maps/documentation/address-validation/requests-validate-address
From the documentation, it seems that addressLines is an array of string, not a string. Does that change something ? (I don't have a key, so I cannot try myself).
And more important, your options object is incorrect (check doc). It should be
options = {
'muteHttpExceptions': true,
'method': 'POST',
'contentType': 'application/json',
'payload': payload
}
I don't know why it works but changed options to
options = {
'muteHttpExceptions': true,
'method': 'POST',
'headers': {
'Content-Type': 'application/json'
},
'payload': payload
}
Solves the problem.
I have a roblem while directing a request from Cloud Flare workers to my API. When I catch the error I get this:
SyntaxError: Unexpected token \n in JSON at position 240
when I did some research I saw some articles about it being about JSON.parse. But I couldn't find the solution.
Example Request Body:
{"link": "link", "provider": "company", "oauth": "key", "testText": "text"}
Cloud Flare Workers Code:
addEventListener('fetch', function (event) {
const { request } = event;
const response = handleRequest(request).catch(handleError)
event.respondWith(response)
})
async function handleRequest(request) {
const realBody = JSON.parse(`${await request.json()}`
.replace(/\n/g, "\\n")
.replace(/\r/g, "\\r")
.replace(/\t/g, "\\t")
.replace(/\f/g, "\\f"));
const stringifiedJSON = JSON.stringify(realBody);
const init = {
body: stringifiedJSON,
method: "POST",
headers: {
"content-type": "application/json;charset=UTF-8",
},
};
const initLog = {
body: JSON.stringify({ msg: { discountBodyStringified: realBody }}),
method: "POST",
headers: {
"content-type": "application/json;charset=UTF-8",
},
}
const responseLogger = await fetch("https://example.com/log", initLog)
console.log(responseLogger)
console.log(init)
const response = await fetch("https://example.com", init)
return new Response("tweet sent!")
}
function handleError(error) {
console.error('Uncaught error:', error)
const { stack } = error
const initLog = {
body: JSON.stringify({ msg: { error: stack || error }}),
method: "POST",
headers: {
"content-type": "application/json;charset=UTF-8",
},
}
const responseLogger = fetch("https://example.com/log", initLog)
return new Response(stack || error, {
status: 500,
headers: {
'Content-Type': 'text/plain;charset=UTF-8'
}
})
}
problem is not in the code, the problem in request which you are or front app is sending somewhere you lived extra comma or didnt close field.
For example:
{
"name": "Alice",
}
this will give same error as SyntaxError: Unexpected token \n in JSON at position because extra comma is there or
{
"name": "Alice
}
this also will throw error because I didnt close quotes
function getClickupTeam() {
let response = UrlFetchApp.fetch(clickupUrl + "team", {
"method": "GET",
"Authorization": clickupToken,
"muteHttpExceptions": true
})
Logger.log(response)
let json = JSON.parse(response);
Logger.log(json);
}
This URLFetchApp call returns {ECODE=OAUTH_017, err=Authorization header required} even though I am including my personal clickup token in the request. Am I missing something? Any help would be appreciated.
It looks like your request is malformed (be sure to check out the reference documentation for the UrlFetchApp.fetch(url, params) method.) The Authorization header should be in an explicit headers object. Plus, you don't need to set method to GET since its the default.
Something else to keep in mind for when you're making POST requests - Google Apps Script has this funny quirk where you have to define the Content-Type header using the contentType property. If you try to set that header in the headers object if will just get overridden by the default (application/x-www-form-urlencoded I believe).
So here's how you'd set up your GET request:
function getClickupTeam() {
let response = UrlFetchApp.fetch(clickupUrl + "team", {
"muteHttpExceptions": true,
"headers": {
"Authorization": clickupToken
}
}
console.log(response.getContentText());
let json = JSON.parse(response.getContentText());
console.log(json);
);
And for POST requests with a JSON payload you'd do something like this:
function getClickupTeam() {
let response = UrlFetchApp.fetch(clickupUrl + "team", {
"method": "POST",
"contentType": "application/json",
"muteHttpExceptions": true,
"headers": {
"Authorization": clickupToken
},
"payload": JSON.stringify({
"key": "value"
});
}
console.log(response.getContentText());
let json = JSON.parse(response.getContentText());
console.log(json);
);
While doing some research on the topic through https://clickup.com/api, I stumbled across some code. There are a couple of different ones for different things, I'd recommend the first, JavaScript (as that's whats closest to what your currently doing). In a comment you said it was for editing tasks so that's what this code is aimed for.
javascript
var request = new XMLHttpRequest();
request.open('PUT', 'https://api.clickup.com/api/v1/task/{task_id}');
request.setRequestHeader('Content-Type', 'application/json');
request.setRequestHeader('Authorization', '"access_token"');
request.onreadystatechange = function () {
if (this.readyState === 4) {
console.log('Status:', this.status);
console.log('Headers:', this.getAllResponseHeaders());
console.log('Body:', this.responseText);
}
};
var body = {
'name': 'New Task Name',
'content': 'New Task Content',
'assignees': {
'add': [
1
],
'rem': [
2
]
},
'status': 'Closed',
'priority': 3,
'due_date': '1508369194377'
};
request.send(JSON.stringify(body));
curl
curl --include \
--request PUT \
--header "Content-Type: application/json" \
--header "Authorization: "access_token"" \
--data-binary "{
\"name\": \"New Task Name\",
\"content\": \"New Task Content\",
\"assignees\": {
\"add\" : [
1
],
\"rem\" : [
2
]
},
\"status\": \"Closed\",
\"priority\": 3,
\"due_date\": \"1508369194377\"
}" \
'https://api.clickup.com/api/v1/task/{task_id}'
node.js
var request = require('request');
request({
method: 'PUT',
url: 'https://api.clickup.com/api/v1/task/{task_id}',
headers: {
'Content-Type': 'application/json',
'Authorization': '\'access_token\''
},
body: "{ \"name\": \"New Task Name\", \"content\": \"New Task Content\", \"assignees\": { \"add\": [ 1 ], \"rem\": [ 2 ] }, \"status\": \"Closed\", \"priority\": 3, \"due_date\": \"1508369194377\"}"
}, function (error, response, body) {
console.log('Status:', response.statusCode);
console.log('Headers:', JSON.stringify(response.headers));
console.log('Response:', body);
});
This is aimed for production let me know if you need mock server or debugging proxy
The following Apps Script code in a Chrome extension does not error, but return no calendars:
chrome.identity.getAuthToken({interactive: true}, function(token)
{
var init =
{
method: 'GET',
async: true,
headers:
{
Authorization: 'Bearer ' + token,
'Content-Type': 'application/json'
},
'contentType': 'json'
};
fetch('https://www.googleapis.com/calendar/v3/users/me/calendarList?minAccessRole=writer&key=' + apiKey, init)
.then(function(data)
{
log('Object ' + JSON.stringify(data));
});
});
I just get this in the console: Object {}
I saw this post and tried the suggestions, no luck. The apiKey came from the API console, and works in a different call. Thanks for any tips or pointers.
Edit #2: Here is my current manifest.json:
"oauth2": {
"client_id": "123456780416-17ur6mlc88sfot8e4s2pq05ehtkd8klh.apps.googleusercontent.com",
"scopes":[
"https://www.googleapis.com/auth/script.external_request",
"https://www.googleapis.com/auth/contacts.readonly",
"https://www.googleapis.com/auth/calendar"
]
}
If you are passing a token into the options of the fetch request, you do not need an API key.
Modify
fetch('https://www.googleapis.com/calendar/v3/users/me/calendarList?minAccessRole=writer&key=' + apiKey, init)
to
fetch('https://www.googleapis.com/calendar/v3/users/me/calendarList?minAccessRole=writer', init)
and define init as
var init = {
"method":"get",
"async": true,
"muteHttpExceptions": true,
"headers": {
"Authorization": "Bearer " + token
},
"contentType": "application/json",
}
Also make sure that your token contains the necessary scopes.
I'm getting the error:
Invalid JSON payload received
When trying to create a new Apps Script file with the Apps Script API.
How do I fix that error?
function createNewFile() {
var d,options,payload,response,theAccessTkn,url;
theAccessTkn = ScriptApp.getOAuthToken();
//See https://developers.google.com/apps-script/api/reference/rest/v1/projects/create
url = "https://script.googleapis.com/v1/projects";
d = new Date().toString().slice(0,10);
payload = {
"title": "AA_" + d
}
options = {
"method" : "POST",
"muteHttpExceptions": true,
"headers": {
'Authorization': 'Bearer ' + theAccessTkn
},
"payload": JSON.stringify(payload)
};
response = UrlFetchApp.fetch(url,options);
Logger.log(response)
return response;
}
I have set the authorization scopes in the manifest file to avoid needing to add an OAuth library:
{
"timeZone": "America/New_York",
"oauthScopes": [
"https://www.googleapis.com/auth/script.projects",
"https://www.googleapis.com/auth/script.external_request"
],
"dependencies": {
},
"exceptionLogging": "STACKDRIVER"
}
I needed to add "contentType": "application/json" to the options.
options = {
"method" : "POST",
"muteHttpExceptions": true,
"headers": {
'Authorization': 'Bearer ' + theAccessTkn
},
"contentType": "application/json",
"payload": JSON.stringify(payload)
};