diff --git a/packages/api/src/auth/index.ts b/packages/api/src/auth/index.ts index ecb189696aa7..9e843c56118f 100644 --- a/packages/api/src/auth/index.ts +++ b/packages/api/src/auth/index.ts @@ -76,6 +76,7 @@ export const getAuthenticationContext = async ({ } const { schema, token } = parseAuthorizationHeader(event) + console.log(`👉 \n ~ file: index.ts:79 ~ token:`, token) let authDecoders: Array = [] diff --git a/packages/auth-providers/dbAuth/api/src/decoder.ts b/packages/auth-providers/dbAuth/api/src/decoder.ts index 0657a2b622fa..58b12c962bb4 100644 --- a/packages/auth-providers/dbAuth/api/src/decoder.ts +++ b/packages/auth-providers/dbAuth/api/src/decoder.ts @@ -10,6 +10,7 @@ export const createAuthDecoder = (cookieNameOption: string): Decoder => { return null } + // @TODO for SSR we need to make sure we are passing the cookie from the FE to the BE const session = dbAuthSession(req.event, cookieNameOption) const authHeaderUserId = token diff --git a/packages/auth/src/AuthProvider/AuthProvider.tsx b/packages/auth/src/AuthProvider/AuthProvider.tsx index b4a5d9a20d29..01fdb54b80d8 100644 --- a/packages/auth/src/AuthProvider/AuthProvider.tsx +++ b/packages/auth/src/AuthProvider/AuthProvider.tsx @@ -1,11 +1,12 @@ import type { ReactNode } from 'react' -import React, { useEffect, useState } from 'react' +import React, { useContext, useEffect, useState } from 'react' import type { AuthContextInterface, CurrentUser } from '../AuthContext' import type { AuthImplementation } from '../AuthImplementation' import type { AuthProviderState } from './AuthProviderState' import { defaultAuthProviderState } from './AuthProviderState' +import { ServerAuthContext } from './ServerAuthProvider' import { useCurrentUser } from './useCurrentUser' import { useForgotPassword } from './useForgotPassword' import { useHasRole } from './useHasRole' @@ -82,9 +83,11 @@ export function createAuthProvider< }: AuthProviderProps) => { // const [hasRestoredState, setHasRestoredState] = useState(false) + const serverAuthState = useContext(ServerAuthContext) + const [authProviderState, setAuthProviderState] = useState< AuthProviderState - >(defaultAuthProviderState) + >(serverAuthState || defaultAuthProviderState) const getToken = useToken(authImplementation) diff --git a/packages/auth/src/AuthProvider/ServerAuthProvider.tsx b/packages/auth/src/AuthProvider/ServerAuthProvider.tsx new file mode 100644 index 000000000000..c2b3de4f7ee9 --- /dev/null +++ b/packages/auth/src/AuthProvider/ServerAuthProvider.tsx @@ -0,0 +1,10 @@ +import React from 'react' + +import type { AuthProviderState } from './AuthProviderState' +import { defaultAuthProviderState } from './AuthProviderState' + +export const ServerAuthContext = React.createContext< + AuthProviderState | undefined +>(defaultAuthProviderState) + +export const ServerAuthProvider = ServerAuthContext.Provider diff --git a/packages/auth/src/index.ts b/packages/auth/src/index.ts index b06907f98619..91be3a01fc54 100644 --- a/packages/auth/src/index.ts +++ b/packages/auth/src/index.ts @@ -2,3 +2,5 @@ export { AuthContextInterface, CurrentUser } from './AuthContext' export { useNoAuth, UseAuth } from './useAuth' export { createAuthentication } from './authFactory' export type { AuthImplementation } from './AuthImplementation' + +export * from './AuthProvider/ServerAuthProvider' diff --git a/packages/vite/src/streaming/createReactStreamingHandler.ts b/packages/vite/src/streaming/createReactStreamingHandler.ts index 63de73f4a261..47400c6555a4 100644 --- a/packages/vite/src/streaming/createReactStreamingHandler.ts +++ b/packages/vite/src/streaming/createReactStreamingHandler.ts @@ -50,6 +50,8 @@ export const createReactStreamingHandler = async ( }) } + let decodedAuthState + // Do this inside the handler for **dev-only**. // This makes sure that changes to entry-server are picked up on refresh if (!isProd) { @@ -59,6 +61,12 @@ export const createReactStreamingHandler = async ( fallbackDocumentImport = await viteDevServer.ssrLoadModule( rwPaths.web.document ) + + const middleware = entryServerImport.middleware + + if (middleware) { + decodedAuthState = await middleware(req) + } } const ServerEntry = @@ -112,6 +120,7 @@ export const createReactStreamingHandler = async ( cssLinks, isProd, jsBundles, + authState: decodedAuthState, }, { waitForAllReady: isSeoCrawler, diff --git a/packages/vite/src/streaming/streamHelpers.ts b/packages/vite/src/streaming/streamHelpers.ts index e92e9038c624..62133427ddd6 100644 --- a/packages/vite/src/streaming/streamHelpers.ts +++ b/packages/vite/src/streaming/streamHelpers.ts @@ -7,6 +7,8 @@ import type { ReactDOMServerReadableStream, } from 'react-dom/server' +import { ServerAuthProvider } from '@redwoodjs/auth' +import type { AuthProviderState } from '@redwoodjs/auth/src/AuthProvider/AuthProviderState' import type { TagDescriptor } from '@redwoodjs/web' // @TODO (ESM), use exports field. Cannot import from web because of index exports import { @@ -26,6 +28,7 @@ interface RenderToStreamArgs { cssLinks: string[] isProd: boolean jsBundles?: string[] + authState?: AuthProviderState | undefined } interface StreamOptions { @@ -46,7 +49,9 @@ export async function reactRenderToStreamResponse( cssLinks, isProd, jsBundles = [], + authState, } = renderOptions + console.log(`👉 \n ~ file: streamHelpers.ts:54 ~ authState:`, authState) if (!isProd) { // For development, we need to inject the react-refresh runtime @@ -84,15 +89,21 @@ export async function reactRenderToStreamResponse( const renderRoot = (path: string) => { return React.createElement( - ServerHtmlProvider, + ServerAuthProvider, { - value: injectToPage, + value: authState, }, - ServerEntry({ - url: path, - css: cssLinks, - meta: metaTags, - }) + React.createElement( + ServerHtmlProvider, + { + value: injectToPage, + }, + ServerEntry({ + url: path, + css: cssLinks, + meta: metaTags, + }) + ) ) } diff --git a/packages/web/src/components/ServerInject.tsx b/packages/web/src/components/ServerInject.tsx index ae5e5b214c71..225614db6dbf 100644 --- a/packages/web/src/components/ServerInject.tsx +++ b/packages/web/src/components/ServerInject.tsx @@ -70,14 +70,3 @@ export function useServerInsertedHTML(callback: () => React.ReactNode): void { addInsertedServerHTMLCallback(callback) } } - -// @TODO use this in streamHelpers final block -export const AppendToHead = ({ tagsToAppend }: { tagsToAppend: string }) => { - return ( -