Keycloak and NextJS
Introduction
Only do it once a project so wanted to capture how to this. Thanks to Harsh Bhandari
Keycloak
Create a Client
Awful way to document but here goes
Add Capabilities
Add Redirect
Get The Secret
Create User
Set The Password
NextJS Bit
Setup Auth
Make the nextauth bits
mkdir -p "src/app/api/auth/[...nextauth]" && touch "src/app/api/auth/[...nextauth]/route.ts"
Implement the root.ts
// src/app/api/auth/[...nextauth]/route.ts
import { AuthOptions } from "next-auth";
import KeycloakProvider from "next-auth/providers/keycloak"
export const authOptions: AuthOptions = {
providers: [
KeycloakProvider({
clientId: process.env.KEYCLOAK_CLIENT_ID,
clientSecret: process.env.KEYCLOAK_CLIENT_SECRET,
issuer: process.env.KEYCLOAK_ISSUER
})
]
}
const handler = NextAuth(authOptions);
export { handler as GET, handler as POST
Fix up ProcessEnv
mkdir types && touch types/node-env.d.ts
And
// types/node-env.d.ts
declare namespace NodeJS {
export interface ProcessEnv {
KEYCLOAK_CLIENT_ID: string
KEYCLOAK_CLIENT_SECRET: string
KEYCLOAK_ISSUER: string
}
}
And
touch .env.local
And add
KEYCLOAK_CLIENT_ID="nextjs"
KEYCLOAK_CLIENT_SECRET="<client_secret>"
KEYCLOAK_ISSUER="http://localhost:8080/realms/myrealm"
Login Page
Home Page
// src/app/page.tsx
import { getServerSession } from 'next-auth'
import { authOptions } from './api/auth/[...nextauth]/route'
import Login from '../components/Login'
import Logout from '../components/Logout'
export default async function Home() {
const session = await getServerSession(authOptions)
if (session) {
return <div>
<div>Your name is {session.user?.name}</div>
<div><Logout /> </div>
</div>
}
return (
<div>
<Login />
</div>
)
}
Login Component
// src/components/Login.tsx
"use client"
import { signIn } from "next-auth/react";
export default function Login() {
return <button onClick={() => signIn("keycloak")}>
Signin with keycloak
</button>
}
Logout Component
// src/components/Logout.tsx
"use client"
import { signOut } from "next-auth/react";
export default function Logout() {
return <button onClick={() => signOut()}>
Signout of keycloak
</button>
}