Dan6erbond / sk-auth

Authentication library for use with SvelteKit featuring built-in OAuth providers and zero restriction customization!
MIT License
578 stars 70 forks source link

Support Cloudflare Workers #78

Open hmnd opened 2 years ago

hmnd commented 2 years ago

fixes #42

vhscom commented 2 years ago

Confirmed this addresses the Cloudflare deployment issue. @hmnd I noticed Cloudflare Pages doesn't like when dotenv is used, presumably because the Functions (Workers) beta uses Service Workers and not Node for edge caching and efficiency purposes. That said, do you have any tips for managing secrets using VITE_ to help ensure they're not leaked?

websocket98765 commented 2 years ago

@vhscom Rich Harris said in a video that a better env variable story is on the roadmap--so a workaround like this may be sufficient for now.

Github Pages supports specifying environmental variables via the web UI. Maybe a solution is to only use .env.local for development (not .env) and require developers to specify env variables in production and consume them like from process.env.MYVAR if in production (i.e. process.env.NODE_ENV === 'production')?

VITE_ should be ok for now as long the dev doesn't use to import secrets into client side code. But not worth blocking on this.

websocket98765 commented 2 years ago

@Dan6erbond would it be possible to merge this please? It would unblock anyone using Cloudflare

hmnd commented 2 years ago

Confirmed this addresses the Cloudflare deployment issue. @hmnd I noticed Cloudflare Pages doesn't like when dotenv is used, presumably because the Functions (Workers) beta uses Service Workers and not Node for edge caching and efficiency purposes. That said, do you have any tips for managing secrets using VITE_ to help ensure they're not leaked?

Sorry for not responding to this sooner.

For Cloudflare Workers Sites, env variables are provided as global variables. The way I would handle that is wrap the dotenv import in an if block, checking whether you're in a dev environment.

For Cloudflare Pages, env variables are provided in event.platform.env. So in that case you could add whatever env variables you need to locals in your hooks file, to make them accessible to any endpoints without exposing to clients.

Anyway, I don't really think that question is relevant to whether this PR can be merged, so would be awesome if it could be ;).

RichiCoder1 commented 2 years ago

Would love to see this merged, planning to push out a PoC w/ SvelteKit and Auth and this looks like it'll be a blocker for that (planning to push to either vercel edge or cloudflare pages).

Worth noting this will fix a bunch of other current and future edge providers too. (See https://wintercg.org/ for more deets on that)

hmnd commented 2 years ago

@RichiCoder1 if it helps, I have this PR published at @icewolf/sk-auth@0.4.1-bleeding.7

vhscom commented 2 years ago

I've also rolled this change into a fork published to NPM. If you're using PMPM you can adjust the module source for sk-auth to use the fork as shown here. Please note my laptop is in for repair so I'm not taking any patch requests to the fork. But it can serve current CF needs.

websocket98765 commented 2 years ago

@hmnd Thanks! I'm getting a Cloudflare "Error 1101" "Worker threw exception" on Cloudflare Pages when redirecting back to the site at /api/auth/signin/github?redirect=/dashboard. It doesn't seem to have a way to view logs for details. Any ideas? Using @icewolf/sk-auth at 0.4.1-bleeding.7

RichiCoder1 commented 2 years ago

@hmnd Thanks! I'm getting a Cloudflare "Error 1101" "Worker threw exception" on Cloudflare Pages when redirecting back to the site at /api/auth/signin/github?redirect=/dashboard. It doesn't seem to have a way to view logs for details. Any ideas? Using @icewolf/sk-auth at 0.4.1-bleeding.7

In the Workers UI, there's a way to live stream worker console.log statements via the Console. I would investigate that and see if you can try/catch the exception.

websocket98765 commented 2 years ago

Just checked. Unfortunately log streaming is only available for standard workers. When deploying via Cloudflare Pages, Svelte Kit's workers don't appear under Workers tab in the Cloudflare Dash, so log streaming isn't available.

websocket98765 commented 2 years ago

Is this the how you all do env vars in production? Maybe this is where I'm messing up. I have them specified in Cloudflare env settings, in the same way as NODE_VERSION is specified in Cloudflare for Svelte Kit to work:

  providers: [
    new GitHubOAuth2Provider({
      clientId: process.env.GITHUB_OAUTH_CLIENT_ID ?? import.meta.env.VITE_GITHUB_OAUTH_CLIENT_ID,
      clientSecret:
        process.env.GITHUB_OAUTH_CLIENT_SECRET ?? import.meta.env.VITE_GITHUB_OAUTH_CLIENT_SECRET,
      profile(profile) {
        return { ...profile, provider: 'github' };
      }
    })
  ],
RichiCoder1 commented 2 years ago

Is this the how you all do env vars in production? Maybe this is where I'm messing up. I have them specified in Cloudflare env settings, in the same way as NODE_VERSION is specified in Cloudflare for Svelte Kit to work:

  providers: [
    new GitHubOAuth2Provider({
      clientId: process.env.GITHUB_OAUTH_CLIENT_ID ?? import.meta.env.VITE_GITHUB_OAUTH_CLIENT_ID,
      clientSecret:
        process.env.GITHUB_OAUTH_CLIENT_SECRET ?? import.meta.env.VITE_GITHUB_OAUTH_CLIENT_SECRET,
      profile(profile) {
        return { ...profile, provider: 'github' };
      }
    })
  ],

Ahh, that might be it! Cloudflare variables work different than traditional node environments. Details here: https://developers.cloudflare.com/workers/platform/environment-variables/. TL;DR: In cloudflare, they become globals and you reference them like globalThis.GITHUB_OAUTH_CLIENT_ID. (globalThis just being a modern way like window to access globals in node and worker environments)

websocket98765 commented 2 years ago

No luck; thanks though. globalThis appears to be "coming soon" for Cloudflare Workers. When I tested it today, globalThis.NODE_VERSION returns undefined and same for globalThis.GITHUB_OAUTH_CLIENT_ID which contained "undefined" in the URL after redirecting to Github.

process.env.NODE_VERSION returns the Node version when I tried printing in my index.svlete, but globalThis.NODE_VERSION was undefined. So I guess it's not this afterall.

@hmnd What's the proper way to consume your fork in my package.json and imports (the below?)? I finally found a useful error message on a Cloudflare preview deploy, which didn't appear on production: Cannot destructure property 'get' of 'appAuth' as it is undefined. Edit: for NPM.

// package.json
"devDependencies": {
    "@icewolf/sk-auth": "^0.4.1-bleeding.7",
     //...
 }       
// appAuth.js
import { SvelteKitAuth } from '@icewolf/sk-auth';
import { GitHubOAuth2Provider } from '@icewolf/sk-auth/providers';