How to Conditionally Render Home Page in Server Component with App Router
Unanswered
Forest bachac posted this in #help-forum
Forest bachacOP
I'm trying to conditionally render the home page based on the user's authenticated state. I'm using Amplify with Cognito for authentication. Amplify has a method called Auth.currentAuthenticatedUser() which returns the user and if there's no user, it'll be empty.
Problem is when I go to home page, <NotAuthHome></NotAuthHome> is rendered which is good, then after logging in <NotAuthHome></NotAuthHome> is still rendered until I refresh the home page. After refreshing the home page, the correct <AuthHome></AuthHome> renders.
I tried turning the method into a dynamic one by making sure I'm using the cookies() method (which successfully gets the cookies), but it doesn't update the "user" after redirecting from the Cognito hosted UI back to localhost:3000/ the user is undefined even though getUser runs again
Problem is when I go to home page, <NotAuthHome></NotAuthHome> is rendered which is good, then after logging in <NotAuthHome></NotAuthHome> is still rendered until I refresh the home page. After refreshing the home page, the correct <AuthHome></AuthHome> renders.
I tried turning the method into a dynamic one by making sure I'm using the cookies() method (which successfully gets the cookies), but it doesn't update the "user" after redirecting from the Cognito hosted UI back to localhost:3000/ the user is undefined even though getUser runs again
import NotAuthHome from "@/app/NotAuthHome";
import {Auth} from "aws-amplify";
import { withSSRContext } from 'aws-amplify';
import AuthHome from "@/app/AuthHome";
import {cookies, headers} from "next/headers";
import { Amplify } from "aws-amplify";
import awsAmplifyConfig from "../awsAmplifyConfig";
Amplify.configure({
...awsAmplifyConfig,
ssr: true
});
const getUser = async () => {
let user = undefined;
const cookieStore = cookies()
let getAllCookies;
if (cookieStore) {
getAllCookies = cookieStore.getAll();
} else {
// Handle the case when cookieStore is undefined
console.error("Error: cookieStore is undefined");
}
const req = {
headers: {
cookie: getAllCookies,
},
};
const SSR = withSSRContext({ req })
try {
user = await SSR.Auth.currentAuthenticatedUser();
} catch (err) {
}
return user;
}
//want to render home page on server for SEO
export default async function Home() {
const user = await getUser();
console.log("running Home" + user);
return (
<>
{user ? <AuthHome></AuthHome> : <NotAuthHome></NotAuthHome>}
</>
)4 Replies
American Curl
I've had quite some headaches with this 😄 Basically, what I'm doing (not using AWS cognito but this should work with any provider) is to set up an authentication context (https://codevoweb.com/setup-react-context-api-in-nextjs-13-app-directory/) which I'm wrapping my application with. Inside that context, I am listening to auth change events.
I'm using supabase so what I can do in the root layout (server component) is check if there is an ongoing session and pass that to my auth context. So on first render, the app already knows if you're authenticated without having to fetch anything - so the first render will show the authenticated home screen right away
I'm using supabase so what I can do in the root layout (server component) is check if there is an ongoing session and pass that to my auth context. So on first render, the app already knows if you're authenticated without having to fetch anything - so the first render will show the authenticated home screen right away
Forest bachacOP
Here is more info if anyone knows how to handle this
1. User clicks login and gets redirected to hosted UI to login
2. User logs in and gets redirected to home page with a code in the url parameter like localhost/code=codehere
3. The get request to localhost/code=codehere causes the home page on next.js to render the page.js and shows <NotAuthHome> because the cookies were not set yet
4. Post request is sent to oauth2/token endpoint in cognito passing in the authorization code, so we get the tokens/cookies
5. Then by manually refreshing the page, the request to localhost/ has the cookies in the header now so it renders <AuthHome>
How does next.js handle redirects like this for authentication with cookies with ouath 2.0 where you have to wait for the authorization code to be exchanged for cookies?
1. User clicks login and gets redirected to hosted UI to login
2. User logs in and gets redirected to home page with a code in the url parameter like localhost/code=codehere
3. The get request to localhost/code=codehere causes the home page on next.js to render the page.js and shows <NotAuthHome> because the cookies were not set yet
4. Post request is sent to oauth2/token endpoint in cognito passing in the authorization code, so we get the tokens/cookies
5. Then by manually refreshing the page, the request to localhost/ has the cookies in the header now so it renders <AuthHome>
How does next.js handle redirects like this for authentication with cookies with ouath 2.0 where you have to wait for the authorization code to be exchanged for cookies?
Forest bachacOP
Going to fix this by rendering parts of the home page client-side that rely on knowing if the user is authenticated and the rest of the home page that needs SEO etc. can be server side