How to call Gmail Api from chrome extension? - google-chrome

I am getting following error while requesting Gmail api :
error
:
code
:
401
errors
:
Array(1)
0
:
domain
:
"global"
location
:
"Authorization"
locationType
:
"header"
message
:
"Invalid Credentials"
reason
:
"authError"
[[Prototype]]
:
Object
length
:
1
[[Prototype]]
:
Array(0)
message
:
"Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project."
status
:
"UNAUTHENTICATED"
background.js
chrome.identity.getAuthToken().then(token => {
console.log(token);
fetch('https://www.googleapis.com/gmail/v1/users/me/labels', {
method: 'POST',
headers: {
'Authorization': Bearer ${token},
'Content-Type': 'application/json'
},
body: JSON.stringify({
labelListVisibility: 'labelShow',
messageListVisibility: 'show',
name: 'labelName'
})
}).then(response => response.json())enter code here
.then(data => console.log(data))
.catch(error => console.error(error));
});

Did you try adding
"oauth2": {
"client_id": "<YOUR_CLIENT_ID>.apps.googleusercontent.com",
"scopes": [
"https://www.googleapis.com/auth/gmail.modify",
"https://mail.google.com/"
]
},
Having the www.googleapis.com in the "scopes" worked for me.
Also, take a look at the match patterns, I've been working with a Gmail extension and my "matches" are ://mail.google.com/
https://developer.chrome.com/docs/extensions/mv3/match_patterns/

Related

NuxtJS - Google Auth: ExpiredAuthSessionError: Both token and refresh token have expired. Your request was aborted

Im using nuxtjs for a while. Before my last update all auth feature run smoothly.
But after I update the nuxt.config.js move axios plugin from plugins array to auth config object the error occurred. I need to put axios in auth config object because I need to access $auth from axios plugin.
Version
"#nuxtjs/auth-next": "5.0.0-1607693598.34d83ea"
"nuxt": "^2.15.2"
Nuxt configuration
Mode:
Universal
Nuxt configuration
auth: {
plugins: [{ src: "~/plugins/axios.js", ssr: true }], // <-- I put this, move from plugins array
strategies: {
local: {
token: {
property: "data.token",
required: true,
type: "",
maxAge: 18000,
},
user: {
property: "data",
autoFetch: true,
},
endpoints: {
login: { url: "/api/main", method: "post" },
logout: { url: "/api/profiles/logout", method: "get" },
user: { url: "/api/profile", method: "get" },
},
},
google: {
responseType: "code",
clientId:"<google client ID>",
codeChallengeMethod: "",
grantType: "authorization_code",
redirectUri: `${baseUrl}/verify-auth`,
},
},
redirect: {
login: "/login",
logout: "/login",
callback: "/login",
home: "/",
},
},
Reproduction
ExpiredAuthSessionError: Both token and refresh token have expired. Your request was aborted.
at a5d2e4e.js:1:4374
Steps to reproduce
After selecting a google account, then redirected to /verify-auth, then the error occurred. After /verify-auth it should go in.
Update google auth config like this:
google: {
responseType: "code",
clientId:"<google client ID>",
codeChallengeMethod: "",
grantType: "authorization_code",
redirectUri: `${baseUrl}/verify-auth`,
token: {
property: "data.token", // <-- based on your API response (endpints.login)
required: true,
type: "",
maxAge: 18000,
},
user: {
property: "data",
autoFetch: true,
},
endpoints: {
login: { url: "{your google auth API}", method: "post" }, // <-- should return response with token on it
logout: { url: "/api/profiles/logout", method: "get" },
user: { url: "/api/profile", method: "get" },
},
}

useDomainAdminAccess creates error in Google Drive API using service account authentication

