I’m using Keycloak for authentication in my Next.js application and want to protect specific routes, like /contact, so that only authenticated users can access them. I’ve initialized Keycloak in my AuthProvider component, but I’m unsure how to redirect unauthenticated users to the login page when they try to access protected routes.
library used are keycloak-js and zustand
The AuthProvider component acts as a gatekeeper for the app, using Keycloak to manage user authentication. When the component mounts, it sets up a Keycloak instance based on your configuration and checks if the user is logged in.
If the user is authenticated, their profile information is loaded, and the app is updated to reflect their logged-in status. However, if they’re not authenticated and try to access protected routes (like /contact), they’ll be redirected to the Keycloak login page. While this is happening, a loading spinner is displayed to let users know the authentication process is in progress.
Overall, this component ensures that only authenticated users can access certain parts of the app
import Loading from "@/error-pages/Loading";
import Keycloak from "keycloak-js";
import { useKeycloakStore } from "@/hooks/useKeycloak";
import { keycloakConfig } from "@/utils/keycloakConfig";
import { usePathname } from "next/navigation";
import React, { ReactNode, useLayoutEffect, useState } from "react";
export default function AuthProvider({ children }: { children: ReactNode }) {
const path = usePathname();
const [loading, setIsloading] = useState(false);
const { initializeKeycloak, setAuthenticated, setProfile } =
useKeycloakStore();
useLayoutEffect(() => {
const protectedRoutes = ["/contact"];
const keycloakInstance = new Keycloak(keycloakConfig);
initializeKeycloak(keycloakInstance);
// INITIALIZE KEYCLOAK
keycloakInstance
.init({
onLoad: "check-sso",
scope: "offline_access",
})
.then((auth) => {
if (auth) {
keycloakInstance?.loadUserProfile().then((item: any) => {
setProfile(item);
});
setAuthenticated(true);
} else {
// If User is not authenticated
if (!keycloakInstance?.authenticated) {
setIsloading(true);
console.log("❌ Not Authenticated");
// If User is not authenticated and page is protected
if (protectedRoutes.includes(path)) {
console.log("❌ Unauthorize need to login");
// send user to login page
keycloakInstance?.login(); // this keeps my page refreshing or redirect
setIsloading(false);
}
}
}
});
}, [setAuthenticated, path, initializeKeycloak, setProfile]);
if (loading) return <Loading />;
return <>{children}</>;
}
KEYCLOAK CONFIG
export const keycloakConfig = {
url: process.env.NEXT_PUBLIC_KEYCLOAK_URL,
realm: process.env.NEXT_PUBLIC_KEYCLOAK_REALM,
clientId: process.env.NEXT_PUBLIC_KEYCLOAK_CLIENT_ID,
};