Next.js + NextAuth.js — Keycloak SSO Integration

Next.js + NextAuth.js — Keycloak SSO Integration

In the previous post, we introduced NextAuth.js and the basic SSO concepts for frontend apps. Now we will integrate Keycloak with NextAuth.js and implement a full login flow in Next.js.


Step 1: Configure Keycloak client

Assuming you already have a Keycloak realm:

  1. Create a client for your Next.js app (e.g., nextjs-app)
  2. Set Access Type to public or confidential depending on your security strategy
  3. Add valid redirect URIs: http://localhost:3000/api/auth/callback/keycloak
  4. Optional: configure roles and mappers

Step 2: Install NextAuth.js in Next.js

npm install next-auth

Create the authentication API route: pages/api/auth/[...nextauth].js


Step 3: Configure Keycloak provider in NextAuth.js



import NextAuth from "next-auth";

import KeycloakProvider from "next-auth/providers/keycloak";

export default NextAuth({

  providers: [

    KeycloakProvider({

      clientId: process.env.KEYCLOAK_CLIENT_ID,

      clientSecret: process.env.KEYCLOAK_CLIENT_SECRET,

      issuer: process.env.KEYCLOAK_ISSUER

    })

  ],

  session: { strategy: "jwt" },

  callbacks: {

    async jwt({ token, account }) {

      if (account) {

        token.accessToken = account.access_token;

        token.idToken = account.id_token;

      }

      return token;

    },

    async session({ session, token }) {

      session.accessToken = token.accessToken;

      session.idToken = token.idToken;

      return session;

    }

  }

});

> Key points:

  • Use issuer from your Keycloak realm URL
  • JWT strategy keeps the session on the client side for API calls
  • Callbacks inject access tokens and ID tokens into the session

Step 4: Protecting pages

Use getServerSideProps or useSession hook for page protection:



import { getSession, useSession } from "next-auth/react";

export default function Profile() {

  const { data: session } = useSession();

  if (!session) return <p>Access Denied</p>;

  return <div>Welcome {session.user.name}!</div>;

}

// Or server-side

export async function getServerSideProps(context) {

  const session = await getSession(context);

  if (!session) {

    return {

      redirect: { destination: "/api/auth/signin", permanent: false }

    };

  }

  return { props: { session } };

}


Step 5: Calling backend APIs with Keycloak token

When calling your Spring Boot backend:



const res = await fetch("/api/protected", {

  headers: { Authorization: `Bearer ${session.accessToken}` }

});

> Your backend validates the JWT as usual (Spring Boot + Keycloak).


Step 6: Debugging tips

  • Redirect loops: check callback URLs in Keycloak and NextAuth.js
  • Roles not applied: verify mappers and session callbacks
  • Token expiration: NextAuth.js can refresh tokens using JWT callbacks
  • Inspect tokens: log session.accessToken for debugging

Next steps

The next post will cover **handling sessions, roles, and protecting routes** in Next.js using NextAuth.js, including role-based page access and API protection.

Part of the Next.js Frontend SSO Series

❤️ Support This Blog


If this post helped you, you can support my writing with a small donation. Thank you for reading.


Comments

Popular posts from this blog

fixed: embedded-redis: Unable to run on macOS Sonoma

Copying MDC Context Map in Web Clients: A Comprehensive Guide

Reset user password for your own Ghost blog