QwikDev / qwik

Instant-loading web apps, without effort
https://qwik.dev
MIT License
20.82k stars 1.3k forks source link

[🐞] Cannot use environment variables in Auth plugin on Vercel Edge Functions #3962

Closed samijaber closed 1 year ago

samijaber commented 1 year ago

Which component is affected?

Qwik City (routing)

Describe the bug

env.get() is not able to read enviroment variables set in Vercel's UI. I only tested this in serverAuth$, the qwik-auth helper method. Not sure what the scope is exactly.

I also tested process.env while I was at it and it prints nothing in Vercel, but loads of stuff in my local machine (although that might be intended by Vercel and/or QwikCity).

Reproduction

https://github.com/samijaber/qwik-env-var-vercel

Steps to reproduce

import { serverAuth$ } from "@builder.io/qwik-auth";
import GitHub from "@auth/core/providers/github";
import type { Provider } from "@auth/core/providers";

export const { onRequest, useAuthSession, useAuthSignin, useAuthSignout } =
  serverAuth$(({ env }) => {
+    if (!env.get("AUTH_SECRET")) throw new Error("Missing AUTH_SECRET");
    return {
      secret: env.get("AUTH_SECRET"),
      trustHost: true,
      providers: [
        GitHub({
          clientId: env.get("GITHUB_ID")!,
          clientSecret: env.get("GITHUB_SECRET")!,
        }),
      ] as Provider[],
    };
  });

env.get() is returning undefined

System Info

System:
    OS: macOS 12.1
    CPU: (10) arm64 Apple M1 Max
    Memory: 4.16 GB / 32.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 18.13.0 - ~/.asdf/installs/nodejs/18.13.0/bin/node
    Yarn: 1.22.19 - ~/.asdf/installs/nodejs/18.13.0/bin/yarn
    npm: 8.19.3 - ~/.asdf/plugins/nodejs/shims/npm
    Watchman: 2022.02.28.00 - /opt/homebrew/bin/watchman
  Browsers:
    Brave Browser: 112.1.50.121
    Chrome: 112.0.5615.137
    Firefox: 109.0.1
    Safari: 15.2
  npmPackages:
    @builder.io/qwik: 0.105.0 => 0.105.0 
    @builder.io/qwik-auth: ~0.1.0 => 0.1.0 
    @builder.io/qwik-city: ~0.104.0 => 0.104.0 
    undici: 5.22.0 => 5.22.0 
    vite: 4.3.3 => 4.3.3

Additional Information

No response

manucorporat commented 1 year ago

I find vercel env variables super buggy, might need to take a look, i beat it's a vercel bug

ulic75 commented 1 year ago

It's also not likely an auth integration issue specifically.

joshdchang commented 1 year ago

I am having an identical error with env.get. Spent some time debugging and also found that process.env did not work. Same exact code worked fine on Cloudflare pages, so probably a problem with the Vercel integration.

stepaniukm commented 1 year ago

I have very similar issues trying to connect @vercel/kv with Qwik as env variables just don't pop out in neither process.env nor import.meta.env in server side code

gabriiels commented 1 year ago

@samijaber @manucorporat

Hello, a solution to this problem is the following:


define: {
       'process.env': JSON.stringify(process.env)
     }
import { defineConfig } from 'vite';
import { qwikVite } from '@builder.io/qwik/optimizer';
import { qwikCity } from '@builder.io/qwik-city/vite';
import tsconfigPaths from 'vite-tsconfig-paths';

export default defineConfig(({mode}) => {
   return {
     plugins: [qwikCity(), qwikVite(), tsconfigPaths()],
     define: {
       'process.env': JSON.stringify(process.env)
     },
     preview: {
       headers: {
         'Cache-Control': 'public, max-age=600',
       },
     },
   };
});

I had the same problem with this solution it works.

I don't know if this brings any security problem with the environment variables

With this solution the authentication works fine in vercel @ulic75

Author: https://discord.com/channels/842438759945601056/1082474458599657473

rolanday commented 1 year ago

