google API calendar watch doesn't work but channel is created - node.js

I try to listen on my calendar change events (google-apps/calendar/v3/reference/events/watch).
I did everything from Google console side, domains - OK, everything is verified and I succeeded to create channel. Also i succeeded to get sync message with right headers (see below). From docs:
Sync message
After creating a new notification channel to watch a resource, the
Google Calendar API sends a sync message to indicate that
notifications are starting. The X-Goog-Resource-State HTTP header
value for these messages is sync. Because of network timing issues, it
is possible to receive the sync message even before you receive the
watch method response.
That mean that notifications are starting
However when I change something in snaggs#comp.com account -
nothing happens, no request sends to callback : 'https://dev-api.mycompany/google-watch/'
This is my working code:
var google = require('googleapis');
var googleAuth = require('google-auth-library');
var _ = require('underscore-node');
var uuid = require('node-uuid');
// ......
var channel_id = uuid.v1();
_auth.credentials = {
access_token: _token.access_token,
token_type: _token.token_type,
refresh_token: _token.refresh_token,
expiry_date: _token.expiry_date
};
var data = {
auth: _auth,
calendarId: _token.provider_email,
singleEvents: true,
orderBy: 'startTime',
resource: {
id: channel_id,
token: 'email='+_token.provider_email,
address: 'https://dev-api.mycompany/google-watch/',
type: 'web_hook',
params: {
ttl: '36000'
}
}
};
calendar.events.watch(data, function (err, response) {
if (err) {
console.error('The API returned an error: ' + err);
return;
}
});
When I start above mentioned snippets of code i get response:
{
"kind": "api#channel",
"id": "277fa000-d4b6-12e5-ab58-e7afaf85ea65",
"resourceId": "C7vFL07CYfqaHy3vDss4qugWDfk",
"resourceUri": "https://www.googleapis.com/calendar/v3/calendars/snaggs#comp.com/events?orderBy=START_TIME&singleEvents=true&alt=json",
"token": "email=snaggs#comp.com",
"expiration": "1455667451000"
}
And in 'https://dev-api.mycompany/google-watch/' URL I get sync message regards to documents, like (See google-apps/calendar/v3/push):
{
"host": "dev-api.mycompany",
"accept": "*/*",
"accept-encoding": "gzip,deflate",
"user-agent": "APIs-Google; (+https://developers.google.com/webmasters/APIs-Google.html)",
"x-goog-channel-expiration": "Tue, 16 Feb 2016 22:44:51 GMT",
"x-goog-channel-id": "277fa000-d4b6-12e5-ab58-e7afaf85ea65",
"x-goog-channel-token": "email=snaggs#comp.com",
"x-goog-message-number": "1",
"x-goog-resource-id": "C7vFL07CYfqaHy3vDss4qugWDfk",
"x-goog-resource-state": "sync",
"x-goog-resource-uri": "https://www.googleapis.com/calendar/v3/calendars/snaggs#comp.com/events?orderBy=START_TIME&singleEvents=true&alt=json",
"x-forwarded-for": "56.102.7.132",
"x-forwarded-port": "443",
"x-forwarded-proto": "https",
"content-length": "0",
"connection": "keep-alive"
}
but not exists message
Do I miss something?
please help,

We have been using Push Notifications for a few years and noticed that for the last 24 hours we did not receive any notifications across several thousand calendars.
Like you we can create/stop a channel but no notifications are received for changes as normal.
As of about an hour ago we are receiving them again. Please try your channel again as it may be a glitch on the Google Push side of things that has been resolved.

Related

Why would a server deny a request?

I am working on a chrome extension that creates an Anki card and adds it to my desk.
Right now am I trying to get the request to work using the Anki API.
For some reason the server is denying my request.
Here is my code (JavaScript) to create a card and send it as a request to the localhost:
async function createCard() {
// Set the Anki API endpoint URL
const baseURL = 'http://localhost:8765';
// Set the Anki API action, version and params
const card = {
"action": "addNote",
"version": 6,
"params": {
"note": {
"deckName": "Default",
"modelName": "Basic",
"fields": {
"Front": "front content",
"Back": "back content"
},
"options": {
"allowDuplicate": false,
"duplicateScope": "deck",
"duplicateScopeOptions": {
"deckName": "Default",
"checkChildren": false,
"checkAllModels": false
}
}
}
}
};
// Send the request to the Anki API
try {
const response = await fetch(baseURL, {
method: 'POST',
mode: 'no-cors',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(card)
});
// Check the status code of the response
if (response.ok) {
console.log('Card created successfully');
} else {
console.error(`Error creating card: ${response.statusText}`);
}
} catch (error) {
console.error(`Error creating card: ${error}`);
}
}
(The card by now is hardcoded.)
When I execute this code I get 2 errors thrown by chrome:
POST http://localhost:8765/ net::ERR_ABORTED 403 (Forbidden)
Error creating card:
The first error happens on the fetch function
and the second error at "console.error('Error creating card: ${response.statusText}');"
I suggest that the second error appears due to the first one.
Since I am new to computer science, all I tried so far is checking the logs of ANKI to find information about the error, but I couldn't find something. I tried different syntax to create the card since I pass this into the fetch function where the error occurs.
The localhost is running while I am working on this, so the server is accessible.
My solution is setting the webCorsOriginList config of AnkiConnect as "*"
"webCorsOriginList": ["*"]
It will allow CORS for all domains.

