Next.js Discord

Discord Forum

Pass environment variables to client component from server component

Unanswered
Asiatic Lion posted this in #help-forum
Open in Discord
Asiatic LionOP
I am using Microsoft Entra ID OAuth for authorization in my app using the MSAL for React client library (though this question is not at all MSAL specific). This requires a configuration object containing the OAuth client ID and redirect URI to be immediately available on the client side so that an MSAL PublicClientApplication can be created and passed into the MsalProvider context provider value. I am deploying through a container image. It is important the client ID and redirect URI are specified as environment variables and not inlined into the build so that a single image can be built once and configured depending on its environment. This currently looks as follows
"use client";
<...>
export function LayoutBody({ children }: Readonly<{ children: React.ReactNode, msalConfig: any }>) {
  const instance = useRef<PublicClientApplication>(new PublicClientApplication(msalConfig));

  return (
    <MsalProvider instance={instance.current}>
      <...>
      {children}
      <...>
    </MsalProvider>
  );
}


It is not possible to have a useEffect in this layout body because MsalProvider only accepts a fully constructed PublicClientApplication instance; it is not possible to pass null or undefined. I want to be able to pass the client ID and redirect URI as props to the client LayoutBody component from a parent server component layout. So, I made the server component below
export default function RootLayout({ children }: Readonly<{ children: React.ReactNode }>) {
  msalConfig = {
    authority: ...,
    clientId: process.env.AZURE_CLIENT_ID,
    redirectUri: process.env.FQDN
  };
  
  return (
    <html lang="en" {...mantineHtmlProps}>
      <head>
        <title>Design Vault</title>
        <ColorSchemeScript defaultColorScheme="light" forceColorScheme="light" />
      </head>
      <body className={classes.body}>
        <LayoutBody msalConfig={}>{children}</LayoutBody>
      </body>
    </html>
  );
}

2 Replies

Asiatic LionOP
The console logs show that clientId and redirectUri have been correctly populated in both the server and client component during the build. When I load the page in a browser, I can see in the server console logs show correct values for clientId and redirectUri. However, when the client hydrates, the values are empty. Any reason why that could be?
Burmese
only NEXT_PUBLIC_ prefixed vars are available on the client - and it is made possible by inlining those values into your built code. If you want to be able to change the config value at boot time, you must not prefix it, which means it will not be available on the client. The only to make it available in the browser is to explicitly fetch it from the backend