diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..20de9e7 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,17 @@ +name: Deploy to cloudflare worker +"on": + push: + branches: + - main + workflow_dispatch: + +jobs: + deploy: + runs-on: ubuntu-latest + name: Deploy + steps: + - uses: actions/checkout@v3 + - name: Publish + uses: cloudflare/wrangler-action@v3 + with: + apiToken: ${{ secrets.CF_API_TOKEN }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..403aa43 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.dev.vars +.wrangler + +/node_modules \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..38baa1f --- /dev/null +++ b/README.md @@ -0,0 +1,56 @@ +# cloudflare-worker-github-oauth-login + +> A Cloudflare Worker + GitHub Pages Login Example + +The [github-oauth-login.js](github-oauth-login.js) file is a [Cloudflare Worker](https://workers.cloudflare.com/) which is continuously deployed using GitHub Actions (see [.github/workflows/deploy.yml](.github/workflows/deploy.yml)). + +The worker does 3 things + +1. When you open the worker URL, it will redirect to the OAuth App's login URL on github.com ([example](https://github-oauth-login.gr2m.workers.dev)). +2. It accepts a `POST` request with the OAuth `code` retrieved from the OAuth callback redirect and returns an OAuth access token in return +3. It enables CORS. + +The [index.html](index.html) file is a demo of a "Login with GitHub" app, you can see the demo at [gr2m.github.io/cloudflare-worker-github-oauth-login/index.html](https://gr2m.github.io/cloudflare-worker-github-oauth-login/index.html). Look at its source code. If something is unclear, please feel free to [open an issue](https://github.com/gr2m/cloudflare-worker-github-oauth-login/issues) or [ping me on twitter](https://twitter.com/gr2m). + +## Step-by-step instructions to create your own + +Note that you require access to the new GitHub Actions for the automated deployment to work. + +1. [Create a GitHub App](https://developer.github.com/apps/building-github-apps/creating-a-github-app/) or [GitHub OAuth App](https://developer.github.com/apps/building-oauth-apps/creating-an-oauth-app/) +1. Fork this repository +1. [Create a Cloudflare account](https://dash.cloudflare.com/) (it's free!) if you don't have one yet. +1. Install the `wrangler` CLI and login with your account + + ``` + npm install --global wrangler + wrangler login + ``` + +1. Edit the `wrangler.toml` file, change the value for `account_id` to your own ([select your account](https://dash.cloudflare.com/), then find your Account ID at the bottom of the side bar) +1. Add the following secrets to your Cloudflare worker: + + - `CLIENT_ID`, `CLIENT_SECRET`: In your GitHub (OAuth) App's settings page, find `Client ID` and `Client SECRET` + + ``` + wrangler secret put CLIENT_ID + wrangler secret put CLIENT_SECRET + ``` + +1. Add the following secret in your fork's repository settings: + - `CF_API_TOKEN`: [Create a new token](https://dash.cloudflare.com/profile/api-tokens), use the "Edit Cloudflare Workers" template +1. Enable GitHub Pages in your repository settings, select `Source` to be the `master branch`. +1. In [index.html](index.html), replace the `gr2m` workers subdomain with your own, in `WORKER_URL` and the login `` tag. + +That should be it. The `github-oauth-login.js` file will now be continously deployed to Cloudflare each time there is a commit to master. + +## See also + +- [Cloudflare Worker GitHub App Example](https://github.com/gr2m/cloudflare-worker-github-app-example/#readme) + +## Credits + +The OAuth App Avatar and this repository's social preview are using [@cameronmcefee](https://github.com/cameronmcefee)'s [cloud](https://octodex.github.com/cloud/) Octodex graphic :octocat:💖 + +## License + +[ISC](LICENSE) diff --git a/decap-cms-login-script.js b/decap-cms-login-script.js new file mode 100644 index 0000000..6bb5532 --- /dev/null +++ b/decap-cms-login-script.js @@ -0,0 +1,23 @@ +// Original version – https://github.com/vencax/netlify-cms-github-oauth-provider/blob/master/login_script.js +export default function (token) { + return ``; +} diff --git a/index.ts b/index.ts new file mode 100644 index 0000000..6ec8ba2 --- /dev/null +++ b/index.ts @@ -0,0 +1,53 @@ +import decapCMSLoginScript from './decap-cms-login-script'; + +addEventListener('fetch', (event: any) => { + event.respondWith(handle(event.request)); +}); + +// Inserted as secrets to the worker +// @ts-ignore +const client_id = CLIENT_ID; +// @ts-ignore +const client_secret = CLIENT_SECRET; + +async function handle(request: Request) { + const { pathname, searchParams: params } = new URL(request.url); + + switch (pathname) { + case '/auth': + return redirectToAuthFlow(); + + case '/callback': + return await fetchAccessToken(params); + } +} + +async function fetchAccessToken(requestParams: URLSearchParams) { + const code = requestParams.get('code'); + + const response = await fetch('https://github.com/login/oauth/access_token', { + method: 'POST', + headers: { + 'content-type': 'application/json', + 'user-agent': 'decap-cms-github-oauth-api-cloudflare', + accept: 'application/json', + }, + body: JSON.stringify({ client_id, client_secret, code }), + }).then((res) => res.json()); + + const loginResponse = decapCMSLoginScript(response.access_token); + + return new Response(loginResponse, { + status: 201, + headers: { + 'Content-Type': 'text/html;charset=UTF-8', + }, + }); +} + +function redirectToAuthFlow() { + return Response.redirect( + `https://github.com/login/oauth/authorize?client_id=${client_id}`, + 302 + ); +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..14fa58f --- /dev/null +++ b/package.json @@ -0,0 +1,9 @@ +{ + "name": "decap-cms-github-oauth-api-cloudflare-worker", + "version": "1.0.0", + "private": true, + "description": "Github login gateway for use with Decap CMS, configured for Cloudflare Worker environment", + "main": "index.ts", + "author": "Ott Martens", + "repository": "github:ottmartens/decap-cms-github-oauth-api-cloudflare" +} \ No newline at end of file diff --git a/wrangler.toml b/wrangler.toml new file mode 100644 index 0000000..36849bb --- /dev/null +++ b/wrangler.toml @@ -0,0 +1,7 @@ +name = "github-oauth-login" +main = "index.ts" + +compatibility_date = "2023-11-11" + +account_id = "c192ee4c911d964935f8f53ac8399ae9" +workers_dev = true