Get Events From A Calendar Using Google's NodeJS OAuth2 Client - javascript

I'm using this nodejs google library: https://github.com/googleapis/google-api-nodejs-client#getting-supported-apis
Here is the api call so far (in the actual code I have my real secrets and ids):
const { google } = require("googleapis");
const oauth2Client = new google.auth.OAuth2(
"MY_CLIENT_ID",
"MY_CLIENT_SECRET",
"http://localhost:3000"
);
export default function handler(req, res) {
res.status(200).json(oauth2Client);
}
That outputs
{"_events":{},"_eventsCount":0,"transporter":{},"credentials":{},"eagerRefreshThresholdMillis":300000,"forceRefreshOnFailure":false,"certificateCache":{},"certificateExpiry":null,"certificateCacheFormat":"PEM","refreshTokenPromises":{},"_clientId":"MY_CLIENT_ID","_clientSecret":"MY_CLIENT_SECRET","redirectUri":"http://localhost:3000"}
Does anybody know how to use that oauth2Client to get a list of events from a specific calendar? I can't find any information on that anywhere.
The info I do find uses something called gapi, but this is what is on Google's documentation.
Edit
I tried Ricardo's suggestion but it said it could not load the default credentials:
const authClient = await auth.getClient();
Is there a way to specify the default credentials in the code without doing it via the command line via
gcloud auth application-default login

Related

How to impersonate a Google Workspace account through ADC on Google Cloud Functions?

What I'm trying to do is to:
Create a service account
Give that service account Domain Wide Delegations
Use the Application Default Credentials to impersonate a Google Workspace user and access it's email with gmail API
My code works fine in local development, by using the credential key json file generated for the Service Account mentioned in step 1, through Application Credentials Default mechanism (I have set up the environment variable GOOGLE_APPLICATION_CREDENTIALS to the path of the credentials.json)
import {google} from 'googleapis'
const scopes = [
'https://www.googleapis.com/auth/gmail.readonly',
'https://www.googleapis.com/auth/gmail.modify',
];
const auth = new google.auth.GoogleAuth({
clientOptions: {
subject: 'user#email.com',
},
scopes,
});
const gmail = google.gmail({
version: 'v1',
auth,
});
const list = await gmail.users.messages.list({
userId: 'me',
maxResults: 10,
});
The problem is AFAIK, in local environment (aka not GCE) GoogleAuth uses JWT and in GCE it uses Compute Auth method, where a subject can't be configured or if configured is ignored.
So that's why when deploying the Cloud Function it throws an error about Precondition Check Failed and nothing else more specific.
In my limited knowledge and research I think the solution would be to somehow convert the Compute Auth -> JWT with a subject defined.
The current solution I have implemented and works, consists in saving the credentials.json into the Google Secret Manager:
// Acquire credentials from secret manager:
const secret = await getApiKeyFromSecretManager('SECRET_NAME');
const jsonCreds = JSON.parse(Buffer.from(secret).toString());
// Create the JWT
const auth = google.auth.fromJSON(jsonCreds);
auth.subject = 'user#email.com';
auth.scopes = scopes;
But I'm not really comfortable having to access or save the credentials in the Secret Manager, as I think the solution is not as elegant as it could be.

Accessing a private Google sheet with a google cloud service account

I have a private Google Spreadsheet and I’m trying to access it programmatically using Google Visualization/Google Charts. I've created the service account, and I have tried using the google-auth-library and googleapis npm packages to create an access token that I can then use to access the spreadsheet. But, when I try to use that access token to read from the spreadsheet, the request fails with HTTP code 401 (Unauthorized). What do I need to do in order to make this work?
This is my code:
const { auth } = require('google-auth-library');
const keys = require('./jwt.keys.json');
const id = '{Spreadsheet ID}';
const sheetId = '{Sheet ID}';
const query = "{Query}";
async function getClient(){
const client = auth.fromJSON(keys);
client.scopes = ['https://www.googleapis.com/auth/spreadsheets.readonly'];
console.log(client);
return client;
}
async function main(){
const client = await getClient();
const token = await client.getAccessToken();
console.log(token);
console.log(token.token);
const url = `https://docs.google.com/spreadsheets/d/${id}/gviz/tq?tqx=out:csv&tq=${encodeURIComponent(query)}&access_token=${token.token}#gid=${sheetId}`;
const res = await client.request({url});
console.log(res);
}
main().catch(console.error);
When I saw your script, I thought that it is required modifying the scope. I had got the same situation as you (the status code 401 using your endpoint). Unfortunately, it seems that your endpoint cannot be used using the scope of https://www.googleapis.com/auth/spreadsheets.readonly. So, for example, how about changing it as follows, and testing it again?
From:
https://www.googleapis.com/auth/spreadsheets.readonly
To:
https://www.googleapis.com/auth/spreadsheets
or
https://www.googleapis.com/auth/drive.readonly
Note:
When I tested your endpoint using the modified scope, I confirmed that no error occurred. But if you tested it and when an error occurs, please check other part, again.