Authorizing with Google APIs using a service account

I'm trying to access some google groups from the google-api using nodeJS and a service account file. I can't find a code sample that works quite like this. I've put together some code that seems to be working, but I keep getting an error 400 - Bad Request from the API without any clues what's wrong.
Am I using the right classes? Can I use a service account here? Am I missing scopes or something?
My code:
import { Auth, google } from "googleapis";
const main = async () => {
const auth = new Auth.GoogleAuth({
keyFile: "/path-to-service-account-file.json",
scopes: "https://www.googleapis.com/auth/admin.directory.group.readonly",
});
const client = await auth.getClient();
// Obtain a new drive client, making sure you pass along the auth client
const admin = google.admin({ version: 'directory_v1', auth: client });
const groups = await admin.groups.list();
console.log(groups.data.groups);
}
main().then(() => process.exit(0)).catch(err => {
console.error(err);
process.exit(1);
});
The file is (I think) a standard service account file:
{
"type": "service_account",
"project_id": "groupmembers-*******",
"private_key_id": "*********",
"private_key": ...,
"client_email": "test-admin-nodejs#groupmembers-****.iam.gserviceaccount.com",
"client_id": "*****",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/test-admin-nodejs%40groupmembers-******.iam.gserviceaccount.com"
}
When I run this code, I get the following response:
status: 400,
statusText: 'Bad Request',
request: {
responseURL: 'https://admin.googleapis.com/admin/directory/v1/groups'
}
What's interesting to me is the bearer token it generates for me. The error also prints out the request info:
config: {
url: 'https://admin.googleapis.com/admin/directory/v1/groups',
method: 'GET',
userAgentDirectives: [ [Object] ],
paramsSerializer: [Function (anonymous)],
headers: {
'x-goog-api-client': 'gdcl/5.1.0 gl-node/17.4.0 auth/7.14.1',
'Accept-Encoding': 'gzip',
'User-Agent': 'google-api-nodejs-client/5.1.0 (gzip)',
Authorization: 'Bearer ya29.c.b0AX***********************************************jzxc........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................',
Accept: 'application/json'
},
I don't know if this is normal or relevant, but I've never seen a bearer token with a bunch of dots at the end.
A 400 error is not an authorization/authentication issue, but instead is a client request issue. According to the official documentation, there are some query parameters required for the api call. One of them is the customer query parameter:
The unique ID for the customer's Google Workspace account. In case of a multi-domain account, to fetch all groups for a customer, fill this field instead of domain. As an account administrator, you can also use the my_customer alias to represent your account's customerId. The customerId is also returned as part of the Users
Based on experience, it is implied you must use this value. Although the documentation should be better and it should explicitly say this is required. So, in summary, your request should look like this:
const groups = await admin.groups.list({
customer: "my_customer"
});
console.log(groups.data.groups);

Not receiving Microsoft Graph change notification

I'd like to subscribe to user deletions, so that whenever a user is deleted in Azure AD, our app can react accordingly.
Here's my subscription request:
const now = new Date();
const threeDaysLater = new Date(now.getTime() + 3 * 24 * 58 * 60 * 1000);
request.post({
auth: {
bearer: {...},
},
headers: {
Accept: 'application/json',
},
json: {
changeType: 'updated,deleted',
clientState: {...},
expirationDateTime: threeDaysLater.toISOString(),
notificationUrl: 'https://{...}.ngrok.io/api/azure/webhook',
resource: 'users',
latestSupportedTlsVersion: 'v1_2',
},
url: 'https://graph.microsoft.com/v1.0/subscriptions',
});
After sending this request, I receive a request to my notificationUrl, which I respond back to with the validation token.
I then receive the following response from the initial request:
{
'#odata.context':
'https://graph.microsoft.com/v1.0/$metadata#subscriptions/$entity',
id: {...},
resource: 'users',
applicationId: {...},
changeType: 'updated,deleted',
clientState: {...},
notificationUrl: 'https://{...}.ngrok.io/api/azure/webhook',
expirationDateTime: '2020-03-22T11:52:36.328Z',
creatorId: {...},
latestSupportedTlsVersion: 'v1_2'
}
However, when I actually go into Azure AD and delete users, I never receive any requests to my endpoint... Any ideas what I'm doing wrong here?
I've seen Not receiving a request on our MS Graph Webhook for deleting a User in AAD, but I've both waited 30 minutes, and tried soft + hard deletes. Neither seems to trigger any sort of request to my endpoint.
Okay, so apparently I was just not being patient enough. It can take hours for MS to send these notification requests.
If you're developing your webhook endpoint, and looking to test/debug it, do the action in Azure AD, then do something else for a few hours until you finally get the request. 🙄

PayPal is sending many multiples of the same webhook (node)

Update: Code is now working, I think there were a ton of unverified transactions that had to work their way back through the system after I added `res.send('on') to the code.
Edit: Adding res.send('on') fixed the 502 gateway error but the re-sending continues.
I have webhooks successfully configured and am receiving them at my listener. The documentation on how to verify is not very clear, but I am running the code for get_and_ verify.js given in the node SDK docs. Each webhook that is sent by PayPal is run through this code, which consistently returns true.
My issue is, PayPal is re-sending the same webhook over and over again, seemingly endlessly. Is there something I have not done in the configuration, or is this just how these work?
listener code:
app.post('/paymentauthed', (req,res) => {
res.status(200);
console.log(req.body);
paypal.configure({
mode: "sandbox", //sandbox or live
client_id:
"...",
client_secret:
"..."
});
const eventBody = `{"id": "${req.body.id}"}`
paypal.notification.webhookEvent.getAndVerify(eventBody, function (error, response) {
if (error) {
console.log(error);
throw error;
} else {
console.log(response);
}
});
});
app.listen(3000, () => console.log('Server Started'))
this response might be relevant also, it says there is a 502 bad gateway, not sure why...
"transmissions": [
{
"webhook_url": "https://cloudhookstester.net/paymentauthed",
"response_headers": {
"SERVER_INFO": "",
"Strict-Transport-Security": "“max-age=15768000”",
"HTTP/1.1 502 Bad Gateway": "",
"Server": "nginx/1.14.2",
"Connection": "keep-alive",
"Content-Length": "173",
"Date": "Tue, 15 Jan 2019 03:38:43 GMT",
"Content-Type": "text/html"
},
"transmission_id": "74323070-1874-11e9-8941-d953a11868e8",
"status": "PENDING",
"timestamp": "2019-01-15T03:20:05Z"
}
],
Any help is appreciated.
I was getting the same problem while implementing receiving paypal webhook in my django application, this is resolved after giving a valid working URL over a server for webhook call with returning HttpResponse.
Hope It will work for you and other people are getting this problem also.

not able to get user info

bellow is my node js script to get google user details using accessToken
var accessToken = req.body.accessToken;
console.log(accessToken)
var google = require('googleapis');
//google api
var plus = google.plus('v1');
var OAuth2 = google.auth.OAuth2;
var oauth2Client = new OAuth2(
config.google.clientID,
config.google.clientSecret,
config.google.redirect_uri
);
oauth2Client.setCredentials({access_token: accessToken});
plus.people.get({
userId: 'me',
auth: oauth2Client
}, function (err, response) {
// handle err and response
if (err) {
reject(err)
} else {
console.log(response);
resolve(response)
}
});
need to get google login user details using accessToken. what is wrong in code?
The most likely cause is the user in question has not created a google+ profile. Here are a few more options.
I am not sure what information you are trying to get but the best way to get user info is to authecate a user using the profile scope then request the data directly of the user info endpoint
Request
GET /userinfo/v2/me HTTP/1.1
Host: www.googleapis.com
Content-length: 0
Authorization: Bearer uzG4XqnvucBFk3jylgxnbtNhoOt2wCc3QvUcjk7PZhJ5m6G7ibtlBwbAQntJjJtLsxZfoDjhbASpzLmcFnlZ9o4qoMd2fCV2eRb4O5XrKRAXC
Response
{
"family_name": "Lawton",
"name": "Linda Lawton",
"picture": "https://lh5.googleusercontent.com/-a1CWlFnA5xE/AAAAAAAAAAI/AAAAAAAAl1I/UcwPajZOuN4/photo.jpg",
"locale": "en",
"gender": "female",
"link": "https://plus.google.com/+LindaLawton",
"given_name": "Linda",
"id": "117200475532672775346"
}
You can also go though the google people api using the same profile scope
GET /v1/people/me HTTP/1.1
Host: people.googleapis.com
Content-length: 0
Authorization: Bearer NuzG4XqnvucBFk3jylgxnbtNhoOt2wCc3QvUcjk7PZhJ5m6G7ibtlBwbAQntJjJtLsxZfoDjhbASpzLmcFnlZ9o4qoMd2fCV2eRb4O5XrKRAXC
But this endpoint reads from Google+ so if the user has not filled anything out on their Google+ profile you wont see much data here.
You can use request module to get the user detail on your node server.
But Before requesting the user data, make sure you have authorized the API by giving it the desired scope. In your case, you need to give https://www.googleapis.com/auth/userinfo.profile in the scope.
When you receive your accessToken, use that token to call this google api
https://www.googleapis.com/oauth2/v1/userinfo
const request = require('request');
// use any api you want to call.
request({
url: 'https://www.googleapis.com/oauth2/v1/userinfo',
method: 'GET',
headers: {
'Authorization': `Bearer ${YourAccessToken}`,
'Accept': 'application/json'
}
}, function(err, response, _user) {
console.log('User Data', _user);
})
I hope this will solve your problem. If still there is some problem, you can test your Google APIs on OAuth 2.0 Playground

Resources