Fyi, I posted the above link (https://discord.com/channels/842438759945601056/1082474458599657473) as quick and dirty to get me going, but, as mentioned, it would be best for somebody on @builder team to take a look because I cannot attest to security implications w/ this approach -- one way or the other, and it's something I'll take a closer look at should I decide to take app to production. This is an issue @builder team should prioritize IMHO since Vercel edge adapter is one of the supported/featured adapters and w/o env vars, real-world apps aren't going to get very far.

stepaniukm commented 1 year ago

Just letting you know, cause I yesterday revisited the problem and suddenly code worked on a Vercel with me changing nothing at all, only thing I’ve done was redeploying my code.

rolanday commented 1 year ago

Doesn't instill a lot of confidence to hear suddenly working -- need to understand why. I can confirm from an unrelated test performed earlier this evening that simply deploying to Vercel edge using Qwik Vercel Edge adapter results in no env vars being set on process. IMO, this is something the adapter should ideally handle "out-of-box" w/ no add'l configuration required, or at least blessed guidance on how to set so we're not needing to guess how to set something as fundamental as environment vars (or just say Vercel edge adapter not supported).

ulic75 commented 1 year ago

Wish I had time to dig in and confirm it, but I suspect this issue isn't directly related to qwik-auth (auth plugin) that just happens to be how it was discovered.

manucorporat commented 1 year ago

This is confusing, because the vercel runtime is not doing what's expected

manucorporat commented 1 year ago

Just letting you know, cause I yesterday revisited the problem and suddenly code worked on a Vercel with me changing nothing at all, only thing I’ve done was redeploying my code.

I have the same experience, their env system is buggy, not sure why it works sometimes and sometimes it doesnt, without changing anything

manucorporat commented 1 year ago

i have no idea how to solve this issue, we are implementing the adapter exactly how described by vercel documentation. their runtime is not setting the environment variables (sometimes).

manucorporat commented 1 year ago

Curious how are you setting the environment variables?

stepaniukm commented 1 year ago

I use 2 ways, one was using connect with storages which auto-injected envs into my project, second was adding manually some test envs via Vercel UI. The result was basically the same, all variables were present in the dashboard, but back then code didn't work and now it works.

shairez commented 1 year ago

CCing @Schniz maybe he could help with this

stepaniukm commented 1 year ago

Yeah, I don't know what he did on the Vercel site, but now the behavior is actually predictable, as when logging process.env I consistently get all needed env variables.

Schniz commented 1 year ago

@stepaniukm we will soon release a changelog :)

Schniz commented 1 year ago

https://vercel.com/changelog/more-flexible-environment-variables-in-edge-functions-and-middleware

I think this issue can be closed now 🙏

hamatoyogi commented 1 year ago

@manucorporat can we confirm that this issue is fixed?

Schniz commented 1 year ago

env.get("AUTH") will work, process.env depends on #4361 (or similar approaches)

jesperp commented 1 year ago

I spent an entire evening pulling my hair on this issue but with vercel postgres. @vercel/postgres uses process.env.POSTGRES_URL (which is undefined in production). This worked for me (explicitly setting the connection string instead of relying on implicit behavior):

import { drizzle } from "drizzle-orm/vercel-postgres";
import { createPool } from "@vercel/postgres";
import * as schema from "./schema";

const pool = createPool({
  connectionString: process.env["POSTGRES_URL"],  // Use bracket syntax, not dot notation! 
});

export const db = drizzle(pool, { schema, });
gioboa commented 1 year ago

Thanks @jesperp So it's something related to Vercel environment. I found this useful change log, I saw this post was mentioned by @Schniz few message ago.

TLDR: Accessing process.env is no longer restricted to be statically analyzable. This means that, for example, you can now compute variable names such as process.env[${PREFIX}_SECRET]

gioboa commented 1 year ago

I cerated a new fresh Qwik 1.2.7 application and I deployed it with Vercel Edge. I can confirm that only with process.env[''] works.

Schniz commented 1 year ago

As mentioned previously, it’s probably related to the Qwik Vercel Edge adapter. Internally at Vercel we do not distinct between process.env.VAR and process.env[‘VAR’], they are the same because we simply populate process.env as an object. As mentioned a while ago, I believe that the compiler configurations happening at Vite (configured by the adapter) are misconfigured

gioboa commented 1 year ago

Having the ability to use env vars like that process.env['<env_name>'] is good enough to close this issue. I will create a PR to add this information in the Qwik docs.