I am creating a service to watch some of my Shared Drive folders on Google Drive. I am using a service account for authentication as this is a service running on a server. Here is my code snippet:
const { google } = require("googleapis");
const auth = new google.auth.GoogleAuth({
keyFile: "./credentials.json",
scopes: ["https://www.googleapis.com/auth/drive"],
});
const drive = google.drive({ version: "v3", auth });
drive.drives
.list({ q: "name = Clients", useDomainAdminAccess: true })
.then((files) => {
console.log(files);
})
.catch((err) => {
console.log(err);
});
If I leave the list method parameters empty, I get back a response with status code 200 and an empty list of drives as expected (as the service account does not own any shared drives). As soon as I add the use useDomainAdminAccess: true parameter, I get an error response as follows:
GaxiosError: Invalid Value
at Gaxios._request (/Users/bteres/Projects/fw-docs/node_modules/gaxios/build/src/gaxios.js:85:23)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
at async JWT.requestAsync (/Users/bteres/Projects/fw-docs/node_modules/google-auth-library/build/src/auth/oauth2client.js:342:22) {
response: {
config: {
url: 'https://www.googleapis.com/drive/v3/drives?q=name%20%3D%20Clients&useDomainAdminAccess=true',
method: 'GET',
userAgentDirectives: [Array],
paramsSerializer: [Function],
headers: [Object],
params: [Object: null prototype],
validateStatus: [Function],
retry: true,
responseType: 'json',
retryConfig: [Object]
},
data: { error: [Object] },
headers: {
'alt-svc': 'h3-27=":443"; ma=2592000,h3-25=":443"; ma=2592000,h3-T050=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q049=":443"; ma=2592000,h3-Q048=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"',
'cache-control': 'private, max-age=0',
connection: 'close',
'content-encoding': 'gzip',
'content-security-policy': "frame-ancestors 'self'",
'content-type': 'application/json; charset=UTF-8',
date: 'Sun, 07 Jun 2020 10:43:54 GMT',
expires: 'Sun, 07 Jun 2020 10:43:54 GMT',
server: 'GSE',
'transfer-encoding': 'chunked',
vary: 'Origin, X-Origin',
'x-content-type-options': 'nosniff',
'x-frame-options': 'SAMEORIGIN',
'x-xss-protection': '1; mode=block'
},
status: 400,
statusText: 'Bad Request',
request: {
responseURL: 'https://www.googleapis.com/drive/v3/drives?q=name%20%3D%20Clients&useDomainAdminAccess=true'
}
},
config: {
url: 'https://www.googleapis.com/drive/v3/drives?q=name%20%3D%20Clients&useDomainAdminAccess=true',
method: 'GET',
userAgentDirectives: [ [Object] ],
paramsSerializer: [Function],
headers: {
'x-goog-api-client': 'gdcl/4.2.1 gl-node/12.17.0 auth/6.0.1',
'Accept-Encoding': 'gzip',
'User-Agent': 'google-api-nodejs-client/4.2.1 (gzip)',
Authorization: 'REDACTED',
Accept: 'application/json'
},
params: [Object: null prototype] {
q: 'name = Clients',
useDomainAdminAccess: true
},
validateStatus: [Function],
retry: true,
responseType: 'json',
retryConfig: {
currentRetryAttempt: 0,
retry: 3,
httpMethodsToRetry: [Array],
noResponseRetries: 2,
statusCodesToRetry: [Array]
}
},
code: 400,
errors: [
{
domain: 'global',
reason: 'invalid',
message: 'Invalid Value',
locationType: 'parameter',
location: 'q'
}
]
}
I tried leaving that out and only using the q parameter and I get the same response. If I leave out the q parameter, same problem.
I have been at this for a couple of days and any help would be greatly appreciated.
UPDATE:
I have already enabled domain-wide delegation for the service account as can be seen below.
I have also enabled this in my G-Suite admin API Management controls as seen below.
Did I possibly get some of the config incorrect here?
After hours of struggle and another nudge, I managed to figure this out. Google's API documentation is not so clear on this. Basically, you can use your service account but the service account need to impersonate a specific user, it is not by default an admin user in your domain even if you have all the configuration done.
So the easiest option I could figure out was to use google-auth's JWT credentials method as below:
const { google } = require("googleapis");
const credentials = require("./credentials.json");
const scopes = ["https://www.googleapis.com/auth/drive"];
const auth = new google.auth.JWT(
credentials.client_email,
null,
credentials.private_key,
scopes,
"admin#domain.com"
);
const drive = google.drive({ version: "v3", auth });
After changing the auth method to this, the query above works as expected.

