Cotter + Cloudflare Workers + Google Calendar API: Build a Serverless Calendar Booking App
Putri Karunia
Posted on November 3, 2020
During this pandemic, scheduling a meeting has become more important than ever, be it for a conference call, a consultation, or just a friendly chat.
In this guide, we'll explore how to use Google Calendar's API to make your own calendar booking app (yes, it's a platform, so other people can log in and share their own calendar link!).
👉 Try out the live demo!
Calendar Booking App by Cotter
We'll use:
- Cotter for logging in users and connecting to their Google Account.
- Cloudflare Workers as a backend that will call Google Calendar API.
- Google Calendar API for booking time slots in your users' calendar.
- We'll also use React in this tutorial.
Why Cloudflare Workers?
Cloudflare workers allows you to deploy JavaScript code on Cloudflare's Edge network. This means you can write serverless code in Cloudflare workers and have it deployed across the globe. Your users will connect to the nearest Cloudflare network.
What about a database?
Cloudflare workers offers a Key-Value store that can keep consistent data across their locations. Note that currently, it's "eventually consistent" which means it might take some time (max 60s) for an update to be available globally.
Why do we need a backend?
The biggest reason why we need a backend in this tutorial is that we need a secure environment to store our API Secret Key which is used to get Google's Access Tokens from Cotter.
We don't need a database or a key-value store for our use case, so Cloudflare Workers is perfect for deploying a simple backend code that authenticates your users and calls Google's API
TLDR
To try it out right now, you can use our CodeSandbox and follow the steps below to set up the Cloudflare Backend:
1. Create a project at Cotter, then add Sign in with Google to your Login Form
- Follow these instructions to set up Google OAuth 2.0 Credentials and connect it to Cotter.
- Make sure you added
https://www.googleapis.com/auth/calendar
for the scope. - Enable Google for your form: Go to Branding > Magic Link Form > click the checkmark to enable Google Sign In
- Add Cotter's Login Form to your website
2. Use this CodeSandbox to get the calendar-booking React App. Update src/constants.js
with your Cotter API KEY ID. You can also clone the project from the Github Repo.
3. Setup Cloudflare Worker, make 3 workers with subdomains:
checkconnection.YOURSUBDOMAIN.workers.dev
createevent.YOURSUBDOMAIN.workers.dev
disconnect.YOURSUBDOMAIN.workers.dev
Copy the code from our Github for your Cloudflare Worker.
4. Enable Google Calendar API in your Google project
Enable Google Calendar API to the project that you used to create Google OAuth 2.0 Credentials.
How it works
Here's the outline of the things that we needed to do to build this platform:
- Users will be using "Sign in with Google" to get an access token from Google. This access token is accessible via Cotter's API.
- Make API endpoints at your Cloudflare Worker which would 1) call Cotter's API to get the user's Google Access Token, and 2) call Google's API using that Google access token.
Logging In
Getting Google's Access Token via Google Sign In
To access Google's Calendar API, you'll need a Google Access Token for the user to modify their calendar. This means the user needs to connect their Google Account. Using Cotter as your authentication service, this can be done in 2 ways:
- If the user logged-in using Google Sign In , you can automatically access their Google Access Token by calling Cotter's API.
- If the user logged-in with their email , you can provide a button on the dashboard and ask them to connect their Google Account. After that, you can access their Google Access Token by calling Cotter's API.
When your user logged-in using Cotter, you'll get a Cotter Access Token. We'll use this access token to protect our API Endpoints that we're going to make in Cloudflare Workers.
1) Adding Sign in with Google to your Login Form
-
Follow these instructions to set up Google OAuth 2.0 Credentials and connect it to Cotter. Make sure you added
https://www.googleapis.com/auth/calendar
for the scope. - Enable Google for your form: Go to Branding > Magic Link Form > click the checkmark to enable Google Sign In
- Add Cotter's Login Form to your website
Using Cotter's React SDK, you can easily use React context provider to keep track of the authentication state (i.e. is the user logged-in, etc).
yarn add cotter-react
import React from "react";
import { Router } from "@reach/router";
import LoginPage from "../login";
import { CotterProvider, LoginForm } from "cotter-react"; // 👈 Import Cotter Provider
function App() {
return (
// 👇 1) Wrap CotterProvider around your ROOT COMPONENT
// Copy paste your Cotter API Key ID below.
<CotterProvider apiKeyID="<YOUR API KEY ID>">
<Router>
<LoginPage path="/" />
</Router>
</CotterProvider>
);
}
function LoginPage() {
return (
<div className="LoginPage__form-container">
{/* 👇 2) Show the login form */}
<LoginForm
onSuccess={(response) => console.log(response)}
onError={(err) => console.log(err)}
/>
</div>
);
}
export default App;
2) Checking if the user is logged-in in your dashboard
Using CotterContext
you can check if the user is logged-in and get their Cotter Access Token.
import { CotterContext, withAuthenticationRequired } from "cotter-react"; // 👈 Import the user context
import React, { useContext, useEffect, useState } from "react";
import "./styles.css";
function DashboardPage() {
const { user, getAccessToken, isLoggedIn } = useContext(CotterContext); // Get the logged-in user information
const [accessToken, setaccessToken] = useState(null);
useEffect(() => {
if (isLoggedIn) readAccessToken();
}, [isLoggedIn]);
// Get the Cotter access token to be used for our API call
// (for now, we'll just display it in the dashboard)
const readAccessToken = async () => {
const token = await getAccessToken();
setaccessToken(token?.token);
};
return (
<div className="container">
User ID: {user?.ID} <br />
User email: {user?.identifier} <br />
Cotter Access Token: {accessToken}
</div>
);
}
// Protect this page using the `withAuthenticationRequired` HOC
// If user is not logged-in, they'll be redirected to the `loginPagePath`
export default withAuthenticationRequired(DashboardPage, {
loginPagePath: "/",
});
- Wrap your component around
withAuthenticationRequired
to automatically redirect your user to login if the user is not logged-in - Use
isLoggedIn
to check if the user is logged-in, anduser
to get the logged-in user information. - Use
getAccessToken
to get the Cotter Access Token that we'll use to call our API endpoints.
3) Checking if the user has connected their Google Account
We'll make an endpoint for this on our Cloudflare Worker which will call Cotter's API to see if the user has connected their Google Account.
4) Show a button to connect Google Account from the Dashboard
If the user has not connected their Google Account (they didn't log in using Google), show a button to connect Google Account. Call this function with your button to connect their Google Account:
import { CotterContext } from "cotter-react"; // 👈 Import the user context
function DashboardPage() {
...
const { getCotter } = useContext(CotterContext);
// If the user hasn't connected their Google Account,
// show a button to call this function to connect
const connectToGoogle = async () => {
var cotter = getCotter();
cotter.connectSocialLogin("GOOGLE", accessToken);
};
return (
<div className="DashboardPage__container">
...
<button onClick={connectToGoogle}>Connect Google Account</button>
</div>
);
}
Cloudflare Worker Endpoints
Making API endpoints at Cloudflare Workers to call Google's API
Once you got the login flow working, you can start making the endpoints at Cloudflare Workers that would call Google's API. Specifically, you'll need these endpoints:
- An API to check if the user has connected their Google Account
- An API to modify their Google Calendar
Create a Cloudflare Account and Setup Workers
- Go to Cloudflare and sign up with your email and password. You don't need to add a domain. When asked to add a domain, if you don't have a domain, you can skip this by clicking on the Cloudflare logo.
- Click Workers on the right side of your dashboard, and add a subdomain that you want for your backend API endpoint. Choose the Free Plan and verify your email.
Create a Test Worker to see how this works
- Press Create a Worker. You can see that you have a handler script on the left side, and a playground to test your API endpoint. Click Send and you should see
hello world
as the response. - That's it, you've just created an endpoint! To save this endpoint, press Save and Deploy.
Creating Endpoints
Notice that you can only change the sub-subdomain, not the path.
To be able to handle different paths, you'll need to use their CLI and use a router. That's too advanced for this tutorial, so we'll just have our endpoints on different subdomains.
Endpoints
Endpoint #1: checkconnection
Check if the user has Google Connected.
Create a worker, and change the name to checkconnection
. We'll define our endpoint as the following:
$ curl --request GET \
--header 'Authorization: Bearer <COTTER_ACCESS_TOKEN>' \
--url 'https://checkconnection.YOUR_SUBDOMAIN.workers.dev?userid=<COTTER_USER_ID>'
// If Google account is connected:
{"connected": true}
// If not:
{"connected": false}
Here are the things that we'll need to do:
- Check if the Cotter access token is valid
- Call Cotter's API to check if this user has a Google Access Token
Code & Env Variables
Copy the code from our Github repo.
Add the Cotter Api Keys as environment variables
Go to the Settings tab, and press Add Variable. Add both the API_KEY_ID
and API_SECRET_KEY
from Cotter, then press Save.
Endpoint #2: createevent
Create a Google Calendar Event
Before we start, you'll need to Enable Google Calendar API to the project that you used to create Google OAuth 2.0 Credentials.
Create another worker, and change the name to createevent
. We'll define our endpoint as the following:
$ curl --request POST \
--header "Content-Type: application/json" \
--data '{"start_time":"2020-11-02T10:00:00-08:00","end_time":"2020-11-02T10:15:00-08:00","attendee_email":"attendee@gmail.com","meeting_title":"John Doe <> Jane Doe"}' \
--url 'https://createevent.YOUR_SUBDOMAIN.workers.dev?userid=<COTTER_USER_ID>'
-
start_time
&end_time
should be in formatted according to RFC3339 -
attendee_email
is the email of the attendee (just 1 email) -
meeting_title
is the title of the meeting
This URL doesn't require an authorization header because we want anyone to be able to book an appointment without having to log in to your platform first.
Here are the things that we'll need to do:
- Call Cotter's API to get the user's Google Access Token
- Use Google API Event insert endpoint using the Google Access Token
Code & Env Variables
Copy the code from our Github repo.
Add the Cotter Api Keys and Google Credentials as environment variables
- Again, we need to add the
API_KEY_ID
andAPI_SECRET_KEY
environment variables from Cotter API Keys. - We also need to add
GOOGLE_CLIENT_ID
andGOOGLE_CLIENT_SECRET
environment variable from Google OAuth Credentials.
Endpoint #3: disconnect
Disconnect the user's Google Account
Create another worker, and change the name to disconnect
. We'll define our endpoint as the following:
$ curl --request DELETE \
--header 'Authorization: Bearer <COTTER_ACCESS_TOKEN>' \
--url 'https://disconnect.YOUR_SUBDOMAIN.workers.dev?userid=<COTTER_USER_ID>'
// If disconnected successfully
{"success": true}
Here are the things that we'll need to do:
- Check if the Cotter access token is valid
- Call Cotter's API to delete a user's Google Access Token
Code & Env Variables
Copy the code from our Github repo.
Add the Cotter Api Keys as environment variables
- Again, we need to add the
API_KEY_ID
andAPI_SECRET_KEY
environment variables from Cotter API Keys.
That's it!
You should now have your backend API set up and Google Sign In set up, all you need to do is connect them in your frontend. If you need some references on how to do that, check out our Github repo:
👉 Try the live demo, it's fully functional
Calendar Booking App by Cotter
Questions & Feedback
Come and talk to the founders of Cotter and other developers who are using Cotter on Cotter's Slack Channel.
Ready to use Cotter?
If you enjoyed this tutorial and want to integrate Cotter into your website or app, you can create a free account and check out our documentation.
If you need help, ping us on our Slack channel or email us at team@cotter.app.
Posted on November 3, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 3, 2020