( ◕◡◕)っ Cloudflare Workers Google OAuth
This is a companion repository for the blog post at Apiumhub :: Tech blog.
In the blog post, we go though the code that OAuth-s a user and uses a Google API for that user. We'll be developing this app that lists, based on a query, the files in that user's Google Drive. Like so:
One picture summary
Generated with sequencediagram.org
title Sequence of requests
Client->Cloudflare Worker: GET / note left of Cloudflare Worker: The client is unauthenticated Cloudflare Worker-->Client: Redirect to Google Sign in Client->Google API: Ask for permission Google API-->Client: Prompt to sign in Client->Google API: Grant permissions activate Google API note left of Google API: Google now\nhas a session\nfor the user Google API-->Client: Go back to the Cloudflare Worker with a
token
Client->Cloudflare Worker: GET /auth with acode
Cloudflare Worker->Google API: Exchangecode
for atoken
Google API-->Cloudflare Worker: a token activate Cloudflare Worker note left of Cloudflare Worker: An auth is stored in the KV with the code Cloudflare Worker-->Client: Go back to the original request with the auth cookie Client->Cloudflare Worker: GET / note left of Cloudflare Worker: Now the client is autenticated Cloudflare Worker->Google API: Get files Google API-->Cloudflare Worker: A list of files Cloudflare Worker-->Client: An HTML with a list of files expandable− logout Client->Cloudflare Worker: GET /logout Cloudflare Worker->Google API: Logout deactivate Google API Google API-->Cloudflare Worker: OK deactivate Cloudflare Worker Cloudflare Worker-->Client: OK end
A more detail explanation of how Google Sign in should behave can be found in Google's docs: Using OAuth 2.0 for Web Server Applications.
Requirements
- wrangler 1.17 or newer.
- A Cloudflare account.
- A Google Services account
- With the API you wish to consume enabled. e.g: https://console.developers.google.com/apis/api/drive.googleapis.com/overview
- A Google OAuth Client ID and Secret, from the Credentials > + Create credentials > Oauh client ID. _Note: "Authorized redirect URIs" should have your cloudflare worker url with
/auth
at the end, and optionalyhttp://127.0.0.1:8787/auth
to work locally.
Setup wrangler
- Clone this template:
wrangler generate [a name] https://github.com/jazcarate/cloudflare-worker-google-oauth
. - Update the worker's secrets with the ones generated by creating the
Credentials
in the Google Service Account:wrangler secret put CLIENT_ID [your client id]
wrangler secret put CLIENT_SECRET [your client secret]
- Create a
KV
namespace:wrangler kv:namespace create "authTokens"
and update thewrangler.toml
accordingly.
Ideas to grow this project
If you would like to use this setups as a starting point to develop interesting things; I recommend trying out one (or all!) of this improvements:
- Create a middleware pattern to deaal with authenticated and unauthenticated endpoints
- Serve static content, either with Cloudflare Sites, or reading local files in a Worker. A default path could be implemented to serve files in
public/
folder. - Improve the rendered HTML with a template library, or roll up your own!
- Use another Google API from the list.
Glossary
Throughout this project there are two somewhat similar, but distincts concepts:
- Google's
code
: Is a one time code that is quickly exchanged with Google for atoken
👇 . token
: Is the authentication method for Google.auth
: Is the authentication method for this Worker.
The app deals with both, in very different ways; and it is the KV
that provides a one way transformation between auth
to token
.
Contributing
If you think that you can improve the code, or the explanation; feel free to drop a pull request or a comment; but please keep in mind that the purpose of this is educational.
Developing
Once the requirements are fulfilled, simply run npm run dev
.
The server will default to running at 127.0.0.1:8787.
Testing
Rn npm test
for jest tests.
Publishing
Run npm run publish
to lint, build and publish to your Cloudflare Worker!
⚠️ Caveats
Some wrangler dev
) or in the cloud; as wrangler dev
reweites the request.url
to always match the environment.