Can I send DescribeUserPoolClient commands for a user pool in another AWS account

looking for some AWS Javascript SDK help.
I am in the situation that my User Pool is defined in a separate account to my Lambda which needs to send a DescribeUserPoolClient command.
Code snippet below:
import {
CognitoIdentityProviderClient,
DescribeUserPoolClientCommand,
} from '#aws-sdk/client-cognito-identity-provider';
export async function describeUserPoolClient(userPoolClientId: string, userPoolId: string) {
const cognitoClient = new CognitoIdentityProviderClient({});
const describeUserPoolClientCommand = new DescribeUserPoolClientCommand({
ClientId: userPoolClientId,
UserPoolId: userPoolId,
});
const userPoolClient = await cognitoClient.send(describeUserPoolClientCommand);
return userPoolClient;
}
Since I can only provide a userPoolId and not a full ARN, I can't see a way to send this request cross-account without assuming a role in the other account which makes my local testing a nightmare with getting roles and policies set up.
Can anyone see another way of doing this? Thanks for your help.

How do I update a google calendar event using Node js?

I'm following the google calendar documentation to update an event via a service account here. Unfortunately, besides describing the initial setup with node in mind (which still doesn't show the process via a service account) google doesn't seem to include the node flavor in any further documentation.
My authentication is setup below:
//import google library
const {google} = require("googleapis")
//setup scope of auth
const scopes = ['https://www.googleapis.com/auth/calendar.events'];
//load client secrets from a local file
let credentialsRaw = fs.readFileSync(process.env.GOOGLE_CALENDAR_SECRET);
//get credentials as json parsed from raw file contents
let credentials = JSON.parse(credentialsRaw);
//setup auth obj
let auth = new google.auth.JWT(
credentials.client_email, null,
credentials.private_key, scopes
);
Followed by my code that tries to update the event:
//setup calendar object
const calendar = await google.calendar({
version: "v3",
auth
});
//make call to update calendar event
let updateResults = await calendar.events.update({
auth: auth,
calendarId: req.body.calendar_id, //log looks like: i798978asdfjka678sagsdfv3344#group.calendar.google.com
eventId: req.body.event_id, //log looks like: 12432dsfkjhhwqejhkj12
resource: {
"summary": "Test Summary",
"description": "Test Description",
"end": req.body.end_time, //log for end and start look like: { dateTime: '2021-08-09T11:30:00-04:00', timeZone: 'America/New_York' }
"start": req.body.start_time,
}
});
The error I get is "Not found". That's it. I've tried encoding the calendarId with encodeURIComponent() according to this answer but that didn't change anything. The poster of that answer also mentioned later that the encoding fix isn't needed anymore.
Some common issues on the account side I think I've handled correctly:
The project that the service account is in has the calendar api enabled
The service account has domain wide authority
The following should show you how to authorize the service account.
const {google} = require('googleapis');
const auth = new google.auth.GoogleAuth({
keyFile: '/path/to/your-secret-key.json',
scopes: ['https://www.googleapis.com/auth/calendar.events'],
});
const service = google.calendar({
version: 'v3',
auth: auth
});
For more info see service-account-credentials
Not found
Error normally means that you do not have access to the calendar you are trying to access. I would check to be sure the delegation was setup properly to the calendar. Try testing with a calendar.get to be sure you have access.

Outbound networking HTTP trigger to App store

const functions = require('firebase-functions');
import iapReceiptValidator from 'iap-receipt-validator';
const password = 'abcdefghijkac64beb900889e1'; // Shared Secret from iTunes connect
const production = false; // use sandbox or production url for validation
async validate(receiptData) {
try {
const validationData = await validateReceipt(receiptData);
// check if Auto-Renewable Subscription is still valid
validationData['latest_receipt_info'][0].expires_date > today
} catch(err) {
console.log(err.valid, err.error, err.message)
}
}
exports.validateReceipt = functions.https.onRequest((req, res) => {
const validateReceipt = iapReceiptValidator(password, production);
}
This is what I have so far. I am using this external library. I am using firebase cloud functions and I am on flame plan. I want to make POST request to send receipt JSON object to app store server for auto-renewable purchase verification. I am not sure how to go forward with this. Can i please get some help in regards to structuring my cloud function. The firebase documentation isn't very helpful.
Appreciate any help!

Categories