K
Kinde•3mo ago
zor

Next.js - Middleware for Kinde & Redirect to login page

Hi, I'm coming from a Kinde competitor, I love Kinde. It has many more advantage for me also how it already includes the 2FA. I am using Next.js 14 I want to redirect user to login page directly. Docs says 💡 As of right now the middleware in the app router does not work when trying to redirect to api/auth/login. This is because of Next.js caching which causes issues during authentication.. So do I have to put
const { isAuthenticated, isLoading } = useKindeBrowserClient();

if (isLoading)
return (
<div>Loading...</div>
)
return isAuthenticated ? (
<div>You can see this page.</div>
) : (
<div>
You have to <LoginLink>Login</LoginLink> to see this page.
</div>
const { isAuthenticated, isLoading } = useKindeBrowserClient();

if (isLoading)
return (
<div>Loading...</div>
)
return isAuthenticated ? (
<div>You can see this page.</div>
) : (
<div>
You have to <LoginLink>Login</LoginLink> to see this page.
</div>
every page.tsx? Also redirect to sign in would be better UX for. So isn't that possible to use Middleware for my situation?
9 Replies
Oli - Kinde
Oli - Kinde•3mo ago
Hey @zor, Thanks for considering Kinde. I will get back to you on this NextJS query. Hey @zor, Hello, I'm glad to hear you're enjoying Kinde and its features, including 2FA! Regarding your question about redirecting users to the login page directly in a Next.js 14 environment, you're correct in noting the current limitation with middleware due to Next.js caching, which affects the ability to use middleware for redirection to api/auth/login. However, you can still achieve a direct redirect to the login page without having to manually check authentication status on every page. Instead of placing the authentication check in every page.tsx file, you can utilize the getKindeServerSession method on the server side to check if a user is authenticated and redirect them if they are not. Here's an example of how you can do this in your getServerSideProps:
// In your page file
import { getKindeServerSession } from "@kinde-oss/kinde-auth-nextjs/server";
import { redirect } from "next/navigation";

export async function getServerSideProps(context) {
const { isAuthenticated } = getKindeServerSession(context.req, context.res);

if (!(await isAuthenticated())) {
return {
redirect: {
destination: "/api/auth/login?post_login_redirect_url=/protected",
permanent: false,
},
};
}

return { props: {} }; // Return props as usual if the user is authenticated
}
// In your page file
import { getKindeServerSession } from "@kinde-oss/kinde-auth-nextjs/server";
import { redirect } from "next/navigation";

export async function getServerSideProps(context) {
const { isAuthenticated } = getKindeServerSession(context.req, context.res);

if (!(await isAuthenticated())) {
return {
redirect: {
destination: "/api/auth/login?post_login_redirect_url=/protected",
permanent: false,
},
};
}

return { props: {} }; // Return props as usual if the user is authenticated
}
This approach uses getServerSideProps to check the authentication status server-side before the page is rendered. If the user is not authenticated, they are redirected to the login page. You can adjust the destination in the redirect object to include a post_login_redirect_url parameter, specifying where the user should be redirected after successfully logging in. This method provides a better user experience by automatically redirecting unauthenticated users to the login page without requiring manual checks on each page or displaying conditional content in the client-side component. Remember, this approach works well for pages that are rendered server-side (getServerSideProps). For client-side navigation or pages using Static Site Generation (getStaticProps), you might need to handle authentication checks differently. Let me know if you need further assistance or have any more questions!
zor
zor•3mo ago
Clerk was working well for me by using just middleware.js to protect every page except the landing page. I'm not very experienced, so I apologize if this seems like a basic question, but I felt that directly protecting every page provided better stability. Is this a proper solution, and would it be proper way to follow continue using Kinde in this way? I'm a bit confused and trying to determine if Kinde is the right authentication solution for my project. Your guidance and personal perspective on this, would be appreciated. Also, I'm using Convex as my backend(BaaS).(https://www.convex.dev) To give some context, imagine a fintech solution like Square (https://squareup.com). Would Kinde integrate well with that kind of application?
Convex | The fullstack TypeScript development platform
The backend application platform with everything you need to build your product.
Oli - Kinde
Oli - Kinde•3mo ago
Hi @zor, Absolutely, your question is valid, and I'm here to help clarify things for you. With Kinde, you can indeed protect your application routes in a manner similar to what you've described with Clerk, using middleware to automatically handle authentication across your pages. This is a common and effective approach to ensure that your application's pages are accessible only to authenticated users, providing a secure and seamless user experience. For Next.js applications, Kinde offers middleware support that allows you to protect your routes efficiently. You can use the authMiddleware from @kinde-oss/kinde-auth-nextjs/server in your middleware.js file to protect your routes. This middleware can be configured to match specific routes, excluding any that you wish to remain publicly accessible, such as your landing page. Here's a simplified example:
// Inside your src/middleware.js file
import {authMiddleware} from "@kinde-oss/kinde-auth-nextjs/server";

export const config = {
matcher: [
// Match all request paths except for the ones you want to exclude
"/((?!your_landing_page_path).*)"
]
};

export default authMiddleware;
// Inside your src/middleware.js file
import {authMiddleware} from "@kinde-oss/kinde-auth-nextjs/server";

export const config = {
matcher: [
// Match all request paths except for the ones you want to exclude
"/((?!your_landing_page_path).*)"
]
};

export default authMiddleware;
This setup will ensure that all pages except for the specified exclusions (like your landing page) require authentication, redirecting unauthenticated users to the login page automatically. Regarding your use of Convex as your backend, integrating Kinde for authentication should not interfere with your backend setup. Kinde acts primarily on the frontend and middleware layers to manage authentication states, user sessions, and secure access to your pages. You would still interact with Convex for your backend needs, such as database interactions, serverless functions, etc. In summary, using Kinde to protect your routes with middleware is a proper and recommended approach. It offers a streamlined way to manage authentication across your Next.js application, ensuring that only authenticated users can access protected routes. If you have any more specific questions or need further assistance with setting up Kinde in your project, feel free to ask. We're here to help you make your project a success with Kinde!
zor
zor•3mo ago
Thank you. I've told "As of right now the middleware in the app router does not work when trying to redirect to api/auth/login. This is because of Next.js caching which causes issues during authentication." though. I use Next.js and I've attempted to use middleware before and it didn't work. Are you sure it is working or not? I am confused because I think I've just told yes and no in this conversation, sorry for the confusion. "Regarding your question about redirecting users to the login page directly in a Next.js 14 environment, you're correct in noting the current limitation with middleware due to Next.js caching, which affects the ability to use middleware for redirection to api/auth/login." I guess, it worked. After many reads, I noticed it says for only app router and I guess mine is page router/dashboard/page.tsx So I guess there are no limitation for me right? I can just use Kinde like Clerk, no middleware issues?
Oli - Kinde
Oli - Kinde•3mo ago
Hey @zor, Good to hear your issue was resolved.
So I guess there are no limitation for me right?
Are you asking whether there is limitations on the free plan of Kinde?
zor
zor•3mo ago
No, I asked if I should be worried for any problem in the future in my middleware protecting. I am aware of plans, I checked your pricing page - https://kinde.com/pricing/ Does the app router middleware limitation affect me by any bit? Will I have to consider escaping it somehow in the future?
Oli - Kinde
Oli - Kinde•3mo ago
Hey @zor, While the current app router middleware limitation is something to be aware of, Kinde provides mechanisms to work around this issue effectively. So this won't affect you any bit.
zor
zor•3mo ago
Sorry I think you don't understand my messages, sorry for that confusion. I think my project is page router so I am asking if it affects me by a bit.
Oli - Kinde
Oli - Kinde•3mo ago
Aaah @zor apologies, I thought you were using NextJS App Router. Given your use of Next.js Pages Router and your interest in redirecting users directly to the login page, the limitation regarding middleware in the app router not working when trying to redirect to api/auth/login due to Next.js caching is indeed relevant to your situation. This limitation can affect the straightforward implementation of direct redirection to the login page using middleware. However, there are alternative approaches to achieve the desired user experience without relying on middleware for redirection. One such approach is to use server-side logic to check the authentication status of the user and then perform the redirection. This can be done using the getKindeServerSession method provided by Kinde, as shown in the documentation. Here's a simplified example:
// In your page's getServerSideProps function
import { getKindeServerSession } from "@kinde-oss/kinde-auth-nextjs/server";

export async function getServerSideProps(context) {
const session = getKindeServerSession(context.req, context.res);
const isAuthenticated = await session.isAuthenticated();

if (!isAuthenticated) {
return {
redirect: {
destination: '/api/auth/login', // Redirect to the login page
permanent: false,
},
};
}

return { props: {} }; // Continue with rendering the page for authenticated users
}
// In your page's getServerSideProps function
import { getKindeServerSession } from "@kinde-oss/kinde-auth-nextjs/server";

export async function getServerSideProps(context) {
const session = getKindeServerSession(context.req, context.res);
const isAuthenticated = await session.isAuthenticated();

if (!isAuthenticated) {
return {
redirect: {
destination: '/api/auth/login', // Redirect to the login page
permanent: false,
},
};
}

return { props: {} }; // Continue with rendering the page for authenticated users
}
This method leverages Next.js' getServerSideProps to check if a user is authenticated before the page is rendered. If the user is not authenticated, they are redirected to the login page. This approach works around the middleware limitation and ensures that only authenticated users can access protected routes. It's important to apply this logic to each protected page where you want to enforce authentication. While it requires more effort compared to a global middleware solution, it effectively achieves the goal of protecting routes and redirecting unauthenticated users to the login page. Apologies again for the confusion. If you have further questions or need more detailed guidance on implementing this in your project, feel free to ask!