React Native POST Method Issues

I have read many questions similar to mine but none solved my issue,
my fetch (Get Method) is working fine but the (POST METHOD) shows Unexpected end of JSON input
fetch('http://monasabat-app.com/Queries/sub_cat.php', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
id: 3
}),
}).then((response) => response.json())
.then((responseJson) => {
this.setState({
fsubCategory: responseJson.sub_cat
})
})
.catch((error) => {
console.error(error);
});
}
And this is the response I got by POSTMAN
{
"sub_cat": [
{
"id": "4",
"sub_cat": "sbu1",
"img_path": "url"
},
{
"id": "9",
"sub_cat": "sub2",
"img_path": "url"
}
]
}
Even if you try in postMan using Content-Type: application/json you will notice you don't get any response.
POST /Queries/sub_cat.php HTTP/1.1
Host: monasabat-app.com
Accept: application/json
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: c60774f8-1aaa-4cf8-8aa3-abcab34b05e3
{id:3}
The unexpected end of JSON input it's because it's trying to parse an empty string.
So it's not an issue related to fetch, just try the following to get the proper response:
fetch('http://monasabat-app.com/Queries/sub_cat.php', {
method: 'POST',
headers: {
'Content-Type':'application/x-www-form-urlencoded',
},
body: 'id=3',
})

Posting JSON format from Google script to PandaDoc API

I am trying to create a new document in PandaDoc via de Google Scipt editor.
Everything works fine (document is created with the right name and template), but the recipients don't come through. If I post the same parameters with Postman the recipients do come through. It probably has to do with the format of the recipient parameters but I am not experienced enough to see what.
Here is my code:
function createPandaDoc() {
var formData = {
"name": "Sample Document5",
"template_uuid": "BDZRbdUt7abCbYFBBBREaL",
"recipients": [
{
"email": "john#appleseed.com",
"first_name": "John",
"last_name": "Appleseed",
"role": "Signer"
}
]
};
// Because payload is a JavaScript object, it will be interpreted as
// as form data. (No need to specify contentType; it will automatically
// default to either 'application/x-www-form-urlencoded'
// or 'multipart/form-data')
var options = {
'method' : 'post',
'headers' : {
Authorization : 'Bearer xxx',
contentType : 'application/json'
},
'payload' : formData
};
UrlFetchApp.fetch('https://api.pandadoc.com/public/v1/documents', options);
}
If you have any idea, please let me know!
Thanks Chris
Got it! Should have been:
function createPandaDoc() {
var formData = {
'name': 'Sample Document5',
'template_uuid': 'BDZRbdUt7abCbYFBBBREaL',
'recipients': [
{
'email': 'john#appleseed.com',
'first_name': 'John',
'last_name': 'Appleseed',
'role': 'Signer'
}
]
};
// Because payload is a JavaScript object, it will be interpreted as
// as form data. (No need to specify contentType; it will automatically
// default to either 'application/x-www-form-urlencoded'
// or 'multipart/form-data')
var options = {
'method' : 'post',
'contentType' : 'application/json',
'headers' : {
Authorization : 'Bearer xxxx'
},
'payload' : JSON.stringify(formData)
}
UrlFetchApp.fetch('https://api.pandadoc.com/public/v1/documents', options);
}

Passport authenticate and JSON response

I'm building a webapplication in NodeJS.
Back-end in application is connected with user just via Json API. I'm trying to do login option. It's possible? How can I receive response from Passport Authenticate?
function post_api(req, res) {
res.writeHead(200, { 'Content-Type': 'application/json' });
// Check method
if(!req.body.method)
res.write( JSON.stringify({
"status":"400",
"response": {
"status" : "error",
"info": "Method not defined."
}
}));
else
{
if(req.body.method == "login")
{
passport.authenticate('local', {failureFlash: true, successFlash: true});
// Something here but i have no idea what...
res.write( JSON.stringify({
"status":"200",
"response": {
"status" : "error", // or success
"info": req.flash('error')
}
}));
}
else
res.write( JSON.stringify({
"status":"404",
"response": {
"status" : "error",
"info": "Method not found."
}
}));
}
res.end(); };
This of course doesn't works, how it should look like?